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