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