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