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

#include "chrome/browser/chromeos/login/existing_user_controller.h"

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/accessibility/accessibility_events.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/login_display_host.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/policy/core/common/policy_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/user_metrics.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "grit/generated_resources.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/accessibility/accessibility_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/widget/widget.h"

namespace chromeos {

namespace {

// URL for account creation.
const char kCreateAccountURL[] =
    "https://accounts.google.com/NewAccount?service=mail";

// ChromeVox tutorial URL (used in place of "getting started" url when
// accessibility is enabled).
const char kChromeVoxTutorialURLPattern[] =
    "http://www.chromevox.com/tutorial/index.html?lang=%s";

// Delay for transferring the auth cache to the system profile.
const long int kAuthCacheTransferDelayMs = 2000;

// Delay for restarting the ui if safe-mode login has failed.
const long int kSafeModeRestartUiDelayMs = 30000;

// Makes a call to the policy subsystem to reload the policy when we detect
// authentication change.
void RefreshPoliciesOnUIThread() {
  if (g_browser_process->policy_service())
    g_browser_process->policy_service()->RefreshPolicies(base::Closure());
}

// Copies any authentication details that were entered in the login profile in
// the mail profile to make sure all subsystems of Chrome can access the network
// with the provided authentication which are possibly for a proxy server.
void TransferContextAuthenticationsOnIOThread(
    net::URLRequestContextGetter* default_profile_context_getter,
    net::URLRequestContextGetter* browser_process_context_getter) {
  net::HttpAuthCache* new_cache =
      browser_process_context_getter->GetURLRequestContext()->
      http_transaction_factory()->GetSession()->http_auth_cache();
  net::HttpAuthCache* old_cache =
      default_profile_context_getter->GetURLRequestContext()->
      http_transaction_factory()->GetSession()->http_auth_cache();
  new_cache->UpdateAllFrom(*old_cache);
  VLOG(1) << "Main request context populated with authentication data.";
  // Last but not least tell the policy subsystem to refresh now as it might
  // have been stuck until now too.
  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
                                   base::Bind(&RefreshPoliciesOnUIThread));
}

}  // namespace

// static
ExistingUserController* ExistingUserController::current_controller_ = NULL;

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, public:

ExistingUserController::ExistingUserController(LoginDisplayHost* host)
    : login_status_consumer_(NULL),
      host_(host),
      login_display_(host_->CreateLoginDisplay(this)),
      num_login_attempts_(0),
      cros_settings_(CrosSettings::Get()),
      weak_factory_(this),
      offline_failed_(false),
      is_login_in_progress_(false),
      password_changed_(false),
      do_auto_enrollment_(false),
      signin_screen_ready_(false),
      network_state_helper_(new login::NetworkStateHelper) {
  DCHECK(current_controller_ == NULL);
  current_controller_ = this;

  registrar_.Add(this,
                 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
                 content::NotificationService::AllSources());
  registrar_.Add(this,
                 chrome::NOTIFICATION_USER_LIST_CHANGED,
                 content::NotificationService::AllSources());
  registrar_.Add(this,
                 chrome::NOTIFICATION_AUTH_SUPPLIED,
                 content::NotificationService::AllSources());
  registrar_.Add(this,
                 chrome::NOTIFICATION_SESSION_STARTED,
                 content::NotificationService::AllSources());
  show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
      kAccountsPrefShowUserNamesOnSignIn,
      base::Bind(&ExistingUserController::DeviceSettingsChanged,
                 base::Unretained(this)));
  allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
      kAccountsPrefAllowNewUser,
      base::Bind(&ExistingUserController::DeviceSettingsChanged,
                 base::Unretained(this)));
  allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
      kAccountsPrefAllowGuest,
      base::Bind(&ExistingUserController::DeviceSettingsChanged,
                 base::Unretained(this)));
  users_subscription_ = cros_settings_->AddSettingsObserver(
      kAccountsPrefUsers,
      base::Bind(&ExistingUserController::DeviceSettingsChanged,
                 base::Unretained(this)));
  local_account_auto_login_id_subscription_ =
      cros_settings_->AddSettingsObserver(
          kAccountsPrefDeviceLocalAccountAutoLoginId,
          base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
                     base::Unretained(this)));
  local_account_auto_login_delay_subscription_ =
      cros_settings_->AddSettingsObserver(
          kAccountsPrefDeviceLocalAccountAutoLoginDelay,
          base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
                     base::Unretained(this)));
}

void ExistingUserController::Init(const UserList& users) {
  time_init_ = base::Time::Now();
  UpdateLoginDisplay(users);
  ConfigurePublicSessionAutoLogin();

  DBusThreadManager::Get()->GetSessionManagerClient()->EmitLoginPromptReady();
}

void ExistingUserController::UpdateLoginDisplay(const UserList& users) {
  bool show_users_on_signin;
  UserList filtered_users;

  cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
                             &show_users_on_signin);
  if (show_users_on_signin) {
    for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
      // TODO(xiyuan): Clean user profile whose email is not in whitelist.
      bool meets_locally_managed_requirements =
          (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED ||
          UserManager::Get()->AreLocallyManagedUsersAllowed();
      bool meets_whitelist_requirements =
          LoginUtils::IsWhitelisted((*it)->email()) ||
          (*it)->GetType() != User::USER_TYPE_REGULAR;
      if (meets_locally_managed_requirements && meets_whitelist_requirements) {
        filtered_users.push_back(*it);
      }
    }
  }

  // If no user pods are visible, fallback to single new user pod which will
  // have guest session link.
  bool show_guest;
  cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
  bool show_users;
  cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_users);
  show_guest &= !filtered_users.empty();
  bool show_new_user = true;
  login_display_->set_parent_window(GetNativeWindow());
  login_display_->Init(filtered_users, show_guest, show_users, show_new_user);
  host_->OnPreferencesChanged();
}

void ExistingUserController::DoAutoEnrollment() {
  do_auto_enrollment_ = true;
}

void ExistingUserController::ResumeLogin() {
  // This means the user signed-in, then auto-enrollment used his credentials
  // to enroll and succeeded.
  resume_login_callback_.Run();
  resume_login_callback_.Reset();
}

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, content::NotificationObserver implementation:
//

void ExistingUserController::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (type == chrome::NOTIFICATION_SESSION_STARTED) {
    // Stop listening to any notification once session has started.
    // Sign in screen objects are marked for deletion with DeleteSoon so
    // make sure no object would be used after session has started.
    // http://crbug.com/125276
    registrar_.RemoveAll();
    return;
  }
  if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
    DeviceSettingsChanged();
    return;
  }
  if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
    // Possibly the user has authenticated against a proxy server and we might
    // need the credentials for enrollment and other system requests from the
    // main |g_browser_process| request context (see bug
    // http://crosbug.com/24861). So we transfer any credentials to the global
    // request context here.
    // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
    // just after the UI is closed but before the new credentials were stored
    // in the profile. Therefore we have to give it some time to make sure it
    // has been updated before we copy it.
    VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
    scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
        g_browser_process->system_request_context();
    Profile* signin_profile = ProfileHelper::GetSigninProfile();
    scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
        signin_profile->GetRequestContext();
    DCHECK(browser_process_context_getter.get());
    DCHECK(signin_profile_context_getter.get());
    content::BrowserThread::PostDelayedTask(
        content::BrowserThread::IO, FROM_HERE,
        base::Bind(&TransferContextAuthenticationsOnIOThread,
                   signin_profile_context_getter,
                   browser_process_context_getter),
        base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
  }
  if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED)
    return;
  login_display_->OnUserImageChanged(*content::Details<User>(details).ptr());
}

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, private:

ExistingUserController::~ExistingUserController() {
  LoginUtils::Get()->DelegateDeleted(this);

  if (current_controller_ == this) {
    current_controller_ = NULL;
  } else {
    NOTREACHED() << "More than one controller are alive.";
  }
  DCHECK(login_display_.get());
}

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, LoginDisplay::Delegate implementation:
//

void ExistingUserController::CancelPasswordChangedFlow() {
  login_performer_.reset(NULL);
  login_display_->SetUIEnabled(true);
  StartPublicSessionAutoLoginTimer();
}

void ExistingUserController::CreateAccount() {
  content::RecordAction(content::UserMetricsAction("Login.CreateAccount"));
  guest_mode_url_ =
      google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL));
  LoginAsGuest();
}

void ExistingUserController::CompleteLogin(const UserContext& user_context) {
  login_display_->set_signin_completed(true);
  if (!host_) {
    // Complete login event was generated already from UI. Ignore notification.
    return;
  }

  // Stop the auto-login timer when attempting login.
  StopPublicSessionAutoLoginTimer();

  // Disable UI while loading user profile.
  login_display_->SetUIEnabled(false);

  if (!time_init_.is_null()) {
    base::TimeDelta delta = base::Time::Now() - time_init_;
    UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
    time_init_ = base::Time();  // Reset to null.
  }

  host_->OnCompleteLogin();

  // Do an ownership check now to avoid auto-enrolling if the device has
  // already been owned.
  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
      base::Bind(&ExistingUserController::CompleteLoginInternal,
                 weak_factory_.GetWeakPtr(),
                 user_context));
}

void ExistingUserController::CompleteLoginInternal(
    const UserContext& user_context,
    DeviceSettingsService::OwnershipStatus ownership_status) {
  // Auto-enrollment must have made a decision by now. It's too late to enroll
  // if the protocol isn't done at this point.
  if (do_auto_enrollment_ &&
      ownership_status == DeviceSettingsService::OWNERSHIP_NONE) {
    VLOG(1) << "Forcing auto-enrollment before completing login";
    // The only way to get out of the enrollment screen from now on is to either
    // complete enrollment, or opt-out of it. So this controller shouldn't force
    // enrollment again if it is reused for another sign-in.
    do_auto_enrollment_ = false;
    auto_enrollment_username_ = user_context.username;
    resume_login_callback_ = base::Bind(
        &ExistingUserController::PerformLogin,
        weak_factory_.GetWeakPtr(),
        user_context, LoginPerformer::AUTH_MODE_EXTENSION);
    ShowEnrollmentScreen(true, user_context.username);
    // Enable UI for the enrollment screen. SetUIEnabled(true) will post a
    // request to show the sign-in screen again when invoked at the sign-in
    // screen; invoke SetUIEnabled() after navigating to the enrollment screen.
    login_display_->SetUIEnabled(true);
  } else {
    PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
  }
}

base::string16 ExistingUserController::GetConnectedNetworkName() {
  return network_state_helper_->GetCurrentNetworkName();
}

bool ExistingUserController::IsSigninInProgress() const {
  return is_login_in_progress_;
}

void ExistingUserController::Login(const UserContext& user_context) {
  if ((user_context.username.empty() || user_context.password.empty()) &&
      user_context.auth_code.empty())
    return;

  // Stop the auto-login timer when attempting login.
  StopPublicSessionAutoLoginTimer();

  // Disable clicking on other windows.
  login_display_->SetUIEnabled(false);

  BootTimesLoader::Get()->RecordLoginAttempted();

  if (last_login_attempt_username_ != user_context.username) {
    last_login_attempt_username_ = user_context.username;
    num_login_attempts_ = 0;
    // Also reset state variables, which are used to determine password change.
    offline_failed_ = false;
    online_succeeded_for_.clear();
  }
  num_login_attempts_++;
  PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
}

void ExistingUserController::PerformLogin(
    const UserContext& user_context,
    LoginPerformer::AuthorizationMode auth_mode) {
  UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
      set_host(host_);

  // Disable UI while loading user profile.
  login_display_->SetUIEnabled(false);

  // Use the same LoginPerformer for subsequent login as it has state
  // such as Authenticator instance.
  if (!login_performer_.get() || num_login_attempts_ <= 1) {
    LoginPerformer::Delegate* delegate = this;
    if (login_performer_delegate_.get())
      delegate = login_performer_delegate_.get();
    // Only one instance of LoginPerformer should exist at a time.
    login_performer_.reset(NULL);
    login_performer_.reset(new LoginPerformer(delegate));
  }

  is_login_in_progress_ = true;
  if (gaia::ExtractDomainName(user_context.username) ==
          UserManager::kLocallyManagedUserDomain) {
    login_performer_->LoginAsLocallyManagedUser(
        UserContext(user_context.username,
                    user_context.password,
                    std::string()));  // auth_code
  } else {
    login_performer_->PerformLogin(user_context, auth_mode);
  }
  SendAccessibilityAlert(
      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
}

void ExistingUserController::LoginAsRetailModeUser() {
  // Stop the auto-login timer when attempting login.
  StopPublicSessionAutoLoginTimer();

  // Disable clicking on other windows.
  login_display_->SetUIEnabled(false);
  // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
  // the enterprise policy wiring is done for retail mode.

  // Only one instance of LoginPerformer should exist at a time.
  login_performer_.reset(NULL);
  login_performer_.reset(new LoginPerformer(this));
  is_login_in_progress_ = true;
  login_performer_->LoginRetailMode();
  SendAccessibilityAlert(
      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
}

void ExistingUserController::LoginAsGuest() {
  if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
    return;

  // Stop the auto-login timer when attempting login.
  StopPublicSessionAutoLoginTimer();

  // Disable clicking on other windows.
  login_display_->SetUIEnabled(false);

  CrosSettingsProvider::TrustedStatus status =
      cros_settings_->PrepareTrustedValues(
          base::Bind(&ExistingUserController::LoginAsGuest,
                     weak_factory_.GetWeakPtr()));
  // Must not proceed without signature verification.
  if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
                              HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    // Reenable clicking on other windows and status area.
    login_display_->SetUIEnabled(true);
    StartPublicSessionAutoLoginTimer();
    display_email_.clear();
    return;
  } else if (status != CrosSettingsProvider::TRUSTED) {
    // Value of AllowNewUser setting is still not verified.
    // Another attempt will be invoked after verification completion.
    return;
  }

  bool allow_guest;
  cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
  if (!allow_guest) {
    // Disallowed. The UI should normally not show the guest pod but if for some
    // reason this has been made available to the user here is the time to tell
    // this nicely.
    login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
                              HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    // Reenable clicking on other windows and status area.
    login_display_->SetUIEnabled(true);
    StartPublicSessionAutoLoginTimer();
    display_email_.clear();
    return;
  }

  // Only one instance of LoginPerformer should exist at a time.
  login_performer_.reset(NULL);
  login_performer_.reset(new LoginPerformer(this));
  is_login_in_progress_ = true;
  login_performer_->LoginOffTheRecord();
  SendAccessibilityAlert(
      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
}

void ExistingUserController::MigrateUserData(const std::string& old_password) {
  // LoginPerformer instance has state of the user so it should exist.
  if (login_performer_.get())
    login_performer_->RecoverEncryptedData(old_password);
}

void ExistingUserController::LoginAsPublicAccount(
    const std::string& username) {
  if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
    return;

  // Stop the auto-login timer when attempting login.
  StopPublicSessionAutoLoginTimer();

  // Disable clicking on other windows.
  login_display_->SetUIEnabled(false);

  CrosSettingsProvider::TrustedStatus status =
      cros_settings_->PrepareTrustedValues(
          base::Bind(&ExistingUserController::LoginAsPublicAccount,
                     weak_factory_.GetWeakPtr(),
                     username));
  // If device policy is permanently unavailable, logging into public accounts
  // is not possible.
  if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
                              HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    // Re-enable clicking on other windows.
    login_display_->SetUIEnabled(true);
    return;
  }

  // If device policy is not verified yet, this function will be called again
  // when verification finishes.
  if (status != CrosSettingsProvider::TRUSTED)
    return;

  // If there is no public account with the given |username|, logging in is not
  // possible.
  const User* user = UserManager::Get()->FindUser(username);
  if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) {
    // Re-enable clicking on other windows.
    login_display_->SetUIEnabled(true);
    StartPublicSessionAutoLoginTimer();
    return;
  }

  // Only one instance of LoginPerformer should exist at a time.
  login_performer_.reset(NULL);
  login_performer_.reset(new LoginPerformer(this));
  is_login_in_progress_ = true;
  login_performer_->LoginAsPublicAccount(username);
  SendAccessibilityAlert(
      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
}

void ExistingUserController::LoginAsKioskApp(const std::string& app_id) {
  host_->StartAppLaunch(app_id);
}

void ExistingUserController::OnSigninScreenReady() {
  signin_screen_ready_ = true;
  StartPublicSessionAutoLoginTimer();
}

void ExistingUserController::OnUserSelected(const std::string& username) {
  login_performer_.reset(NULL);
  num_login_attempts_ = 0;
}

void ExistingUserController::OnStartEnterpriseEnrollment() {
  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
      base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
                 weak_factory_.GetWeakPtr()));
}

void ExistingUserController::OnStartKioskEnableScreen() {
  KioskAppManager::Get()->GetConsumerKioskModeStatus(
      base::Bind(&ExistingUserController::OnConsumerKioskModeCheckCompleted,
                 weak_factory_.GetWeakPtr()));
}

void ExistingUserController::OnStartDeviceReset() {
  ShowResetScreen();
}

void ExistingUserController::OnStartKioskAutolaunchScreen() {
  ShowKioskAutolaunchScreen();
}

void ExistingUserController::ResyncUserData() {
  // LoginPerformer instance has state of the user so it should exist.
  if (login_performer_.get())
    login_performer_->ResyncEncryptedData();
}

void ExistingUserController::SetDisplayEmail(const std::string& email) {
  display_email_ = email;
}

void ExistingUserController::ShowWrongHWIDScreen() {
  scoped_ptr<DictionaryValue> params;
  host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass());
  login_display_->OnFadeOut();
}

void ExistingUserController::Signout() {
  NOTREACHED();
}

void ExistingUserController::OnConsumerKioskModeCheckCompleted(
    KioskAppManager::ConsumerKioskModeStatus status) {
  if (status == KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE)
    ShowKioskEnableScreen();
}

void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
    DeviceSettingsService::OwnershipStatus status) {
  if (status == DeviceSettingsService::OWNERSHIP_NONE) {
    ShowEnrollmentScreen(false, std::string());
  } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
    // On a device that is already owned we might want to allow users to
    // re-enroll if the policy information is invalid.
    CrosSettingsProvider::TrustedStatus trusted_status =
        CrosSettings::Get()->PrepareTrustedValues(
            base::Bind(
                &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
                weak_factory_.GetWeakPtr(), status));
    if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
      ShowEnrollmentScreen(false, std::string());
    }
  } else {
    // OwnershipService::GetStatusAsync is supposed to return either
    // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
    NOTREACHED();
  }
}

void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment,
                                                  const std::string& user) {
  scoped_ptr<DictionaryValue> params;
  if (is_auto_enrollment) {
    params.reset(new DictionaryValue());
    params->SetBoolean("is_auto_enrollment", true);
    params->SetString("user", user);
  }
  host_->StartWizard(WizardController::kEnrollmentScreenName,
                     params.Pass());
  login_display_->OnFadeOut();
}

void ExistingUserController::ShowResetScreen() {
  scoped_ptr<DictionaryValue> params;
  host_->StartWizard(WizardController::kResetScreenName, params.Pass());
  login_display_->OnFadeOut();
}

void ExistingUserController::ShowKioskEnableScreen() {
  scoped_ptr<DictionaryValue> params;
  host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass());
  login_display_->OnFadeOut();
}

void ExistingUserController::ShowKioskAutolaunchScreen() {
  scoped_ptr<DictionaryValue> params;
  host_->StartWizard(WizardController::kKioskAutolaunchScreenName,
                     params.Pass());
  login_display_->OnFadeOut();
}

void ExistingUserController::ShowTPMError() {
  login_display_->SetUIEnabled(false);
  login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
}

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, LoginPerformer::Delegate implementation:
//

void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
  is_login_in_progress_ = false;
  offline_failed_ = true;

  guest_mode_url_ = GURL::EmptyGURL();
  std::string error = failure.GetErrorString();

  if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
          HandleLoginFailure(failure)) {
    login_display_->SetUIEnabled(true);
    return;
  }

  if (failure.reason() == LoginFailure::OWNER_REQUIRED) {
    ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
    content::BrowserThread::PostDelayedTask(
        content::BrowserThread::UI, FROM_HERE,
        base::Bind(&SessionManagerClient::StopSession,
                   base::Unretained(DBusThreadManager::Get()->
                                    GetSessionManagerClient())),
        base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
  } else if (failure.reason() == LoginFailure::TPM_ERROR) {
    ShowTPMError();
  } else if (!online_succeeded_for_.empty()) {
    ShowGaiaPasswordChanged(online_succeeded_for_);
  } else {
    // Check networking after trying to login in case user is
    // cached locally or the local admin account.
    bool is_known_user =
        UserManager::Get()->IsKnownUser(last_login_attempt_username_);
    if (!network_state_helper_->IsConnected()) {
      if (is_known_user)
        ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
      else
        ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
    } else {
      // TODO(nkostylev): Cleanup rest of ClientLogin related code.
      if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
          failure.error().state() ==
              GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
        ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
      } else {
        if (!is_known_user)
          ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
        else
          ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
      }
    }
    // Reenable clicking on other windows and status area.
    login_display_->SetUIEnabled(true);
    login_display_->ClearAndEnablePassword();
    StartPublicSessionAutoLoginTimer();
  }

  // Reset user flow to default, so that special flow will not affect next
  // attempt.
  UserManager::Get()->ResetUserFlow(last_login_attempt_username_);

  if (login_status_consumer_)
    login_status_consumer_->OnLoginFailure(failure);

  // Clear the recorded displayed email so it won't affect any future attempts.
  display_email_.clear();
}

void ExistingUserController::OnLoginSuccess(const UserContext& user_context) {
  is_login_in_progress_ = false;
  offline_failed_ = false;
  login_display_->set_signin_completed(true);

  StopPublicSessionAutoLoginTimer();

  bool has_cookies =
      login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
      user_context.auth_code.empty();

  // Login performer will be gone so cache this value to use
  // once profile is loaded.
  password_changed_ = login_performer_->password_changed();

  // LoginPerformer instance will delete itself once online auth result is OK.
  // In case of failure it'll bring up ScreenLock and ask for
  // correct password/display error message.
  // Even in case when following online,offline protocol and returning
  // requests_pending = false, let LoginPerformer delete itself.
  login_performer_->set_delegate(NULL);
  ignore_result(login_performer_.release());

  // Will call OnProfilePrepared() in the end.
  LoginUtils::Get()->PrepareProfile(user_context,
                                    display_email_,
                                    has_cookies,
                                    false,          // Start session for user.
                                    this);

  display_email_.clear();

  // Notify LoginDisplay to allow it provide visual feedback to user.
  login_display_->OnLoginSuccess(user_context.username);
}

void ExistingUserController::OnProfilePrepared(Profile* profile) {
  // Reenable clicking on other windows and status area.
  login_display_->SetUIEnabled(true);

  UserManager* user_manager = UserManager::Get();
  if (user_manager->IsCurrentUserNew() &&
      user_manager->IsLoggedInAsLocallyManagedUser()) {
    // Supervised users should launch into empty desktop on first run.
    CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
  }

  if (user_manager->IsCurrentUserNew() &&
      !user_manager->GetCurrentUserFlow()->ShouldSkipPostLoginScreens() &&
      !WizardController::default_controller()->skip_post_login_screens()) {
    // Don't specify start URLs if the administrator has configured the start
    // URLs via policy.
    if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs()))
      InitializeStartUrls();

    // Mark the device as registered., i.e. the second part of OOBE as
    // completed.
    if (!StartupUtils::IsDeviceRegistered())
      StartupUtils::MarkDeviceRegistered();

    if (CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kOobeSkipPostLogin)) {
      LoginUtils::Get()->DoBrowserLaunch(profile, host_);
      host_ = NULL;
    } else {
      ActivateWizard(WizardController::kTermsOfServiceScreenName);
    }
  } else {
    LoginUtils::Get()->DoBrowserLaunch(profile, host_);
    host_ = NULL;
  }
  // Inform |login_status_consumer_| about successful login.
  if (login_status_consumer_)
    login_status_consumer_->OnLoginSuccess(UserContext());
  login_display_->OnFadeOut();
}

void ExistingUserController::OnOffTheRecordLoginSuccess() {
  is_login_in_progress_ = false;
  offline_failed_ = false;

  // Mark the device as registered., i.e. the second part of OOBE as completed.
  if (!StartupUtils::IsDeviceRegistered())
    StartupUtils::MarkDeviceRegistered();

  LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_);

  if (login_status_consumer_)
    login_status_consumer_->OnOffTheRecordLoginSuccess();
}

void ExistingUserController::OnPasswordChangeDetected() {
  is_login_in_progress_ = false;
  offline_failed_ = false;

  // Must not proceed without signature verification.
  if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
      base::Bind(&ExistingUserController::OnPasswordChangeDetected,
                 weak_factory_.GetWeakPtr()))) {
    // Value of owner email is still not verified.
    // Another attempt will be invoked after verification completion.
    return;
  }

  if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
          HandlePasswordChangeDetected()) {
    return;
  }

  // True if user has already made an attempt to enter old password and failed.
  bool show_invalid_old_password_error =
      login_performer_->password_changed_callback_count() > 1;

  // Note: We allow owner using "full sync" mode which will recreate
  // cryptohome and deal with owner private key being lost. This also allows
  // us to recover from a lost owner password/homedir.
  // TODO(gspencer): We shouldn't have to erase stateful data when
  // doing this.  See http://crosbug.com/9115 http://crosbug.com/7792
  login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);

  if (login_status_consumer_)
    login_status_consumer_->OnPasswordChangeDetected();

  display_email_.clear();
}

void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
  is_login_in_progress_ = false;
  offline_failed_ = false;

  ShowError(IDS_LOGIN_ERROR_WHITELIST, email);

  // Reenable clicking on other windows and status area.
  login_display_->SetUIEnabled(true);
  login_display_->ShowSigninUI(email);

  if (login_status_consumer_) {
    login_status_consumer_->OnLoginFailure(LoginFailure(
          LoginFailure::WHITELIST_CHECK_FAILED));
  }

  display_email_.clear();

  StartPublicSessionAutoLoginTimer();
}

void ExistingUserController::PolicyLoadFailed() {
  ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");

  // Reenable clicking on other windows and status area.
  is_login_in_progress_ = false;
  offline_failed_ = false;
  login_display_->SetUIEnabled(true);

  display_email_.clear();

  // Policy load failure stops login attempts -- restart the timer.
  StartPublicSessionAutoLoginTimer();
}

void ExistingUserController::OnOnlineChecked(const std::string& username,
                                             bool success) {
  if (success && last_login_attempt_username_ == username) {
    online_succeeded_for_ = username;
    // Wait for login attempt to end, if it hasn't yet.
    if (offline_failed_ && !is_login_in_progress_)
      ShowGaiaPasswordChanged(username);
  }
}

////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, private:

void ExistingUserController::DeviceSettingsChanged() {
  if (host_ != NULL) {
    // Signed settings or user list changed. Notify views and update them.
    UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
    ConfigurePublicSessionAutoLogin();
    return;
  }
}

void ExistingUserController::ActivateWizard(const std::string& screen_name) {
  scoped_ptr<DictionaryValue> params;
  host_->StartWizard(screen_name, params.Pass());
}

void ExistingUserController::ConfigurePublicSessionAutoLogin() {
  std::string auto_login_account_id;
  cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
                            &auto_login_account_id);
  const std::vector<policy::DeviceLocalAccount> device_local_accounts =
      policy::GetDeviceLocalAccounts(cros_settings_);

  public_session_auto_login_username_.clear();
  for (std::vector<policy::DeviceLocalAccount>::const_iterator
           it = device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    if (it->account_id == auto_login_account_id) {
      public_session_auto_login_username_ = it->user_id;
      break;
    }
  }

  const User* user =
      UserManager::Get()->FindUser(public_session_auto_login_username_);
  if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
    public_session_auto_login_username_.clear();

  if (!cros_settings_->GetInteger(
          kAccountsPrefDeviceLocalAccountAutoLoginDelay,
          &public_session_auto_login_delay_)) {
    public_session_auto_login_delay_ = 0;
  }

  if (!public_session_auto_login_username_.empty())
    StartPublicSessionAutoLoginTimer();
  else
    StopPublicSessionAutoLoginTimer();
}

void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
  // Only restart the auto-login timer if it's already running.
  if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
    StopPublicSessionAutoLoginTimer();
    StartPublicSessionAutoLoginTimer();
  }
}

void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
  CHECK(signin_screen_ready_ &&
        !is_login_in_progress_ &&
        !public_session_auto_login_username_.empty());
  LoginAsPublicAccount(public_session_auto_login_username_);
}

void ExistingUserController::StopPublicSessionAutoLoginTimer() {
  if (auto_login_timer_)
    auto_login_timer_->Stop();
}

void ExistingUserController::StartPublicSessionAutoLoginTimer() {
  if (!signin_screen_ready_ ||
      is_login_in_progress_ ||
      public_session_auto_login_username_.empty()) {
    return;
  }

  // Start the auto-login timer.
  if (!auto_login_timer_)
    auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);

  auto_login_timer_->Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(
          public_session_auto_login_delay_),
      base::Bind(
          &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
          weak_factory_.GetWeakPtr()));
}

gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
  return host_->GetNativeWindow();
}

void ExistingUserController::InitializeStartUrls() const {
  std::vector<std::string> start_urls;

  const base::ListValue *urls;
  bool can_show_getstarted_guide = true;
  if (UserManager::Get()->IsLoggedInAsDemoUser()) {
    if (CrosSettings::Get()->GetList(kStartUpUrls, &urls)) {
      // The retail mode user will get start URLs from a special policy if it is
      // set.
      for (base::ListValue::const_iterator it = urls->begin();
           it != urls->end(); ++it) {
        std::string url;
        if ((*it)->GetAsString(&url))
          start_urls.push_back(url);
      }
    }
    can_show_getstarted_guide = false;
  // Skip the default first-run behavior for public accounts.
  } else if (!UserManager::Get()->IsLoggedInAsPublicAccount()) {
    if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
      const char* url = kChromeVoxTutorialURLPattern;
      PrefService* prefs = g_browser_process->local_state();
      const std::string current_locale =
          StringToLowerASCII(prefs->GetString(prefs::kApplicationLocale));
      std::string vox_url = base::StringPrintf(url, current_locale.c_str());
      start_urls.push_back(vox_url);
      can_show_getstarted_guide = false;
    }
  }

  ServicesCustomizationDocument* customization =
      ServicesCustomizationDocument::GetInstance();
  if (!ServicesCustomizationDocument::WasApplied() &&
      customization->IsReady()) {
    // Since we don't use OEM start URL anymore, just mark as applied.
    customization->ApplyCustomization();
  }

  // Only show getting started guide for a new user.
  const bool should_show_getstarted_guide =
      UserManager::Get()->IsCurrentUserNew();

  if (can_show_getstarted_guide && should_show_getstarted_guide) {
    // Don't open default Chrome window if we're going to launch the GS app.
    // Because we dont' want the GS app to be hidden in the background.
    CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
  } else {
    for (size_t i = 0; i < start_urls.size(); ++i) {
      CommandLine::ForCurrentProcess()->AppendArg(start_urls[i]);
    }
  }
}

void ExistingUserController::ShowError(int error_id,
                                       const std::string& details) {
  // TODO(dpolukhin): show detailed error info. |details| string contains
  // low level error info that is not localized and even is not user friendly.
  // For now just ignore it because error_text contains all required information
  // for end users, developers can see details string in Chrome logs.
  VLOG(1) << details;
  HelpAppLauncher::HelpTopic help_topic_id;
  bool is_offline = !network_state_helper_->IsConnected();
  switch (login_performer_->error().state()) {
    case GoogleServiceAuthError::CONNECTION_FAILED:
      help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
      break;
    case GoogleServiceAuthError::ACCOUNT_DISABLED:
      help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
      break;
    case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
      help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
      break;
    default:
      help_topic_id = is_offline ?
          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
      break;
  }

  login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
}

void ExistingUserController::ShowGaiaPasswordChanged(
    const std::string& username) {
  // Invalidate OAuth token, since it can't be correct after password is
  // changed.
  UserManager::Get()->SaveUserOAuthStatus(
      username,
      User::OAUTH2_TOKEN_STATUS_INVALID);

  login_display_->SetUIEnabled(true);
  login_display_->ShowGaiaPasswordChanged(username);
}

void ExistingUserController::SendAccessibilityAlert(
    const std::string& alert_text) {
  AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text);
  SendControlAccessibilityNotification(
      ui::AccessibilityTypes::EVENT_VALUE_CHANGED, &event);
}

}  // namespace chromeos
