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