// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/screens/user_selection_screen.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
#include "chrome/browser/chromeos/login/lock/screen_locker.h"
#include "chrome/browser/chromeos/login/lock_screen_utils.h"
#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
#include "chrome/browser/chromeos/login/reauth_stats.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/login/ui/views/user_board_view.h"
#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
#include "chrome/browser/chromeos/login/users/default_user_image/default_user_images.h"
#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/ui/ash/login_screen_client.h"
#include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/components/proximity_auth/screenlock_bridge.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_util.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/known_user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"

namespace chromeos {

namespace {

// User dictionary keys.
const char kKeyUsername[] = "username";
const char kKeyDisplayName[] = "displayName";
const char kKeyEmailAddress[] = "emailAddress";
const char kKeyEnterpriseDisplayDomain[] = "enterpriseDisplayDomain";
const char kKeyPublicAccount[] = "publicAccount";
const char kKeyLegacySupervisedUser[] = "legacySupervisedUser";
const char kKeyChildUser[] = "childUser";
const char kKeyDesktopUser[] = "isDesktopUser";
const char kKeySignedIn[] = "signedIn";
const char kKeyCanRemove[] = "canRemove";
const char kKeyIsOwner[] = "isOwner";
const char kKeyIsActiveDirectory[] = "isActiveDirectory";
const char kKeyInitialAuthType[] = "initialAuthType";
const char kKeyMultiProfilesAllowed[] = "isMultiProfilesAllowed";
const char kKeyMultiProfilesPolicy[] = "multiProfilesPolicy";
const char kKeyInitialLocales[] = "initialLocales";
const char kKeyInitialLocale[] = "initialLocale";
const char kKeyInitialMultipleRecommendedLocales[] =
    "initialMultipleRecommendedLocales";
const char kKeyAllowFingerprint[] = "allowFingerprint";

// Max number of users to show.
// Please keep synced with one in signin_userlist_unittest.cc.
const size_t kMaxUsers = 18;

const int kPasswordClearTimeoutSec = 60;

// Returns true if we have enterprise domain information.
// |out_domain|:  Output value of the enterprise domain.
bool GetEnterpriseDomain(std::string* out_domain) {
  policy::BrowserPolicyConnectorChromeOS* policy_connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (policy_connector->IsCloudManaged()) {
    *out_domain = policy_connector->GetEnterpriseDisplayDomain();
    return true;
  }
  return false;
}

// Get locales information of public account user.
// Returns a list of available locales.
// |public_session_recommended_locales|: This can be nullptr if we don't have
// recommended locales.
// |out_selected_locale|: Output value of the initially selected locale.
// |out_multiple_locales|: Output value indicates whether we have multiple
// recommended locales.
std::unique_ptr<base::ListValue> GetPublicSessionLocales(
    const std::vector<std::string>* public_session_recommended_locales,
    std::string* out_selected_locale,
    bool* out_multiple_locales) {
  std::vector<std::string> kEmptyRecommendedLocales;
  const std::vector<std::string>& recommended_locales =
      public_session_recommended_locales ? *public_session_recommended_locales
                                         : kEmptyRecommendedLocales;

  // Construct the list of available locales. This list consists of the
  // recommended locales, followed by all others.
  std::unique_ptr<base::ListValue> available_locales =
      GetUILanguageList(&recommended_locales, std::string());

  // Select the the first recommended locale that is actually available or the
  // current UI locale if none of them are available.
  *out_selected_locale =
      FindMostRelevantLocale(recommended_locales, *available_locales.get(),
                             g_browser_process->GetApplicationLocale());

  *out_multiple_locales = recommended_locales.size() >= 2;
  return available_locales;
}

void AddPublicSessionDetailsToUserDictionaryEntry(
    base::DictionaryValue* user_dict,
    const std::vector<std::string>* public_session_recommended_locales) {
  std::string domain;
  if (GetEnterpriseDomain(&domain))
    user_dict->SetString(kKeyEnterpriseDisplayDomain, domain);

  std::string selected_locale;
  bool has_multiple_locales;
  std::unique_ptr<base::ListValue> available_locales =
      GetPublicSessionLocales(public_session_recommended_locales,
                              &selected_locale, &has_multiple_locales);

  // Set |kKeyInitialLocales| to the list of available locales.
  user_dict->Set(kKeyInitialLocales, std::move(available_locales));

  // Set |kKeyInitialLocale| to the initially selected locale.
  user_dict->SetString(kKeyInitialLocale, selected_locale);

  // Set |kKeyInitialMultipleRecommendedLocales| to indicate whether the list
  // of recommended locales contains at least two entries. This is used to
  // decide whether the public session pod expands to its basic form (for zero
  // or one recommended locales) or the advanced form (two or more recommended
  // locales).
  user_dict->SetBoolean(kKeyInitialMultipleRecommendedLocales,
                        has_multiple_locales);
}

// Determines the initial fingerprint state for the given user.
ash::mojom::FingerprintState GetInitialFingerprintState(
    const user_manager::User* user) {
  // User must be logged in.
  if (!user->is_logged_in())
    return ash::mojom::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;

  // Fingerprint is not registered for this account.
  if (!quick_unlock_storage->fingerprint_storage()->HasRecord())
    return ash::mojom::FingerprintState::UNAVAILABLE;

  // Fingerprint unlock attempts should not be exceeded, as the lock screen has
  // not been displayed yet.
  DCHECK(
      !quick_unlock_storage->fingerprint_storage()->ExceededUnlockAttempts());

  // It has been too long since the last authentication.
  if (!quick_unlock_storage->HasStrongAuth())
    return ash::mojom::FingerprintState::DISABLED_FROM_TIMEOUT;

  // Auth is available.
  if (quick_unlock_storage->IsFingerprintAuthenticationAvailable())
    return ash::mojom::FingerprintState::AVAILABLE;

  // Default to unavailabe.
  return ash::mojom::FingerprintState::UNAVAILABLE;
}

// Returns true if dircrypto migration check should be performed.
bool ShouldCheckNeedDircryptoMigration() {
  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kDisableEncryptionMigration) &&
         arc::IsArcAvailable();
}

// Returns true if the user can run ARC based on the user type.
bool IsUserAllowedForARC(const AccountId& account_id) {
  return user_manager::UserManager::IsInitialized() &&
         arc::IsArcAllowedForUser(
             user_manager::UserManager::Get()->FindUser(account_id));
}

AccountId GetOwnerAccountId() {
  std::string owner_email;
  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner,
                                           &owner_email);
  const AccountId owner = user_manager::known_user::GetAccountId(
      owner_email, std::string() /* id */, AccountType::UNKNOWN);
  return owner;
}

bool IsEnterpriseManaged() {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  return connector->IsEnterpriseManaged();
}

bool IsSigninToAdd() {
  return LoginDisplayHost::default_host() &&
         user_manager::UserManager::Get()->IsUserLoggedIn();
}

bool CanRemoveUser(const user_manager::User* user) {
  const bool is_single_user =
      user_manager::UserManager::Get()->GetUsers().size() == 1;

  // Single user check here is necessary because owner info might not be
  // available when running into login screen on first boot.
  // See http://crosbug.com/12723
  if (is_single_user && !IsEnterpriseManaged())
    return false;
  if (!user->GetAccountId().is_valid())
    return false;
  if (user->GetAccountId() == GetOwnerAccountId())
    return false;
  if (user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT ||
      user->is_logged_in() || IsSigninToAdd())
    return false;

  return true;
}

void GetMultiProfilePolicy(const user_manager::User* user,
                           bool* out_is_allowed,
                           ash::mojom::MultiProfileUserBehavior* out_policy) {
  const std::string& user_id = user->GetAccountId().GetUserEmail();
  MultiProfileUserController* multi_profile_user_controller =
      ChromeUserManager::Get()->GetMultiProfileUserController();
  MultiProfileUserController::UserAllowedInSessionReason is_user_allowed_reason;
  *out_is_allowed = multi_profile_user_controller->IsUserAllowedInSession(
      user_id, &is_user_allowed_reason);

  std::string policy;
  if (is_user_allowed_reason ==
      MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY) {
    policy = MultiProfileUserController::kBehaviorOwnerPrimaryOnly;
  } else {
    policy = multi_profile_user_controller->GetCachedValue(user_id);
  }
  *out_policy = MultiProfileUserController::UserBehaviorStringToEnum(policy);
}

}  // namespace

// Helper class to call cryptohome to check whether a user needs dircrypto
// migration. The check results are cached to limit calls to cryptohome.
class UserSelectionScreen::DircryptoMigrationChecker {
 public:
  explicit DircryptoMigrationChecker(UserSelectionScreen* owner)
      : owner_(owner), weak_ptr_factory_(this) {}
  ~DircryptoMigrationChecker() = default;

  // Start to check whether the given user needs dircrypto migration.
  void Check(const AccountId& account_id) {
    focused_user_ = account_id;

    // If the user may be enterprise-managed, don't display the banner, because
    // migration may be blocked by user policy (and user policy is not available
    // at this time yet).
    if (!policy::BrowserPolicyConnector::IsNonEnterpriseUser(
            account_id.GetUserEmail())) {
      UpdateUI(account_id, false);
      return;
    }

    auto it = needs_dircrypto_migration_cache_.find(account_id);
    if (it != needs_dircrypto_migration_cache_.end()) {
      UpdateUI(account_id, it->second);
      return;
    }

    // No banner if the user is not allowed for ARC.
    if (!IsUserAllowedForARC(account_id)) {
      UpdateUI(account_id, false);
      return;
    }

    DBusThreadManager::Get()
        ->GetCryptohomeClient()
        ->WaitForServiceToBeAvailable(
            base::Bind(&DircryptoMigrationChecker::RunCryptohomeCheck,
                       weak_ptr_factory_.GetWeakPtr(), account_id));
  }

 private:
  // WaitForServiceToBeAvailable callback to invoke NeedsDircryptoMigration when
  // cryptohome service is available.
  void RunCryptohomeCheck(const AccountId& account_id, bool service_is_ready) {
    if (!service_is_ready) {
      LOG(ERROR) << "Cryptohome is not available.";
      return;
    }

    DBusThreadManager::Get()->GetCryptohomeClient()->NeedsDircryptoMigration(
        cryptohome::CreateAccountIdentifierFromAccountId(account_id),
        base::BindOnce(&DircryptoMigrationChecker::
                           OnCryptohomeNeedsDircryptoMigrationCallback,
                       weak_ptr_factory_.GetWeakPtr(), account_id));
  }

  // Callback invoked when NeedsDircryptoMigration call is finished.
  void OnCryptohomeNeedsDircryptoMigrationCallback(
      const AccountId& account_id,
      base::Optional<bool> needs_migration) {
    if (!needs_migration.has_value()) {
      LOG(ERROR) << "Failed to call cryptohome NeedsDircryptoMigration.";
      // Hide the banner to avoid confusion in http://crbug.com/721948.
      // Cache is not updated so that cryptohome call will still be attempted.
      UpdateUI(account_id, false);
      return;
    }

    needs_dircrypto_migration_cache_[account_id] = needs_migration.value();
    UpdateUI(account_id, needs_migration.value());
  }

  // Update UI for the given user when the check result is available.
  void UpdateUI(const AccountId& account_id, bool needs_migration) {
    // Bail if the user is not the currently focused.
    if (account_id != focused_user_)
      return;

    owner_->ShowBannerMessage(
        needs_migration ? l10n_util::GetStringUTF16(
                              IDS_LOGIN_NEEDS_DIRCRYPTO_MIGRATION_BANNER)
                        : base::string16(),
        needs_migration);
  }

  UserSelectionScreen* const owner_;
  AccountId focused_user_ = EmptyAccountId();

  // Cached result of NeedsDircryptoMigration cryptohome check. Key is the
  // account id of users. True value means the user needs dircrypto migration
  // and false means dircrypto migration is done.
  std::map<AccountId, bool> needs_dircrypto_migration_cache_;

  base::WeakPtrFactory<DircryptoMigrationChecker> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(DircryptoMigrationChecker);
};

UserSelectionScreen::UserSelectionScreen(const std::string& display_type)
    : BaseScreen(nullptr, OobeScreen::SCREEN_USER_SELECTION),
      display_type_(display_type),
      weak_factory_(this) {}

UserSelectionScreen::~UserSelectionScreen() {
  proximity_auth::ScreenlockBridge::Get()->SetLockHandler(nullptr);
  ui::UserActivityDetector* activity_detector = ui::UserActivityDetector::Get();
  if (activity_detector && activity_detector->HasObserver(this))
    activity_detector->RemoveObserver(this);
}

void UserSelectionScreen::InitEasyUnlock() {
  proximity_auth::ScreenlockBridge::Get()->SetLockHandler(this);
}

// static
void UserSelectionScreen::FillUserDictionary(
    const user_manager::User* user,
    bool is_owner,
    bool is_signin_to_add,
    proximity_auth::mojom::AuthType auth_type,
    const std::vector<std::string>* public_session_recommended_locales,
    base::DictionaryValue* user_dict) {
  const bool is_public_session =
      user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
  const bool is_legacy_supervised_user =
      user->GetType() == user_manager::USER_TYPE_SUPERVISED;
  const bool is_child_user = user->GetType() == user_manager::USER_TYPE_CHILD;

  user_dict->SetString(kKeyUsername, user->GetAccountId().Serialize());
  user_dict->SetString(kKeyEmailAddress, user->display_email());
  user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
  user_dict->SetBoolean(kKeyPublicAccount, is_public_session);
  user_dict->SetBoolean(kKeyLegacySupervisedUser, is_legacy_supervised_user);
  user_dict->SetBoolean(kKeyChildUser, is_child_user);
  user_dict->SetBoolean(kKeyDesktopUser, false);
  user_dict->SetInteger(kKeyInitialAuthType, static_cast<int>(auth_type));
  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);

  FillMultiProfileUserPrefs(user, user_dict, is_signin_to_add);

  if (is_public_session) {
    AddPublicSessionDetailsToUserDictionaryEntry(
        user_dict, public_session_recommended_locales);
  }
}

// static
void UserSelectionScreen::FillMultiProfileUserPrefs(
    const user_manager::User* user,
    base::DictionaryValue* user_dict,
    bool is_signin_to_add) {
  if (!is_signin_to_add) {
    user_dict->SetBoolean(kKeyMultiProfilesAllowed, true);
    return;
  }

  bool is_user_allowed;
  ash::mojom::MultiProfileUserBehavior policy;
  GetMultiProfilePolicy(user, &is_user_allowed, &policy);
  user_dict->SetBoolean(kKeyMultiProfilesAllowed, is_user_allowed);
  user_dict->SetInteger(kKeyMultiProfilesPolicy, static_cast<int>(policy));
}

// static
bool UserSelectionScreen::ShouldForceOnlineSignIn(
    const user_manager::User* user) {
  // Public sessions are always allowed to log in offline.
  // Supervised users are always allowed to log in offline.
  // For all other users, force online sign in if:
  // * The flag to force online sign-in is set for the user.
  // * The user's OAuth token is invalid or unknown.
  if (user->is_logged_in())
    return false;

  const user_manager::User::OAuthTokenStatus token_status =
      user->oauth_token_status();
  const bool is_supervised_user =
      user->GetType() == user_manager::USER_TYPE_SUPERVISED;
  const bool is_public_session =
      user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
  const bool has_gaia_account = user->HasGaiaAccount();

  if (is_supervised_user)
    return false;

  if (is_public_session)
    return false;

  // At this point the reason for invalid token should be already set. If not,
  // this might be a leftover from an old version.
  if (has_gaia_account &&
      token_status == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID)
    RecordReauthReason(user->GetAccountId(), ReauthReason::OTHER);

  // We need to force an online signin if the user is marked as requiring it,
  // or if the user's session never completed initialization (still need to
  // check for policy/management state) or if there's an invalid OAUTH token
  // that needs to be refreshed.
  return user->force_online_signin() || !user->profile_ever_initialized() ||
         (has_gaia_account &&
          (token_status == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID ||
           token_status == user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN));
}

// 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(
        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& rb = ui::ResourceBundle::GetSharedInstance();
    base::StringPiece avatar_data =
        rb.GetRawDataResourceForScale(resource_id, rb.GetMaxScaleFactor());
    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()) {
    int resource_id = chromeos::default_user_image::kDefaultImageResourceIDs
        [user->image_index()];
    load_image_from_resource(resource_id);
  } else if (user->image_is_stub()) {
    load_image_from_resource(IDR_LOGIN_DEFAULT_USER);
  }

  return avatar;
}

void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) {
  handler_ = handler;

  if (handler_) {
    // Forcibly refresh all of the user images, as the |handler_| instance may
    // have been reused.
    for (user_manager::User* user : users_)
      handler_->OnUserImageChanged(*user);
  }
}

void UserSelectionScreen::SetView(UserBoardView* view) {
  view_ = view;
}

void UserSelectionScreen::Init(const user_manager::UserList& users) {
  users_ = users;

  ui::UserActivityDetector* activity_detector = ui::UserActivityDetector::Get();
  if (activity_detector && !activity_detector->HasObserver(this))
    activity_detector->AddObserver(this);
}

void UserSelectionScreen::OnBeforeUserRemoved(const AccountId& account_id) {
  for (auto it = users_.cbegin(); it != users_.cend(); ++it) {
    if ((*it)->GetAccountId() == account_id) {
      users_.erase(it);
      break;
    }
  }
}

void UserSelectionScreen::OnUserRemoved(const AccountId& account_id) {
  if (!handler_)
    return;
  handler_->OnUserRemoved(account_id, users_.empty());
}

void UserSelectionScreen::OnUserImageChanged(const user_manager::User& user) {
  if (!handler_)
    return;
  handler_->OnUserImageChanged(user);
  // TODO(antrim) : updateUserImage(user.email())
}

void UserSelectionScreen::OnPasswordClearTimerExpired() {
  if (handler_)
    handler_->ClearUserPodPassword();
}

void UserSelectionScreen::OnUserActivity(const ui::Event* event) {
  if (!password_clear_timer_.IsRunning()) {
    password_clear_timer_.Start(
        FROM_HERE, base::TimeDelta::FromSeconds(kPasswordClearTimeoutSec), this,
        &UserSelectionScreen::OnPasswordClearTimerExpired);
  }
  password_clear_timer_.Reset();
}

// static
const user_manager::UserList UserSelectionScreen::PrepareUserListForSending(
    const user_manager::UserList& users,
    const AccountId& owner,
    bool is_signin_to_add) {
  user_manager::UserList users_to_send;
  bool has_owner = owner.is_valid();
  size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers;
  size_t non_owner_count = 0;

  for (user_manager::User* user : users) {
    bool is_owner = user->GetAccountId() == owner;
    bool is_public_account =
        user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;

    if ((is_public_account && !is_signin_to_add) || is_owner ||
        (!is_public_account && non_owner_count < max_non_owner_users)) {
      if (!is_owner)
        ++non_owner_count;
      if (is_owner && users_to_send.size() > kMaxUsers) {
        // Owner is always in the list.
        users_to_send.insert(users_to_send.begin() + (kMaxUsers - 1), user);
        while (users_to_send.size() > kMaxUsers)
          users_to_send.erase(users_to_send.begin() + kMaxUsers);
      } else if (users_to_send.size() < kMaxUsers) {
        users_to_send.push_back(user);
      }
    }
  }
  return users_to_send;
}

void UserSelectionScreen::SendUserList() {
  std::unique_ptr<base::ListValue> users_list =
      UpdateAndReturnUserListForWebUI();
  handler_->LoadUsers(users_to_send_, *users_list);
}

void UserSelectionScreen::HandleGetUsers() {
  SendUserList();
}

void UserSelectionScreen::CheckUserStatus(const AccountId& account_id) {
  // No checks on lock screen.
  if (ScreenLocker::default_screen_locker())
    return;

  if (!token_handle_util_.get()) {
    token_handle_util_.reset(new TokenHandleUtil());
  }

  if (token_handle_util_->HasToken(account_id)) {
    token_handle_util_->CheckToken(
        account_id, base::Bind(&UserSelectionScreen::OnUserStatusChecked,
                               weak_factory_.GetWeakPtr()));
  }

  // Run dircrypto migration check only on the login screen when necessary.
  if (display_type_ == OobeUI::kLoginDisplay &&
      ShouldCheckNeedDircryptoMigration()) {
    if (!dircrypto_migration_checker_) {
      dircrypto_migration_checker_ =
          std::make_unique<DircryptoMigrationChecker>(this);
    }
    dircrypto_migration_checker_->Check(account_id);
  }
}

void UserSelectionScreen::OnUserStatusChecked(
    const AccountId& account_id,
    TokenHandleUtil::TokenHandleStatus status) {
  if (status == TokenHandleUtil::INVALID) {
    RecordReauthReason(account_id, ReauthReason::INVALID_TOKEN_HANDLE);
    token_handle_util_->MarkHandleInvalid(account_id);
    SetAuthType(account_id, proximity_auth::mojom::AuthType::ONLINE_SIGN_IN,
                base::string16());
  }
}

// EasyUnlock stuff

void UserSelectionScreen::SetAuthType(const AccountId& account_id,
                                      proximity_auth::mojom::AuthType auth_type,
                                      const base::string16& initial_value) {
  if (GetAuthType(account_id) ==
      proximity_auth::mojom::AuthType::FORCE_OFFLINE_PASSWORD) {
    return;
  }

  DCHECK(GetAuthType(account_id) !=
             proximity_auth::mojom::AuthType::FORCE_OFFLINE_PASSWORD ||
         auth_type == proximity_auth::mojom::AuthType::FORCE_OFFLINE_PASSWORD);
  user_auth_type_map_[account_id] = auth_type;
  view_->SetAuthType(account_id, auth_type, initial_value);
}

proximity_auth::mojom::AuthType UserSelectionScreen::GetAuthType(
    const AccountId& account_id) const {
  if (user_auth_type_map_.find(account_id) == user_auth_type_map_.end())
    return proximity_auth::mojom::AuthType::OFFLINE_PASSWORD;
  return user_auth_type_map_.find(account_id)->second;
}

proximity_auth::ScreenlockBridge::LockHandler::ScreenType
UserSelectionScreen::GetScreenType() const {
  if (display_type_ == OobeUI::kLockDisplay)
    return LOCK_SCREEN;

  if (display_type_ == OobeUI::kLoginDisplay)
    return SIGNIN_SCREEN;

  return OTHER_SCREEN;
}

void UserSelectionScreen::ShowBannerMessage(const base::string16& message,
                                            bool is_warning) {
  view_->ShowBannerMessage(message, is_warning);
}

void UserSelectionScreen::ShowUserPodCustomIcon(
    const AccountId& account_id,
    const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions&
        icon_options) {
  view_->ShowUserPodCustomIcon(account_id, icon_options);
}

void UserSelectionScreen::HideUserPodCustomIcon(const AccountId& account_id) {
  view_->HideUserPodCustomIcon(account_id);
}

void UserSelectionScreen::EnableInput() {
  // If Easy Unlock fails to unlock the screen, re-enable the password input.
  // This is only necessary on the lock screen, because the error handling for
  // the sign-in screen uses a different code path.
  if (ScreenLocker::default_screen_locker())
    ScreenLocker::default_screen_locker()->EnableInput();
}

void UserSelectionScreen::Unlock(const AccountId& account_id) {
  DCHECK_EQ(GetScreenType(), LOCK_SCREEN);
  ScreenLocker::Hide();
}

void UserSelectionScreen::AttemptEasySignin(const AccountId& account_id,
                                            const std::string& secret,
                                            const std::string& key_label) {
  DCHECK_EQ(GetScreenType(), SIGNIN_SCREEN);

  const user_manager::User* const user =
      user_manager::UserManager::Get()->FindUser(account_id);
  DCHECK(user);
  UserContext user_context(*user);
  user_context.SetAuthFlow(UserContext::AUTH_FLOW_EASY_UNLOCK);
  user_context.SetKey(Key(secret));
  user_context.GetKey()->SetLabel(key_label);

  // LoginDisplayHost does not exist in views-based lock screen.
  if (LoginDisplayHost::default_host()) {
    LoginDisplayHost::default_host()->GetLoginDisplay()->delegate()->Login(
        user_context, SigninSpecifics());
  }
}

void UserSelectionScreen::Show() {}

void UserSelectionScreen::Hide() {}

void UserSelectionScreen::HardLockPod(const AccountId& account_id) {
  view_->SetAuthType(account_id,
                     proximity_auth::mojom::AuthType::OFFLINE_PASSWORD,
                     base::string16());
  EasyUnlockService* service = GetEasyUnlockServiceForUser(account_id);
  if (!service)
    return;
  service->SetHardlockState(EasyUnlockScreenlockStateHandler::USER_HARDLOCK);
}

void UserSelectionScreen::AttemptEasyUnlock(const AccountId& account_id) {
  EasyUnlockService* service = GetEasyUnlockServiceForUser(account_id);
  if (!service)
    return;
  service->AttemptAuth(account_id);
}

std::unique_ptr<base::ListValue>
UserSelectionScreen::UpdateAndReturnUserListForWebUI() {
  std::unique_ptr<base::ListValue> users_list =
      std::make_unique<base::ListValue>();

  // TODO(nkostylev): Move to a separate method in UserManager.
  // http://crbug.com/230852
  const AccountId owner = GetOwnerAccountId();
  const bool is_signin_to_add = IsSigninToAdd();

  users_to_send_ = PrepareUserListForSending(users_, owner, is_signin_to_add);

  user_auth_type_map_.clear();

  for (const user_manager::User* user : users_to_send_) {
    const AccountId& account_id = user->GetAccountId();
    bool is_owner = (account_id == owner);
    const bool is_public_account =
        user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
    const proximity_auth::mojom::AuthType initial_auth_type =
        is_public_account
            ? proximity_auth::mojom::AuthType::EXPAND_THEN_USER_CLICK
            : (ShouldForceOnlineSignIn(user)
                   ? proximity_auth::mojom::AuthType::ONLINE_SIGN_IN
                   : proximity_auth::mojom::AuthType::OFFLINE_PASSWORD);
    user_auth_type_map_[account_id] = initial_auth_type;

    auto user_dict = std::make_unique<base::DictionaryValue>();
    const std::vector<std::string>* public_session_recommended_locales =
        public_session_recommended_locales_.find(account_id) ==
                public_session_recommended_locales_.end()
            ? nullptr
            : &public_session_recommended_locales_[account_id];
    FillUserDictionary(user, is_owner, is_signin_to_add, initial_auth_type,
                       public_session_recommended_locales, user_dict.get());
    user_dict->SetBoolean(kKeyCanRemove, CanRemoveUser(user));
    users_list->Append(std::move(user_dict));
  }

  return users_list;
}

std::vector<ash::mojom::LoginUserInfoPtr>
UserSelectionScreen::UpdateAndReturnUserListForMojo() {
  std::vector<ash::mojom::LoginUserInfoPtr> user_info_list;

  const AccountId owner = GetOwnerAccountId();
  const bool is_signin_to_add = IsSigninToAdd();
  users_to_send_ = PrepareUserListForSending(users_, owner, is_signin_to_add);

  user_auth_type_map_.clear();

  for (const user_manager::User* user : users_to_send_) {
    const AccountId& account_id = user->GetAccountId();
    bool is_owner = owner == account_id;
    const bool is_public_account =
        user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
    const proximity_auth::mojom::AuthType initial_auth_type =
        is_public_account
            ? proximity_auth::mojom::AuthType::EXPAND_THEN_USER_CLICK
            : (ShouldForceOnlineSignIn(user)
                   ? proximity_auth::mojom::AuthType::ONLINE_SIGN_IN
                   : 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 =
        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);

    // Fill multi-profile data.
    if (!is_signin_to_add) {
      user_info->is_multiprofile_allowed = true;
    } else {
      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;
      if (GetEnterpriseDomain(&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) ==
                  public_session_recommended_locales_.end()
              ? nullptr
              : &public_session_recommended_locales_[account_id];
      std::string selected_locale;
      bool has_multiple_locales;
      std::unique_ptr<base::ListValue> available_locales =
          GetPublicSessionLocales(public_session_recommended_locales,
                                  &selected_locale, &has_multiple_locales);
      DCHECK(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;
      // Do not show expanded view when in demo mode.
      user_info->public_account_info->show_expanded_view =
          !DemoSession::IsDeviceInDemoMode();
    }

    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);
    }

    user_info_list.push_back(std::move(user_info));
  }

  return user_info_list;
}

void UserSelectionScreen::SetUsersLoaded(bool loaded) {
  users_loaded_ = loaded;
}

EasyUnlockService* UserSelectionScreen::GetEasyUnlockServiceForUser(
    const AccountId& account_id) const {
  if (GetScreenType() == OTHER_SCREEN)
    return nullptr;

  const user_manager::User* unlock_user = nullptr;
  for (const user_manager::User* user : users_) {
    if (user->GetAccountId() == account_id) {
      unlock_user = user;
      break;
    }
  }
  if (!unlock_user)
    return nullptr;

  ProfileHelper* profile_helper = ProfileHelper::Get();
  Profile* profile = profile_helper->GetProfileByUser(unlock_user);

  // The user profile should exist if and only if this is the lock screen.
  DCHECK_EQ(!!profile, GetScreenType() == LOCK_SCREEN);

  if (!profile)
    profile = profile_helper->GetSigninProfile();

  return EasyUnlockService::Get(profile);
}

}  // namespace chromeos
