Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/login/existing_user_controller.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/callback.h"
     12 #include "base/command_line.h"
     13 #include "base/logging.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/metrics/histogram.h"
     17 #include "base/prefs/pref_service.h"
     18 #include "base/strings/string_util.h"
     19 #include "base/strings/stringprintf.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "base/values.h"
     22 #include "base/version.h"
     23 #include "chrome/browser/browser_process.h"
     24 #include "chrome/browser/chrome_notification_types.h"
     25 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
     26 #include "chrome/browser/chromeos/boot_times_loader.h"
     27 #include "chrome/browser/chromeos/customization_document.h"
     28 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
     29 #include "chrome/browser/chromeos/login/helper.h"
     30 #include "chrome/browser/chromeos/login/login_display_host.h"
     31 #include "chrome/browser/chromeos/login/login_utils.h"
     32 #include "chrome/browser/chromeos/login/startup_utils.h"
     33 #include "chrome/browser/chromeos/login/user_manager.h"
     34 #include "chrome/browser/chromeos/login/wizard_controller.h"
     35 #include "chrome/browser/chromeos/policy/device_local_account.h"
     36 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     37 #include "chrome/browser/chromeos/settings/cros_settings.h"
     38 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
     39 #include "chrome/browser/chromeos/system/statistics_provider.h"
     40 #include "chrome/browser/google/google_util.h"
     41 #include "chrome/browser/policy/policy_service.h"
     42 #include "chrome/browser/prefs/session_startup_pref.h"
     43 #include "chrome/common/chrome_switches.h"
     44 #include "chrome/common/chrome_version_info.h"
     45 #include "chrome/common/pref_names.h"
     46 #include "chrome/common/url_constants.h"
     47 #include "chromeos/chromeos_switches.h"
     48 #include "chromeos/dbus/dbus_thread_manager.h"
     49 #include "chromeos/dbus/power_manager_client.h"
     50 #include "chromeos/dbus/session_manager_client.h"
     51 #include "content/public/browser/browser_thread.h"
     52 #include "content/public/browser/notification_service.h"
     53 #include "content/public/browser/notification_types.h"
     54 #include "content/public/browser/user_metrics.h"
     55 #include "google_apis/gaia/gaia_auth_util.h"
     56 #include "google_apis/gaia/google_service_auth_error.h"
     57 #include "grit/generated_resources.h"
     58 #include "net/http/http_auth_cache.h"
     59 #include "net/http/http_network_session.h"
     60 #include "net/http/http_transaction_factory.h"
     61 #include "net/url_request/url_request_context.h"
     62 #include "net/url_request/url_request_context_getter.h"
     63 #include "ui/base/l10n/l10n_util.h"
     64 #include "ui/views/widget/widget.h"
     65 
     66 namespace chromeos {
     67 
     68 namespace {
     69 
     70 // Major version where we still show GSG as "Release Notes" after the update.
     71 const long int kReleaseNotesTargetRelease = 19;
     72 
     73 // URL for account creation.
     74 const char kCreateAccountURL[] =
     75     "https://accounts.google.com/NewAccount?service=mail";
     76 
     77 // ChromeVox tutorial URL (used in place of "getting started" url when
     78 // accessibility is enabled).
     79 const char kChromeVoxTutorialURLPattern[] =
     80     "http://www.chromevox.com/tutorial/index.html?lang=%s";
     81 
     82 // Delay for transferring the auth cache to the system profile.
     83 const long int kAuthCacheTransferDelayMs = 2000;
     84 
     85 // Delay for restarting the ui if safe-mode login has failed.
     86 const long int kSafeModeRestartUiDelayMs = 30000;
     87 
     88 // Delay for rebooting machine if TPM critical error was encountered.
     89 const long int kCriticalErrorRebootDelayMs = 3500;
     90 
     91 // Makes a call to the policy subsystem to reload the policy when we detect
     92 // authentication change.
     93 void RefreshPoliciesOnUIThread() {
     94   if (g_browser_process->policy_service())
     95     g_browser_process->policy_service()->RefreshPolicies(base::Closure());
     96 }
     97 
     98 // Copies any authentication details that were entered in the login profile in
     99 // the mail profile to make sure all subsystems of Chrome can access the network
    100 // with the provided authentication which are possibly for a proxy server.
    101 void TransferContextAuthenticationsOnIOThread(
    102     net::URLRequestContextGetter* default_profile_context_getter,
    103     net::URLRequestContextGetter* browser_process_context_getter) {
    104   net::HttpAuthCache* new_cache =
    105       browser_process_context_getter->GetURLRequestContext()->
    106       http_transaction_factory()->GetSession()->http_auth_cache();
    107   net::HttpAuthCache* old_cache =
    108       default_profile_context_getter->GetURLRequestContext()->
    109       http_transaction_factory()->GetSession()->http_auth_cache();
    110   new_cache->UpdateAllFrom(*old_cache);
    111   VLOG(1) << "Main request context populated with authentication data.";
    112   // Last but not least tell the policy subsystem to refresh now as it might
    113   // have been stuck until now too.
    114   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
    115                                    base::Bind(&RefreshPoliciesOnUIThread));
    116 }
    117 
    118 }  // namespace
    119 
    120 // static
    121 ExistingUserController* ExistingUserController::current_controller_ = NULL;
    122 
    123 ////////////////////////////////////////////////////////////////////////////////
    124 // ExistingUserController, public:
    125 
    126 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
    127     : login_status_consumer_(NULL),
    128       host_(host),
    129       login_display_(host_->CreateLoginDisplay(this)),
    130       num_login_attempts_(0),
    131       cros_settings_(CrosSettings::Get()),
    132       weak_factory_(this),
    133       offline_failed_(false),
    134       is_login_in_progress_(false),
    135       password_changed_(false),
    136       do_auto_enrollment_(false),
    137       signin_screen_ready_(false),
    138       network_state_helper_(new login::NetworkStateHelper) {
    139   DCHECK(current_controller_ == NULL);
    140   current_controller_ = this;
    141 
    142   registrar_.Add(this,
    143                  chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
    144                  content::NotificationService::AllSources());
    145   registrar_.Add(this,
    146                  chrome::NOTIFICATION_USER_LIST_CHANGED,
    147                  content::NotificationService::AllSources());
    148   registrar_.Add(this,
    149                  chrome::NOTIFICATION_AUTH_SUPPLIED,
    150                  content::NotificationService::AllSources());
    151   registrar_.Add(this,
    152                  chrome::NOTIFICATION_SESSION_STARTED,
    153                  content::NotificationService::AllSources());
    154   cros_settings_->AddSettingsObserver(kAccountsPrefShowUserNamesOnSignIn, this);
    155   cros_settings_->AddSettingsObserver(kAccountsPrefAllowNewUser, this);
    156   cros_settings_->AddSettingsObserver(kAccountsPrefAllowGuest, this);
    157   cros_settings_->AddSettingsObserver(kAccountsPrefUsers, this);
    158   cros_settings_->AddSettingsObserver(
    159       kAccountsPrefDeviceLocalAccountAutoLoginId,
    160       this);
    161   cros_settings_->AddSettingsObserver(
    162       kAccountsPrefDeviceLocalAccountAutoLoginDelay,
    163       this);
    164 }
    165 
    166 void ExistingUserController::Init(const UserList& users) {
    167   time_init_ = base::Time::Now();
    168   UpdateLoginDisplay(users);
    169   ConfigurePublicSessionAutoLogin();
    170 
    171   DBusThreadManager::Get()->GetSessionManagerClient()->EmitLoginPromptReady();
    172 }
    173 
    174 void ExistingUserController::UpdateLoginDisplay(const UserList& users) {
    175   bool show_users_on_signin;
    176   UserList filtered_users;
    177 
    178   cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
    179                              &show_users_on_signin);
    180   if (show_users_on_signin) {
    181     for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
    182       // TODO(xiyuan): Clean user profile whose email is not in whitelist.
    183       bool meets_locally_managed_requirements =
    184           (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED ||
    185           UserManager::Get()->AreLocallyManagedUsersAllowed();
    186       bool meets_whitelist_requirements =
    187           LoginUtils::IsWhitelisted((*it)->email()) ||
    188           (*it)->GetType() != User::USER_TYPE_REGULAR;
    189       if (meets_locally_managed_requirements && meets_whitelist_requirements) {
    190         filtered_users.push_back(*it);
    191       }
    192     }
    193   }
    194 
    195   // If no user pods are visible, fallback to single new user pod which will
    196   // have guest session link.
    197   bool show_guest;
    198   cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
    199   bool show_users;
    200   cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_users);
    201   show_guest &= !filtered_users.empty();
    202   bool show_new_user = true;
    203   login_display_->set_parent_window(GetNativeWindow());
    204   login_display_->Init(filtered_users, show_guest, show_users, show_new_user);
    205   host_->OnPreferencesChanged();
    206 }
    207 
    208 void ExistingUserController::DoAutoEnrollment() {
    209   do_auto_enrollment_ = true;
    210 }
    211 
    212 void ExistingUserController::ResumeLogin() {
    213   // This means the user signed-in, then auto-enrollment used his credentials
    214   // to enroll and succeeded.
    215   resume_login_callback_.Run();
    216   resume_login_callback_.Reset();
    217 }
    218 
    219 void ExistingUserController::PrepareKioskAppLaunch() {
    220   // Disable login UI while waiting for the kiosk app launch. There is no
    221   // balanced UI enable call because this very login screen will not be
    222   // accessed again. If app is launched, it will be destroyed. If app fails to
    223   // launch, chrome is restarted to go back to a new login screen.
    224   login_display_->SetUIEnabled(false);
    225 }
    226 
    227 ////////////////////////////////////////////////////////////////////////////////
    228 // ExistingUserController, content::NotificationObserver implementation:
    229 //
    230 
    231 void ExistingUserController::Observe(
    232     int type,
    233     const content::NotificationSource& source,
    234     const content::NotificationDetails& details) {
    235   if (type == chrome::NOTIFICATION_SESSION_STARTED) {
    236     // Stop listening to any notification once session has started.
    237     // Sign in screen objects are marked for deletion with DeleteSoon so
    238     // make sure no object would be used after session has started.
    239     // http://crbug.com/125276
    240     registrar_.RemoveAll();
    241     return;
    242   }
    243   if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) {
    244     const std::string setting = *content::Details<const std::string>(
    245         details).ptr();
    246     if (setting == kAccountsPrefDeviceLocalAccountAutoLoginId ||
    247         setting == kAccountsPrefDeviceLocalAccountAutoLoginDelay) {
    248       ConfigurePublicSessionAutoLogin();
    249     }
    250   }
    251   if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
    252       type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
    253     if (host_ != NULL) {
    254       // Signed settings or user list changed. Notify views and update them.
    255       UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
    256       ConfigurePublicSessionAutoLogin();
    257       return;
    258     }
    259   }
    260   if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
    261     // Possibly the user has authenticated against a proxy server and we might
    262     // need the credentials for enrollment and other system requests from the
    263     // main |g_browser_process| request context (see bug
    264     // http://crosbug.com/24861). So we transfer any credentials to the global
    265     // request context here.
    266     // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
    267     // just after the UI is closed but before the new credentials were stored
    268     // in the profile. Therefore we have to give it some time to make sure it
    269     // has been updated before we copy it.
    270     LOG(INFO) << "Authentication was entered manually, possibly for proxyauth.";
    271     scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
    272         g_browser_process->system_request_context();
    273     Profile* signin_profile = ProfileHelper::GetSigninProfile();
    274     scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
    275         signin_profile->GetRequestContext();
    276     DCHECK(browser_process_context_getter.get());
    277     DCHECK(signin_profile_context_getter.get());
    278     content::BrowserThread::PostDelayedTask(
    279         content::BrowserThread::IO, FROM_HERE,
    280         base::Bind(&TransferContextAuthenticationsOnIOThread,
    281                    signin_profile_context_getter,
    282                    browser_process_context_getter),
    283         base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
    284   }
    285   if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED)
    286     return;
    287   login_display_->OnUserImageChanged(*content::Details<User>(details).ptr());
    288 }
    289 
    290 ////////////////////////////////////////////////////////////////////////////////
    291 // ExistingUserController, private:
    292 
    293 ExistingUserController::~ExistingUserController() {
    294   LoginUtils::Get()->DelegateDeleted(this);
    295 
    296   cros_settings_->RemoveSettingsObserver(kAccountsPrefShowUserNamesOnSignIn,
    297                                          this);
    298   cros_settings_->RemoveSettingsObserver(kAccountsPrefAllowNewUser, this);
    299   cros_settings_->RemoveSettingsObserver(kAccountsPrefAllowGuest, this);
    300   cros_settings_->RemoveSettingsObserver(kAccountsPrefUsers, this);
    301   cros_settings_->RemoveSettingsObserver(
    302       kAccountsPrefDeviceLocalAccountAutoLoginId,
    303       this);
    304   cros_settings_->RemoveSettingsObserver(
    305       kAccountsPrefDeviceLocalAccountAutoLoginDelay,
    306       this);
    307 
    308   if (current_controller_ == this) {
    309     current_controller_ = NULL;
    310   } else {
    311     NOTREACHED() << "More than one controller are alive.";
    312   }
    313   DCHECK(login_display_.get());
    314 }
    315 
    316 ////////////////////////////////////////////////////////////////////////////////
    317 // ExistingUserController, LoginDisplay::Delegate implementation:
    318 //
    319 
    320 void ExistingUserController::CancelPasswordChangedFlow() {
    321   login_performer_.reset(NULL);
    322   login_display_->SetUIEnabled(true);
    323   StartPublicSessionAutoLoginTimer();
    324 }
    325 
    326 void ExistingUserController::CreateAccount() {
    327   content::RecordAction(content::UserMetricsAction("Login.CreateAccount"));
    328   guest_mode_url_ =
    329       google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL));
    330   LoginAsGuest();
    331 }
    332 
    333 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
    334   login_display_->set_signin_completed(true);
    335   if (!host_) {
    336     // Complete login event was generated already from UI. Ignore notification.
    337     return;
    338   }
    339 
    340   // Stop the auto-login timer when attempting login.
    341   StopPublicSessionAutoLoginTimer();
    342 
    343   // Disable UI while loading user profile.
    344   login_display_->SetUIEnabled(false);
    345 
    346   if (!time_init_.is_null()) {
    347     base::TimeDelta delta = base::Time::Now() - time_init_;
    348     UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
    349     time_init_ = base::Time();  // Reset to null.
    350   }
    351 
    352   host_->OnCompleteLogin();
    353 
    354   // Do an ownership check now to avoid auto-enrolling if the device has
    355   // already been owned.
    356   DeviceSettingsService::Get()->GetOwnershipStatusAsync(
    357       base::Bind(&ExistingUserController::CompleteLoginInternal,
    358                  weak_factory_.GetWeakPtr(),
    359                  user_context));
    360 }
    361 
    362 void ExistingUserController::CompleteLoginInternal(
    363     const UserContext& user_context,
    364     DeviceSettingsService::OwnershipStatus ownership_status,
    365     bool is_owner) {
    366   // Auto-enrollment must have made a decision by now. It's too late to enroll
    367   // if the protocol isn't done at this point.
    368   if (do_auto_enrollment_ &&
    369       ownership_status == DeviceSettingsService::OWNERSHIP_NONE) {
    370     VLOG(1) << "Forcing auto-enrollment before completing login";
    371     // The only way to get out of the enrollment screen from now on is to either
    372     // complete enrollment, or opt-out of it. So this controller shouldn't force
    373     // enrollment again if it is reused for another sign-in.
    374     do_auto_enrollment_ = false;
    375     auto_enrollment_username_ = user_context.username;
    376     resume_login_callback_ = base::Bind(
    377         &ExistingUserController::PerformLogin,
    378         weak_factory_.GetWeakPtr(),
    379         user_context, LoginPerformer::AUTH_MODE_EXTENSION);
    380     ShowEnrollmentScreen(true, user_context.username);
    381     // Enable UI for the enrollment screen. SetUIEnabled(true) will post a
    382     // request to show the sign-in screen again when invoked at the sign-in
    383     // screen; invoke SetUIEnabled() after navigating to the enrollment screen.
    384     login_display_->SetUIEnabled(true);
    385   } else {
    386     PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
    387   }
    388 }
    389 
    390 string16 ExistingUserController::GetConnectedNetworkName() {
    391   return network_state_helper_->GetCurrentNetworkName();
    392 }
    393 
    394 bool ExistingUserController::IsSigninInProgress() const {
    395   return is_login_in_progress_;
    396 }
    397 
    398 void ExistingUserController::Login(const UserContext& user_context) {
    399   if ((user_context.username.empty() || user_context.password.empty()) &&
    400       user_context.auth_code.empty())
    401     return;
    402 
    403   // Stop the auto-login timer when attempting login.
    404   StopPublicSessionAutoLoginTimer();
    405 
    406   // Disable clicking on other windows.
    407   login_display_->SetUIEnabled(false);
    408 
    409   BootTimesLoader::Get()->RecordLoginAttempted();
    410 
    411   if (last_login_attempt_username_ != user_context.username) {
    412     last_login_attempt_username_ = user_context.username;
    413     num_login_attempts_ = 0;
    414     // Also reset state variables, which are used to determine password change.
    415     offline_failed_ = false;
    416     online_succeeded_for_.clear();
    417   }
    418   num_login_attempts_++;
    419   PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
    420 }
    421 
    422 void ExistingUserController::PerformLogin(
    423     const UserContext& user_context,
    424     LoginPerformer::AuthorizationMode auth_mode) {
    425   UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
    426       set_host(host_);
    427 
    428   // Disable UI while loading user profile.
    429   login_display_->SetUIEnabled(false);
    430 
    431   // Use the same LoginPerformer for subsequent login as it has state
    432   // such as Authenticator instance.
    433   if (!login_performer_.get() || num_login_attempts_ <= 1) {
    434     LoginPerformer::Delegate* delegate = this;
    435     if (login_performer_delegate_.get())
    436       delegate = login_performer_delegate_.get();
    437     // Only one instance of LoginPerformer should exist at a time.
    438     login_performer_.reset(NULL);
    439     login_performer_.reset(new LoginPerformer(delegate));
    440   }
    441 
    442   is_login_in_progress_ = true;
    443   if (gaia::ExtractDomainName(user_context.username) ==
    444           UserManager::kLocallyManagedUserDomain) {
    445     if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
    446       LOG(ERROR) << "Login attempt of locally managed user detected.";
    447       login_display_->SetUIEnabled(true);
    448       return;
    449     }
    450     login_performer_->LoginAsLocallyManagedUser(
    451         UserContext(user_context.username,
    452                     user_context.password,
    453                     std::string()));  // auth_code
    454   } else {
    455     login_performer_->PerformLogin(user_context, auth_mode);
    456   }
    457   AccessibilityManager::Get()->MaybeSpeak(
    458       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
    459 }
    460 
    461 void ExistingUserController::LoginAsRetailModeUser() {
    462   // Stop the auto-login timer when attempting login.
    463   StopPublicSessionAutoLoginTimer();
    464 
    465   // Disable clicking on other windows.
    466   login_display_->SetUIEnabled(false);
    467   // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
    468   // the enterprise policy wiring is done for retail mode.
    469 
    470   // Only one instance of LoginPerformer should exist at a time.
    471   login_performer_.reset(NULL);
    472   login_performer_.reset(new LoginPerformer(this));
    473   is_login_in_progress_ = true;
    474   login_performer_->LoginRetailMode();
    475   AccessibilityManager::Get()->MaybeSpeak(
    476       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
    477 }
    478 
    479 void ExistingUserController::LoginAsGuest() {
    480   if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
    481     return;
    482 
    483   // Stop the auto-login timer when attempting login.
    484   StopPublicSessionAutoLoginTimer();
    485 
    486   // Disable clicking on other windows.
    487   login_display_->SetUIEnabled(false);
    488 
    489   CrosSettingsProvider::TrustedStatus status =
    490       cros_settings_->PrepareTrustedValues(
    491           base::Bind(&ExistingUserController::LoginAsGuest,
    492                      weak_factory_.GetWeakPtr()));
    493   // Must not proceed without signature verification.
    494   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    495     login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
    496                               HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    497     // Reenable clicking on other windows and status area.
    498     login_display_->SetUIEnabled(true);
    499     StartPublicSessionAutoLoginTimer();
    500     display_email_.clear();
    501     return;
    502   } else if (status != CrosSettingsProvider::TRUSTED) {
    503     // Value of AllowNewUser setting is still not verified.
    504     // Another attempt will be invoked after verification completion.
    505     return;
    506   }
    507 
    508   bool allow_guest;
    509   cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
    510   if (!allow_guest) {
    511     // Disallowed. The UI should normally not show the guest pod but if for some
    512     // reason this has been made available to the user here is the time to tell
    513     // this nicely.
    514     login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
    515                               HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    516     // Reenable clicking on other windows and status area.
    517     login_display_->SetUIEnabled(true);
    518     StartPublicSessionAutoLoginTimer();
    519     display_email_.clear();
    520     return;
    521   }
    522 
    523   // Only one instance of LoginPerformer should exist at a time.
    524   login_performer_.reset(NULL);
    525   login_performer_.reset(new LoginPerformer(this));
    526   is_login_in_progress_ = true;
    527   login_performer_->LoginOffTheRecord();
    528   AccessibilityManager::Get()->MaybeSpeak(
    529       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
    530 }
    531 
    532 void ExistingUserController::MigrateUserData(const std::string& old_password) {
    533   // LoginPerformer instance has state of the user so it should exist.
    534   if (login_performer_.get())
    535     login_performer_->RecoverEncryptedData(old_password);
    536 }
    537 
    538 void ExistingUserController::LoginAsPublicAccount(
    539     const std::string& username) {
    540   if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
    541     return;
    542 
    543   // Stop the auto-login timer when attempting login.
    544   StopPublicSessionAutoLoginTimer();
    545 
    546   // Disable clicking on other windows.
    547   login_display_->SetUIEnabled(false);
    548 
    549   CrosSettingsProvider::TrustedStatus status =
    550       cros_settings_->PrepareTrustedValues(
    551           base::Bind(&ExistingUserController::LoginAsPublicAccount,
    552                      weak_factory_.GetWeakPtr(),
    553                      username));
    554   // If device policy is permanently unavailable, logging into public accounts
    555   // is not possible.
    556   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    557     login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
    558                               HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
    559     // Re-enable clicking on other windows.
    560     login_display_->SetUIEnabled(true);
    561     return;
    562   }
    563 
    564   // If device policy is not verified yet, this function will be called again
    565   // when verification finishes.
    566   if (status != CrosSettingsProvider::TRUSTED)
    567     return;
    568 
    569   // If there is no public account with the given |username|, logging in is not
    570   // possible.
    571   const User* user = UserManager::Get()->FindUser(username);
    572   if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) {
    573     // Re-enable clicking on other windows.
    574     login_display_->SetUIEnabled(true);
    575     StartPublicSessionAutoLoginTimer();
    576     return;
    577   }
    578 
    579   // Only one instance of LoginPerformer should exist at a time.
    580   login_performer_.reset(NULL);
    581   login_performer_.reset(new LoginPerformer(this));
    582   is_login_in_progress_ = true;
    583   login_performer_->LoginAsPublicAccount(username);
    584   AccessibilityManager::Get()->MaybeSpeak(
    585       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
    586 }
    587 
    588 void ExistingUserController::OnSigninScreenReady() {
    589   signin_screen_ready_ = true;
    590   StartPublicSessionAutoLoginTimer();
    591 }
    592 
    593 void ExistingUserController::OnUserSelected(const std::string& username) {
    594   login_performer_.reset(NULL);
    595   num_login_attempts_ = 0;
    596 }
    597 
    598 void ExistingUserController::OnStartEnterpriseEnrollment() {
    599   DeviceSettingsService::Get()->GetOwnershipStatusAsync(
    600       base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
    601                  weak_factory_.GetWeakPtr()));
    602 }
    603 
    604 void ExistingUserController::OnStartKioskEnableScreen() {
    605   KioskAppManager::Get()->GetConsumerKioskModeStatus(
    606       base::Bind(&ExistingUserController::OnConsumerKioskModeCheckCompleted,
    607                  weak_factory_.GetWeakPtr()));
    608 }
    609 
    610 void ExistingUserController::OnStartDeviceReset() {
    611   ShowResetScreen();
    612 }
    613 
    614 void ExistingUserController::OnStartKioskAutolaunchScreen() {
    615   ShowKioskAutolaunchScreen();
    616 }
    617 
    618 void ExistingUserController::ResyncUserData() {
    619   // LoginPerformer instance has state of the user so it should exist.
    620   if (login_performer_.get())
    621     login_performer_->ResyncEncryptedData();
    622 }
    623 
    624 void ExistingUserController::SetDisplayEmail(const std::string& email) {
    625   display_email_ = email;
    626 }
    627 
    628 void ExistingUserController::ShowWrongHWIDScreen() {
    629   scoped_ptr<DictionaryValue> params;
    630   host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass());
    631   login_display_->OnFadeOut();
    632 }
    633 
    634 void ExistingUserController::Signout() {
    635   NOTREACHED();
    636 }
    637 
    638 void ExistingUserController::OnConsumerKioskModeCheckCompleted(
    639     KioskAppManager::ConsumerKioskModeStatus status) {
    640   if (status == KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE)
    641     ShowKioskEnableScreen();
    642 }
    643 
    644 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
    645     DeviceSettingsService::OwnershipStatus status,
    646     bool current_user_is_owner) {
    647   if (status == DeviceSettingsService::OWNERSHIP_NONE) {
    648     ShowEnrollmentScreen(false, std::string());
    649   } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
    650     // On a device that is already owned we might want to allow users to
    651     // re-enroll if the policy information is invalid.
    652     CrosSettingsProvider::TrustedStatus trusted_status =
    653         CrosSettings::Get()->PrepareTrustedValues(
    654             base::Bind(
    655                 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
    656                 weak_factory_.GetWeakPtr(),
    657                 status, current_user_is_owner));
    658     if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    659       ShowEnrollmentScreen(false, std::string());
    660     }
    661   } else {
    662     // OwnershipService::GetStatusAsync is supposed to return either
    663     // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
    664     NOTREACHED();
    665   }
    666 }
    667 
    668 void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment,
    669                                                   const std::string& user) {
    670   scoped_ptr<DictionaryValue> params;
    671   if (is_auto_enrollment) {
    672     params.reset(new DictionaryValue());
    673     params->SetBoolean("is_auto_enrollment", true);
    674     params->SetString("user", user);
    675   }
    676   host_->StartWizard(WizardController::kEnrollmentScreenName,
    677                      params.Pass());
    678   login_display_->OnFadeOut();
    679 }
    680 
    681 void ExistingUserController::ShowResetScreen() {
    682   scoped_ptr<DictionaryValue> params;
    683   host_->StartWizard(WizardController::kResetScreenName, params.Pass());
    684   login_display_->OnFadeOut();
    685 }
    686 
    687 void ExistingUserController::ShowKioskEnableScreen() {
    688   scoped_ptr<DictionaryValue> params;
    689   host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass());
    690   login_display_->OnFadeOut();
    691 }
    692 
    693 void ExistingUserController::ShowKioskAutolaunchScreen() {
    694   scoped_ptr<DictionaryValue> params;
    695   host_->StartWizard(WizardController::kKioskAutolaunchScreenName,
    696                      params.Pass());
    697   login_display_->OnFadeOut();
    698 }
    699 
    700 void ExistingUserController::ShowTPMError() {
    701   login_display_->SetUIEnabled(false);
    702   login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
    703 }
    704 
    705 ////////////////////////////////////////////////////////////////////////////////
    706 // ExistingUserController, LoginPerformer::Delegate implementation:
    707 //
    708 
    709 void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
    710   is_login_in_progress_ = false;
    711   offline_failed_ = true;
    712 
    713   guest_mode_url_ = GURL::EmptyGURL();
    714   std::string error = failure.GetErrorString();
    715 
    716   if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
    717           HandleLoginFailure(failure)) {
    718     login_display_->SetUIEnabled(true);
    719     return;
    720   }
    721 
    722   if (failure.reason() == LoginFailure::OWNER_REQUIRED) {
    723     ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
    724     content::BrowserThread::PostDelayedTask(
    725         content::BrowserThread::UI, FROM_HERE,
    726         base::Bind(&SessionManagerClient::StopSession,
    727                    base::Unretained(DBusThreadManager::Get()->
    728                                     GetSessionManagerClient())),
    729         base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
    730   } else if (failure.reason() == LoginFailure::TPM_ERROR) {
    731     ShowTPMError();
    732   } else if (!online_succeeded_for_.empty()) {
    733     ShowGaiaPasswordChanged(online_succeeded_for_);
    734   } else {
    735     // Check networking after trying to login in case user is
    736     // cached locally or the local admin account.
    737     bool is_known_user =
    738         UserManager::Get()->IsKnownUser(last_login_attempt_username_);
    739     if (!network_state_helper_->IsConnected()) {
    740       if (is_known_user)
    741         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
    742       else
    743         ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
    744     } else {
    745       // TODO(nkostylev): Cleanup rest of ClientLogin related code.
    746       if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
    747           failure.error().state() ==
    748               GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
    749         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
    750       } else {
    751         if (!is_known_user)
    752           ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
    753         else
    754           ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
    755       }
    756     }
    757     // Reenable clicking on other windows and status area.
    758     login_display_->SetUIEnabled(true);
    759     login_display_->ClearAndEnablePassword();
    760     StartPublicSessionAutoLoginTimer();
    761   }
    762 
    763   // Reset user flow to default, so that special flow will not affect next
    764   // attempt.
    765   UserManager::Get()->ResetUserFlow(last_login_attempt_username_);
    766 
    767   if (login_status_consumer_)
    768     login_status_consumer_->OnLoginFailure(failure);
    769 
    770   // Clear the recorded displayed email so it won't affect any future attempts.
    771   display_email_.clear();
    772 }
    773 
    774 void ExistingUserController::OnLoginSuccess(
    775     const UserContext& user_context,
    776     bool pending_requests,
    777     bool using_oauth) {
    778   is_login_in_progress_ = false;
    779   offline_failed_ = false;
    780   login_display_->set_signin_completed(true);
    781 
    782   StopPublicSessionAutoLoginTimer();
    783 
    784   bool has_cookies =
    785       login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
    786       user_context.auth_code.empty();
    787 
    788   // Login performer will be gone so cache this value to use
    789   // once profile is loaded.
    790   password_changed_ = login_performer_->password_changed();
    791 
    792   // LoginPerformer instance will delete itself once online auth result is OK.
    793   // In case of failure it'll bring up ScreenLock and ask for
    794   // correct password/display error message.
    795   // Even in case when following online,offline protocol and returning
    796   // requests_pending = false, let LoginPerformer delete itself.
    797   login_performer_->set_delegate(NULL);
    798   ignore_result(login_performer_.release());
    799 
    800   // Will call OnProfilePrepared() in the end.
    801   LoginUtils::Get()->PrepareProfile(user_context,
    802                                     display_email_,
    803                                     using_oauth,
    804                                     has_cookies,
    805                                     false,          // Start session for user.
    806                                     this);
    807 
    808   display_email_.clear();
    809 
    810   // Notify LoginDisplay to allow it provide visual feedback to user.
    811   login_display_->OnLoginSuccess(user_context.username);
    812 }
    813 
    814 void ExistingUserController::OnProfilePrepared(Profile* profile) {
    815   // Reenable clicking on other windows and status area.
    816   login_display_->SetUIEnabled(true);
    817 
    818   if (UserManager::Get()->IsCurrentUserNew() &&
    819       !UserManager::Get()->GetCurrentUserFlow()->ShouldSkipPostLoginScreens() &&
    820       !WizardController::default_controller()->skip_post_login_screens()) {
    821     // Don't specify start URLs if the administrator has configured the start
    822     // URLs via policy.
    823     if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs()))
    824       InitializeStartUrls();
    825 
    826     // Mark the device as registered., i.e. the second part of OOBE as
    827     // completed.
    828     if (!StartupUtils::IsDeviceRegistered())
    829       StartupUtils::MarkDeviceRegistered();
    830 
    831     if (CommandLine::ForCurrentProcess()->HasSwitch(
    832           chromeos::switches::kOobeSkipPostLogin)) {
    833       LoginUtils::Get()->DoBrowserLaunch(profile, host_);
    834       host_ = NULL;
    835     } else {
    836       ActivateWizard(WizardController::kTermsOfServiceScreenName);
    837     }
    838   } else {
    839     LoginUtils::Get()->DoBrowserLaunch(profile, host_);
    840     host_ = NULL;
    841   }
    842   // Inform |login_status_consumer_| about successful login. Set most
    843   // parameters to empty since they're not needed.
    844   if (login_status_consumer_) {
    845     login_status_consumer_->OnLoginSuccess(UserContext(),
    846                                            false,    // pending_requests
    847                                            false);   // using_oauth
    848   }
    849   login_display_->OnFadeOut();
    850 }
    851 
    852 void ExistingUserController::OnOffTheRecordLoginSuccess() {
    853   is_login_in_progress_ = false;
    854   offline_failed_ = false;
    855 
    856   // Mark the device as registered., i.e. the second part of OOBE as completed.
    857   if (!StartupUtils::IsDeviceRegistered())
    858     StartupUtils::MarkDeviceRegistered();
    859 
    860   LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_);
    861 
    862   if (login_status_consumer_)
    863     login_status_consumer_->OnOffTheRecordLoginSuccess();
    864 }
    865 
    866 void ExistingUserController::OnPasswordChangeDetected() {
    867   is_login_in_progress_ = false;
    868   offline_failed_ = false;
    869 
    870   // Must not proceed without signature verification.
    871   if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
    872       base::Bind(&ExistingUserController::OnPasswordChangeDetected,
    873                  weak_factory_.GetWeakPtr()))) {
    874     // Value of owner email is still not verified.
    875     // Another attempt will be invoked after verification completion.
    876     return;
    877   }
    878 
    879   if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
    880           HandlePasswordChangeDetected()) {
    881     return;
    882   }
    883 
    884   // True if user has already made an attempt to enter old password and failed.
    885   bool show_invalid_old_password_error =
    886       login_performer_->password_changed_callback_count() > 1;
    887 
    888   // Note: We allow owner using "full sync" mode which will recreate
    889   // cryptohome and deal with owner private key being lost. This also allows
    890   // us to recover from a lost owner password/homedir.
    891   // TODO(gspencer): We shouldn't have to erase stateful data when
    892   // doing this.  See http://crosbug.com/9115 http://crosbug.com/7792
    893   login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
    894 
    895   if (login_status_consumer_)
    896     login_status_consumer_->OnPasswordChangeDetected();
    897 
    898   display_email_.clear();
    899 }
    900 
    901 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
    902   is_login_in_progress_ = false;
    903   offline_failed_ = false;
    904 
    905   ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
    906 
    907   // Reenable clicking on other windows and status area.
    908   login_display_->SetUIEnabled(true);
    909   login_display_->ShowSigninUI(email);
    910 
    911   if (login_status_consumer_) {
    912     login_status_consumer_->OnLoginFailure(LoginFailure(
    913           LoginFailure::WHITELIST_CHECK_FAILED));
    914   }
    915 
    916   display_email_.clear();
    917 
    918   StartPublicSessionAutoLoginTimer();
    919 }
    920 
    921 void ExistingUserController::PolicyLoadFailed() {
    922   ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
    923 
    924   // Reenable clicking on other windows and status area.
    925   is_login_in_progress_ = false;
    926   offline_failed_ = false;
    927   login_display_->SetUIEnabled(true);
    928 
    929   display_email_.clear();
    930 
    931   // Policy load failure stops login attempts -- restart the timer.
    932   StartPublicSessionAutoLoginTimer();
    933 }
    934 
    935 void ExistingUserController::OnOnlineChecked(const std::string& username,
    936                                              bool success) {
    937   if (success && last_login_attempt_username_ == username) {
    938     online_succeeded_for_ = username;
    939     // Wait for login attempt to end, if it hasn't yet.
    940     if (offline_failed_ && !is_login_in_progress_)
    941       ShowGaiaPasswordChanged(username);
    942   }
    943 }
    944 
    945 ////////////////////////////////////////////////////////////////////////////////
    946 // ExistingUserController, private:
    947 
    948 void ExistingUserController::ActivateWizard(const std::string& screen_name) {
    949   scoped_ptr<DictionaryValue> params;
    950   host_->StartWizard(screen_name, params.Pass());
    951 }
    952 
    953 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
    954   std::string auto_login_account_id;
    955   cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
    956                             &auto_login_account_id);
    957   const std::vector<policy::DeviceLocalAccount> device_local_accounts =
    958       policy::GetDeviceLocalAccounts(cros_settings_);
    959 
    960   public_session_auto_login_username_.clear();
    961   for (std::vector<policy::DeviceLocalAccount>::const_iterator
    962            it = device_local_accounts.begin();
    963        it != device_local_accounts.end(); ++it) {
    964     if (it->account_id == auto_login_account_id) {
    965       public_session_auto_login_username_ = it->user_id;
    966       break;
    967     }
    968   }
    969 
    970   const User* user =
    971       UserManager::Get()->FindUser(public_session_auto_login_username_);
    972   if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
    973     public_session_auto_login_username_.clear();
    974 
    975   if (!cros_settings_->GetInteger(
    976           kAccountsPrefDeviceLocalAccountAutoLoginDelay,
    977           &public_session_auto_login_delay_)) {
    978     public_session_auto_login_delay_ = 0;
    979   }
    980 
    981   if (!public_session_auto_login_username_.empty())
    982     StartPublicSessionAutoLoginTimer();
    983   else
    984     StopPublicSessionAutoLoginTimer();
    985 }
    986 
    987 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
    988   // Only restart the auto-login timer if it's already running.
    989   if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
    990     StopPublicSessionAutoLoginTimer();
    991     StartPublicSessionAutoLoginTimer();
    992   }
    993 }
    994 
    995 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
    996   CHECK(signin_screen_ready_ &&
    997         !is_login_in_progress_ &&
    998         !public_session_auto_login_username_.empty());
    999   LoginAsPublicAccount(public_session_auto_login_username_);
   1000 }
   1001 
   1002 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
   1003   if (auto_login_timer_)
   1004     auto_login_timer_->Stop();
   1005 }
   1006 
   1007 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
   1008   if (!signin_screen_ready_ ||
   1009       is_login_in_progress_ ||
   1010       public_session_auto_login_username_.empty()) {
   1011     return;
   1012   }
   1013 
   1014   // Start the auto-login timer.
   1015   if (!auto_login_timer_)
   1016     auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
   1017 
   1018   auto_login_timer_->Start(
   1019       FROM_HERE,
   1020       base::TimeDelta::FromMilliseconds(
   1021           public_session_auto_login_delay_),
   1022       base::Bind(
   1023           &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
   1024           weak_factory_.GetWeakPtr()));
   1025 }
   1026 
   1027 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
   1028   return host_->GetNativeWindow();
   1029 }
   1030 
   1031 void ExistingUserController::InitializeStartUrls() const {
   1032   std::vector<std::string> start_urls;
   1033 
   1034   const base::ListValue *urls;
   1035   bool can_show_getstarted_guide = true;
   1036   if (UserManager::Get()->IsLoggedInAsDemoUser()) {
   1037     if (CrosSettings::Get()->GetList(kStartUpUrls, &urls)) {
   1038       // The retail mode user will get start URLs from a special policy if it is
   1039       // set.
   1040       for (base::ListValue::const_iterator it = urls->begin();
   1041            it != urls->end(); ++it) {
   1042         std::string url;
   1043         if ((*it)->GetAsString(&url))
   1044           start_urls.push_back(url);
   1045       }
   1046     }
   1047     can_show_getstarted_guide = false;
   1048   // Skip the default first-run behavior for public accounts.
   1049   } else if (!UserManager::Get()->IsLoggedInAsPublicAccount()) {
   1050     if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
   1051       const char* url = kChromeVoxTutorialURLPattern;
   1052       PrefService* prefs = g_browser_process->local_state();
   1053       const std::string current_locale =
   1054           StringToLowerASCII(prefs->GetString(prefs::kApplicationLocale));
   1055       std::string vox_url = base::StringPrintf(url, current_locale.c_str());
   1056       start_urls.push_back(vox_url);
   1057       can_show_getstarted_guide = false;
   1058     }
   1059   }
   1060 
   1061   ServicesCustomizationDocument* customization =
   1062       ServicesCustomizationDocument::GetInstance();
   1063   if (!ServicesCustomizationDocument::WasApplied() &&
   1064       customization->IsReady()) {
   1065     // Since we don't use OEM start URL anymore, just mark as applied.
   1066     customization->ApplyCustomization();
   1067   }
   1068 
   1069   // Only show getting started guide for a new user.
   1070   const bool should_show_getstarted_guide =
   1071       UserManager::Get()->IsCurrentUserNew();
   1072 
   1073   if (can_show_getstarted_guide && should_show_getstarted_guide) {
   1074     // Don't open default Chrome window if we're going to launch the GS app.
   1075     // Because we dont' want the GS app to be hidden in the background.
   1076     CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
   1077   } else {
   1078     for (size_t i = 0; i < start_urls.size(); ++i) {
   1079       CommandLine::ForCurrentProcess()->AppendArg(start_urls[i]);
   1080     }
   1081   }
   1082 }
   1083 
   1084 void ExistingUserController::ShowError(int error_id,
   1085                                        const std::string& details) {
   1086   // TODO(dpolukhin): show detailed error info. |details| string contains
   1087   // low level error info that is not localized and even is not user friendly.
   1088   // For now just ignore it because error_text contains all required information
   1089   // for end users, developers can see details string in Chrome logs.
   1090   VLOG(1) << details;
   1091   HelpAppLauncher::HelpTopic help_topic_id;
   1092   bool is_offline = !network_state_helper_->IsConnected();
   1093   switch (login_performer_->error().state()) {
   1094     case GoogleServiceAuthError::CONNECTION_FAILED:
   1095       help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
   1096       break;
   1097     case GoogleServiceAuthError::ACCOUNT_DISABLED:
   1098       help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
   1099       break;
   1100     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
   1101       help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
   1102       break;
   1103     default:
   1104       help_topic_id = is_offline ?
   1105           HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
   1106           HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
   1107       break;
   1108   }
   1109 
   1110   login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
   1111 }
   1112 
   1113 void ExistingUserController::ShowGaiaPasswordChanged(
   1114     const std::string& username) {
   1115   // Invalidate OAuth token, since it can't be correct after password is
   1116   // changed.
   1117   UserManager::Get()->SaveUserOAuthStatus(
   1118       username,
   1119       User::OAUTH2_TOKEN_STATUS_INVALID);
   1120 
   1121   login_display_->SetUIEnabled(true);
   1122   login_display_->ShowGaiaPasswordChanged(username);
   1123 }
   1124 
   1125 }  // namespace chromeos
   1126