Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/login/wizard_controller.h"
      6 
      7 #include <signal.h>
      8 #include <stdlib.h>
      9 #include <sys/types.h>
     10 
     11 #include <string>
     12 #include <vector>
     13 
     14 #include "base/bind.h"
     15 #include "base/callback_helpers.h"
     16 #include "base/logging.h"
     17 #include "base/metrics/histogram.h"
     18 #include "base/prefs/pref_registry_simple.h"
     19 #include "base/prefs/pref_service.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "base/threading/thread_restrictions.h"
     22 #include "base/values.h"
     23 #include "chrome/browser/browser_process.h"
     24 #include "chrome/browser/chrome_notification_types.h"
     25 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
     26 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
     27 #include "chrome/browser/chromeos/customization_document.h"
     28 #include "chrome/browser/chromeos/geolocation/simple_geolocation_provider.h"
     29 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h"
     30 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
     31 #include "chrome/browser/chromeos/login/existing_user_controller.h"
     32 #include "chrome/browser/chromeos/login/helper.h"
     33 #include "chrome/browser/chromeos/login/hwid_checker.h"
     34 #include "chrome/browser/chromeos/login/login_utils.h"
     35 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
     36 #include "chrome/browser/chromeos/login/screens/error_screen.h"
     37 #include "chrome/browser/chromeos/login/screens/eula_screen.h"
     38 #include "chrome/browser/chromeos/login/screens/hid_detection_screen.h"
     39 #include "chrome/browser/chromeos/login/screens/kiosk_autolaunch_screen.h"
     40 #include "chrome/browser/chromeos/login/screens/kiosk_enable_screen.h"
     41 #include "chrome/browser/chromeos/login/screens/network_screen.h"
     42 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
     43 #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h"
     44 #include "chrome/browser/chromeos/login/screens/update_screen.h"
     45 #include "chrome/browser/chromeos/login/screens/user_image_screen.h"
     46 #include "chrome/browser/chromeos/login/screens/wrong_hwid_screen.h"
     47 #include "chrome/browser/chromeos/login/startup_utils.h"
     48 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
     49 #include "chrome/browser/chromeos/login/ui/oobe_display.h"
     50 #include "chrome/browser/chromeos/login/users/user_manager.h"
     51 #include "chrome/browser/chromeos/net/delay_network_call.h"
     52 #include "chrome/browser/chromeos/net/network_portal_detector.h"
     53 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
     54 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
     55 #include "chrome/browser/chromeos/settings/cros_settings.h"
     56 #include "chrome/browser/chromeos/timezone/timezone_provider.h"
     57 #include "chrome/browser/lifetime/application_lifetime.h"
     58 #include "chrome/browser/profiles/profile.h"
     59 #include "chrome/browser/profiles/profile_manager.h"
     60 #include "chrome/browser/ui/options/options_util.h"
     61 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
     62 #include "chrome/common/chrome_constants.h"
     63 #include "chrome/common/pref_names.h"
     64 #include "chromeos/audio/cras_audio_handler.h"
     65 #include "chromeos/chromeos_constants.h"
     66 #include "chromeos/chromeos_switches.h"
     67 #include "chromeos/dbus/dbus_thread_manager.h"
     68 #include "chromeos/dbus/session_manager_client.h"
     69 #include "chromeos/network/network_state.h"
     70 #include "chromeos/network/network_state_handler.h"
     71 #include "chromeos/settings/cros_settings_names.h"
     72 #include "chromeos/settings/timezone_settings.h"
     73 #include "components/breakpad/app/breakpad_linux.h"
     74 #include "content/public/browser/browser_thread.h"
     75 #include "content/public/browser/notification_types.h"
     76 #include "ui/base/accelerators/accelerator.h"
     77 #include "ui/base/l10n/l10n_util.h"
     78 
     79 using content::BrowserThread;
     80 
     81 namespace {
     82 // If reboot didn't happen, ask user to reboot device manually.
     83 const int kWaitForRebootTimeSec = 3;
     84 
     85 // Interval in ms which is used for smooth screen showing.
     86 static int kShowDelayMs = 400;
     87 
     88 // Total timezone resolving process timeout.
     89 const unsigned int kResolveTimeZoneTimeoutSeconds = 60;
     90 
     91 // Stores the list of all screens that should be shown when resuming OOBE.
     92 const char *kResumableScreens[] = {
     93   chromeos::WizardController::kNetworkScreenName,
     94   chromeos::WizardController::kUpdateScreenName,
     95   chromeos::WizardController::kEulaScreenName,
     96   chromeos::WizardController::kEnrollmentScreenName,
     97   chromeos::WizardController::kTermsOfServiceScreenName,
     98   chromeos::WizardController::kAutoEnrollmentCheckScreenName
     99 };
    100 
    101 // Checks flag for HID-detection screen show.
    102 bool CanShowHIDDetectionScreen() {
    103   return !CommandLine::ForCurrentProcess()->HasSwitch(
    104         chromeos::switches::kDisableHIDDetectionOnOOBE);
    105 }
    106 
    107 bool IsResumableScreen(const std::string& screen) {
    108   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kResumableScreens); ++i) {
    109     if (screen == kResumableScreens[i])
    110       return true;
    111   }
    112   return false;
    113 }
    114 
    115 }  // namespace
    116 
    117 namespace chromeos {
    118 
    119 const char WizardController::kNetworkScreenName[] = "network";
    120 const char WizardController::kLoginScreenName[] = "login";
    121 const char WizardController::kUpdateScreenName[] = "update";
    122 const char WizardController::kUserImageScreenName[] = "image";
    123 const char WizardController::kEulaScreenName[] = "eula";
    124 const char WizardController::kEnrollmentScreenName[] = "enroll";
    125 const char WizardController::kResetScreenName[] = "reset";
    126 const char WizardController::kKioskEnableScreenName[] = "kiosk-enable";
    127 const char WizardController::kKioskAutolaunchScreenName[] = "autolaunch";
    128 const char WizardController::kErrorScreenName[] = "error-message";
    129 const char WizardController::kTermsOfServiceScreenName[] = "tos";
    130 const char WizardController::kAutoEnrollmentCheckScreenName[] =
    131   "auto-enrollment-check";
    132 const char WizardController::kWrongHWIDScreenName[] = "wrong-hwid";
    133 const char WizardController::kLocallyManagedUserCreationScreenName[] =
    134   "locally-managed-user-creation-flow";
    135 const char WizardController::kAppLaunchSplashScreenName[] =
    136   "app-launch-splash";
    137 const char WizardController::kHIDDetectionScreenName[] = "hid-detection";
    138 
    139 // static
    140 const int WizardController::kMinAudibleOutputVolumePercent = 10;
    141 
    142 // Passing this parameter as a "first screen" initiates full OOBE flow.
    143 const char WizardController::kOutOfBoxScreenName[] = "oobe";
    144 
    145 // Special test value that commands not to create any window yet.
    146 const char WizardController::kTestNoScreenName[] = "test:nowindow";
    147 
    148 // Initialize default controller.
    149 // static
    150 WizardController* WizardController::default_controller_ = NULL;
    151 
    152 // static
    153 bool WizardController::skip_post_login_screens_ = false;
    154 
    155 // static
    156 bool WizardController::zero_delay_enabled_ = false;
    157 
    158 ///////////////////////////////////////////////////////////////////////////////
    159 // WizardController, public:
    160 
    161 PrefService* WizardController::local_state_for_testing_ = NULL;
    162 
    163 WizardController::WizardController(chromeos::LoginDisplayHost* host,
    164                                    chromeos::OobeDisplay* oobe_display)
    165     : current_screen_(NULL),
    166       previous_screen_(NULL),
    167 #if defined(GOOGLE_CHROME_BUILD)
    168       is_official_build_(true),
    169 #else
    170       is_official_build_(false),
    171 #endif
    172       is_out_of_box_(false),
    173       host_(host),
    174       oobe_display_(oobe_display),
    175       usage_statistics_reporting_(true),
    176       skip_update_enroll_after_eula_(false),
    177       enrollment_recovery_(ShouldRecoverEnrollment()),
    178       login_screen_started_(false),
    179       user_image_screen_return_to_previous_hack_(false),
    180       timezone_resolved_(false),
    181       weak_factory_(this) {
    182   DCHECK(default_controller_ == NULL);
    183   default_controller_ = this;
    184   AccessibilityManager* accessibility_manager = AccessibilityManager::Get();
    185   CHECK(accessibility_manager);
    186   accessibility_subscription_ = accessibility_manager->RegisterCallback(
    187       base::Bind(&WizardController::OnAccessibilityStatusChanged,
    188                  base::Unretained(this)));
    189 }
    190 
    191 WizardController::~WizardController() {
    192   if (default_controller_ == this) {
    193     default_controller_ = NULL;
    194   } else {
    195     NOTREACHED() << "More than one controller are alive.";
    196   }
    197 }
    198 
    199 void WizardController::Init(
    200     const std::string& first_screen_name,
    201     scoped_ptr<base::DictionaryValue> screen_parameters) {
    202   VLOG(1) << "Starting OOBE wizard with screen: " << first_screen_name;
    203   first_screen_name_ = first_screen_name;
    204   screen_parameters_ = screen_parameters.Pass();
    205 
    206   bool oobe_complete = StartupUtils::IsOobeCompleted();
    207   if (!oobe_complete || first_screen_name == kOutOfBoxScreenName)
    208     is_out_of_box_ = true;
    209 
    210   // This is a hacky way to check for local state corruption, because
    211   // it depends on the fact that the local state is loaded
    212   // synchroniously and at the first demand. IsEnterpriseManaged()
    213   // check is required because currently powerwash is disabled for
    214   // enterprise-entrolled devices.
    215   //
    216   // TODO (ygorshenin@): implement handling of the local state
    217   // corruption in the case of asynchronious loading.
    218   //
    219   // TODO (ygorshenin@): remove IsEnterpriseManaged() check once
    220   // crbug.com/241313 will be fixed.
    221   policy::BrowserPolicyConnectorChromeOS* connector =
    222       g_browser_process->platform_part()->browser_policy_connector_chromeos();
    223   if (!connector->IsEnterpriseManaged()) {
    224     const PrefService::PrefInitializationStatus status =
    225         GetLocalState()->GetInitializationStatus();
    226     if (status == PrefService::INITIALIZATION_STATUS_ERROR) {
    227       OnLocalStateInitialized(false);
    228       return;
    229     } else if (status == PrefService::INITIALIZATION_STATUS_WAITING) {
    230       GetLocalState()->AddPrefInitObserver(
    231           base::Bind(&WizardController::OnLocalStateInitialized,
    232                      weak_factory_.GetWeakPtr()));
    233     }
    234   }
    235 
    236   const std::string screen_pref =
    237       GetLocalState()->GetString(prefs::kOobeScreenPending);
    238   if (is_out_of_box_ && !screen_pref.empty() && (first_screen_name.empty() ||
    239       first_screen_name == WizardController::kTestNoScreenName)) {
    240     first_screen_name_ = screen_pref;
    241   }
    242 
    243   AdvanceToScreen(first_screen_name_);
    244   if (!IsMachineHWIDCorrect() && !StartupUtils::IsDeviceRegistered() &&
    245       first_screen_name_.empty())
    246     ShowWrongHWIDScreen();
    247 }
    248 
    249 chromeos::NetworkScreen* WizardController::GetNetworkScreen() {
    250   if (!network_screen_.get())
    251     network_screen_.reset(new chromeos::NetworkScreen(
    252         this, oobe_display_->GetNetworkScreenActor()));
    253   return network_screen_.get();
    254 }
    255 
    256 chromeos::UpdateScreen* WizardController::GetUpdateScreen() {
    257   if (!update_screen_.get()) {
    258     update_screen_.reset(new chromeos::UpdateScreen(
    259         this, oobe_display_->GetUpdateScreenActor()));
    260     update_screen_->SetRebootCheckDelay(kWaitForRebootTimeSec);
    261   }
    262   return update_screen_.get();
    263 }
    264 
    265 chromeos::UserImageScreen* WizardController::GetUserImageScreen() {
    266   if (!user_image_screen_.get())
    267     user_image_screen_.reset(
    268         new chromeos::UserImageScreen(
    269             this, oobe_display_->GetUserImageScreenActor()));
    270   return user_image_screen_.get();
    271 }
    272 
    273 chromeos::EulaScreen* WizardController::GetEulaScreen() {
    274   if (!eula_screen_.get())
    275     eula_screen_.reset(new chromeos::EulaScreen(
    276         this, oobe_display_->GetEulaScreenActor()));
    277   return eula_screen_.get();
    278 }
    279 
    280 chromeos::EnrollmentScreen*
    281     WizardController::GetEnrollmentScreen() {
    282   if (!enrollment_screen_.get()) {
    283     enrollment_screen_.reset(
    284         new chromeos::EnrollmentScreen(
    285             this, oobe_display_->GetEnrollmentScreenActor()));
    286   }
    287   return enrollment_screen_.get();
    288 }
    289 
    290 chromeos::ResetScreen* WizardController::GetResetScreen() {
    291   if (!reset_screen_.get()) {
    292     reset_screen_.reset(
    293         new chromeos::ResetScreen(this, oobe_display_->GetResetScreenActor()));
    294   }
    295   return reset_screen_.get();
    296 }
    297 
    298 chromeos::KioskEnableScreen* WizardController::GetKioskEnableScreen() {
    299   if (!kiosk_enable_screen_.get()) {
    300     kiosk_enable_screen_.reset(
    301         new chromeos::KioskEnableScreen(
    302             this,
    303             oobe_display_->GetKioskEnableScreenActor()));
    304   }
    305   return kiosk_enable_screen_.get();
    306 }
    307 
    308 chromeos::KioskAutolaunchScreen* WizardController::GetKioskAutolaunchScreen() {
    309   if (!autolaunch_screen_.get()) {
    310     autolaunch_screen_.reset(
    311         new chromeos::KioskAutolaunchScreen(
    312             this, oobe_display_->GetKioskAutolaunchScreenActor()));
    313   }
    314   return autolaunch_screen_.get();
    315 }
    316 
    317 chromeos::TermsOfServiceScreen* WizardController::GetTermsOfServiceScreen() {
    318   if (!terms_of_service_screen_.get()) {
    319     terms_of_service_screen_.reset(
    320         new chromeos::TermsOfServiceScreen(
    321             this, oobe_display_->GetTermsOfServiceScreenActor()));
    322   }
    323   return terms_of_service_screen_.get();
    324 }
    325 
    326 chromeos::WrongHWIDScreen* WizardController::GetWrongHWIDScreen() {
    327   if (!wrong_hwid_screen_.get()) {
    328     wrong_hwid_screen_.reset(
    329         new chromeos::WrongHWIDScreen(
    330             this, oobe_display_->GetWrongHWIDScreenActor()));
    331   }
    332   return wrong_hwid_screen_.get();
    333 }
    334 
    335 chromeos::AutoEnrollmentCheckScreen*
    336     WizardController::GetAutoEnrollmentCheckScreen() {
    337   if (!auto_enrollment_check_screen_.get()) {
    338     auto_enrollment_check_screen_.reset(
    339         new chromeos::AutoEnrollmentCheckScreen(
    340             this,
    341             oobe_display_->GetAutoEnrollmentCheckScreenActor()));
    342   }
    343   return auto_enrollment_check_screen_.get();
    344 }
    345 
    346 chromeos::LocallyManagedUserCreationScreen*
    347     WizardController::GetLocallyManagedUserCreationScreen() {
    348   if (!locally_managed_user_creation_screen_.get()) {
    349     locally_managed_user_creation_screen_.reset(
    350         new chromeos::LocallyManagedUserCreationScreen(
    351             this, oobe_display_->GetLocallyManagedUserCreationScreenActor()));
    352   }
    353   return locally_managed_user_creation_screen_.get();
    354 }
    355 
    356 chromeos::HIDDetectionScreen* WizardController::GetHIDDetectionScreen() {
    357   if (!hid_detection_screen_.get()) {
    358     hid_detection_screen_.reset(
    359         new chromeos::HIDDetectionScreen(
    360             this, oobe_display_->GetHIDDetectionScreenActor()));
    361   }
    362   return hid_detection_screen_.get();
    363 }
    364 
    365 void WizardController::ShowNetworkScreen() {
    366   VLOG(1) << "Showing network screen.";
    367   // Hide the status area initially; it only appears after OOBE first animates
    368   // in. Keep it visible if the user goes back to the existing network screen.
    369   SetStatusAreaVisible(network_screen_.get());
    370   SetCurrentScreen(GetNetworkScreen());
    371 }
    372 
    373 void WizardController::ShowLoginScreen(const LoginScreenContext& context) {
    374   if (!time_eula_accepted_.is_null()) {
    375     base::TimeDelta delta = base::Time::Now() - time_eula_accepted_;
    376     UMA_HISTOGRAM_MEDIUM_TIMES("OOBE.EULAToSignInTime", delta);
    377   }
    378   VLOG(1) << "Showing login screen.";
    379   SetStatusAreaVisible(true);
    380   host_->StartSignInScreen(context);
    381   smooth_show_timer_.Stop();
    382   oobe_display_ = NULL;
    383   login_screen_started_ = true;
    384 }
    385 
    386 void WizardController::ResumeLoginScreen() {
    387   VLOG(1) << "Resuming login screen.";
    388   SetStatusAreaVisible(true);
    389   host_->ResumeSignInScreen();
    390   smooth_show_timer_.Stop();
    391   oobe_display_ = NULL;
    392 }
    393 
    394 void WizardController::ShowUpdateScreen() {
    395   VLOG(1) << "Showing update screen.";
    396   SetStatusAreaVisible(true);
    397   SetCurrentScreen(GetUpdateScreen());
    398 }
    399 
    400 void WizardController::ShowUserImageScreen() {
    401   const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
    402   // Skip user image selection for public sessions and ephemeral logins.
    403   if (user_manager->IsLoggedInAsPublicAccount() ||
    404       user_manager->IsCurrentUserNonCryptohomeDataEphemeral()) {
    405     OnUserImageSkipped();
    406     return;
    407   }
    408   VLOG(1) << "Showing user image screen.";
    409 
    410   bool profile_picture_enabled = true;
    411   std::string user_id;
    412   if (screen_parameters_.get()) {
    413     screen_parameters_->GetBoolean("profile_picture_enabled",
    414         &profile_picture_enabled);
    415     screen_parameters_->GetString("user_id", &user_id);
    416   }
    417 
    418   // Status area has been already shown at sign in screen so it
    419   // doesn't make sense to hide it here and then show again at user session as
    420   // this produces undesired UX transitions.
    421   SetStatusAreaVisible(true);
    422 
    423   UserImageScreen* screen = GetUserImageScreen();
    424   if (!user_id.empty())
    425     screen->SetUserID(user_id);
    426   screen->SetProfilePictureEnabled(profile_picture_enabled);
    427 
    428   SetCurrentScreen(screen);
    429 }
    430 
    431 void WizardController::ShowEulaScreen() {
    432   VLOG(1) << "Showing EULA screen.";
    433   SetStatusAreaVisible(true);
    434   SetCurrentScreen(GetEulaScreen());
    435 }
    436 
    437 void WizardController::ShowEnrollmentScreen() {
    438   VLOG(1) << "Showing enrollment screen.";
    439 
    440   SetStatusAreaVisible(true);
    441 
    442   bool is_auto_enrollment = false;
    443   std::string user;
    444   if (screen_parameters_.get()) {
    445     screen_parameters_->GetBoolean("is_auto_enrollment", &is_auto_enrollment);
    446     screen_parameters_->GetString("user", &user);
    447   }
    448 
    449   EnrollmentScreenActor::EnrollmentMode mode =
    450       EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
    451   EnrollmentScreen* screen = GetEnrollmentScreen();
    452   std::string enrollment_domain = GetForcedEnrollmentDomain();
    453   if (is_auto_enrollment) {
    454     mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
    455   } else if (enrollment_recovery_) {
    456     mode = EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY;
    457     enrollment_domain = GetEnrollmentRecoveryDomain();
    458   } else if (ShouldAutoStartEnrollment() && !CanExitEnrollment()) {
    459     mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
    460   }
    461 
    462   screen->SetParameters(mode, enrollment_domain, user);
    463   SetCurrentScreen(screen);
    464 }
    465 
    466 void WizardController::ShowResetScreen() {
    467   VLOG(1) << "Showing reset screen.";
    468   SetStatusAreaVisible(false);
    469   SetCurrentScreen(GetResetScreen());
    470 }
    471 
    472 void WizardController::ShowKioskEnableScreen() {
    473   VLOG(1) << "Showing kiosk enable screen.";
    474   SetStatusAreaVisible(false);
    475   SetCurrentScreen(GetKioskEnableScreen());
    476 }
    477 
    478 void WizardController::ShowKioskAutolaunchScreen() {
    479   VLOG(1) << "Showing kiosk autolaunch screen.";
    480   SetStatusAreaVisible(false);
    481   SetCurrentScreen(GetKioskAutolaunchScreen());
    482 }
    483 
    484 void WizardController::ShowTermsOfServiceScreen() {
    485   // Only show the Terms of Service when logging into a public account and Terms
    486   // of Service have been specified through policy. In all other cases, advance
    487   // to the user image screen immediately.
    488   if (!chromeos::UserManager::Get()->IsLoggedInAsPublicAccount() ||
    489       !ProfileManager::GetActiveUserProfile()->GetPrefs()->
    490           IsManagedPreference(prefs::kTermsOfServiceURL)) {
    491     ShowUserImageScreen();
    492     return;
    493   }
    494 
    495   VLOG(1) << "Showing Terms of Service screen.";
    496   SetStatusAreaVisible(true);
    497   SetCurrentScreen(GetTermsOfServiceScreen());
    498 }
    499 
    500 void WizardController::ShowWrongHWIDScreen() {
    501   VLOG(1) << "Showing wrong HWID screen.";
    502   SetStatusAreaVisible(false);
    503   SetCurrentScreen(GetWrongHWIDScreen());
    504 }
    505 
    506 void WizardController::ShowAutoEnrollmentCheckScreen() {
    507   VLOG(1) << "Showing Auto-enrollment check screen.";
    508   SetStatusAreaVisible(true);
    509   AutoEnrollmentCheckScreen* screen = GetAutoEnrollmentCheckScreen();
    510   screen->set_auto_enrollment_controller(host_->GetAutoEnrollmentController());
    511   SetCurrentScreen(screen);
    512 }
    513 
    514 void WizardController::ShowLocallyManagedUserCreationScreen() {
    515   VLOG(1) << "Showing Locally managed user creation screen screen.";
    516   SetStatusAreaVisible(true);
    517   LocallyManagedUserCreationScreen* screen =
    518       GetLocallyManagedUserCreationScreen();
    519   SetCurrentScreen(screen);
    520 }
    521 
    522 void WizardController::ShowHIDDetectionScreen() {
    523   VLOG(1) << "Showing HID discovery screen.";
    524   SetStatusAreaVisible(true);
    525   SetCurrentScreen(GetHIDDetectionScreen());
    526 }
    527 
    528 void WizardController::SkipToLoginForTesting(
    529     const LoginScreenContext& context) {
    530   VLOG(1) << "SkipToLoginForTesting.";
    531   StartupUtils::MarkEulaAccepted();
    532   PerformPostEulaActions();
    533   OnOOBECompleted();
    534 }
    535 
    536 void WizardController::AddObserver(Observer* observer) {
    537   observer_list_.AddObserver(observer);
    538 }
    539 
    540 void WizardController::RemoveObserver(Observer* observer) {
    541   observer_list_.RemoveObserver(observer);
    542 }
    543 
    544 void WizardController::OnSessionStart() {
    545   FOR_EACH_OBSERVER(Observer, observer_list_, OnSessionStart());
    546 }
    547 
    548 void WizardController::SkipUpdateEnrollAfterEula() {
    549   skip_update_enroll_after_eula_ = true;
    550 }
    551 
    552 ///////////////////////////////////////////////////////////////////////////////
    553 // WizardController, ExitHandlers:
    554 void WizardController::OnHIDDetectionCompleted() {
    555   // Check for tests configuration.
    556   if (!StartupUtils::IsOobeCompleted())
    557     ShowNetworkScreen();
    558 }
    559 
    560 void WizardController::OnNetworkConnected() {
    561   if (is_official_build_) {
    562     if (!StartupUtils::IsEulaAccepted()) {
    563       ShowEulaScreen();
    564     } else {
    565       // Possible cases:
    566       // 1. EULA was accepted, forced shutdown/reboot during update.
    567       // 2. EULA was accepted, planned reboot after update.
    568       // Make sure that device is up-to-date.
    569       InitiateOOBEUpdate();
    570     }
    571   } else {
    572     InitiateOOBEUpdate();
    573   }
    574 }
    575 
    576 void WizardController::OnNetworkOffline() {
    577   // TODO(dpolukhin): if(is_out_of_box_) we cannot work offline and
    578   // should report some error message here and stay on the same screen.
    579   ShowLoginScreen(LoginScreenContext());
    580 }
    581 
    582 void WizardController::OnConnectionFailed() {
    583   // TODO(dpolukhin): show error message after login screen is displayed.
    584   ShowLoginScreen(LoginScreenContext());
    585 }
    586 
    587 void WizardController::OnUpdateCompleted() {
    588   ShowAutoEnrollmentCheckScreen();
    589 }
    590 
    591 void WizardController::OnEulaAccepted() {
    592   time_eula_accepted_ = base::Time::Now();
    593   StartupUtils::MarkEulaAccepted();
    594   bool uma_enabled =
    595       OptionsUtil::ResolveMetricsReportingEnabled(usage_statistics_reporting_);
    596 
    597   CrosSettings::Get()->SetBoolean(kStatsReportingPref, uma_enabled);
    598   if (uma_enabled) {
    599 #if defined(GOOGLE_CHROME_BUILD)
    600     // The crash reporter initialization needs IO to complete.
    601     base::ThreadRestrictions::ScopedAllowIO allow_io;
    602     breakpad::InitCrashReporter(std::string());
    603 #endif
    604   }
    605 
    606   if (skip_update_enroll_after_eula_) {
    607     PerformPostEulaActions();
    608     ShowAutoEnrollmentCheckScreen();
    609   } else {
    610     InitiateOOBEUpdate();
    611   }
    612 }
    613 
    614 void WizardController::OnUpdateErrorCheckingForUpdate() {
    615   // TODO(nkostylev): Update should be required during OOBE.
    616   // We do not want to block users from being able to proceed to the login
    617   // screen if there is any error checking for an update.
    618   // They could use "browse without sign-in" feature to set up the network to be
    619   // able to perform the update later.
    620   OnUpdateCompleted();
    621 }
    622 
    623 void WizardController::OnUpdateErrorUpdating() {
    624   // If there was an error while getting or applying the update,
    625   // return to network selection screen.
    626   // TODO(nkostylev): Show message to the user explaining update error.
    627   // TODO(nkostylev): Update should be required during OOBE.
    628   // Temporary fix, need to migrate to new API. http://crosbug.com/4321
    629   OnUpdateCompleted();
    630 }
    631 
    632 void WizardController::EnableUserImageScreenReturnToPreviousHack() {
    633   user_image_screen_return_to_previous_hack_ = true;
    634 }
    635 
    636 void WizardController::OnUserImageSelected() {
    637   if (user_image_screen_return_to_previous_hack_) {
    638     user_image_screen_return_to_previous_hack_ = false;
    639     DCHECK(previous_screen_);
    640     if (previous_screen_) {
    641       SetCurrentScreen(previous_screen_);
    642       return;
    643     }
    644   }
    645   // Launch browser and delete login host controller.
    646   BrowserThread::PostTask(
    647       BrowserThread::UI,
    648       FROM_HERE,
    649       base::Bind(&chromeos::LoginUtils::DoBrowserLaunch,
    650                  base::Unretained(chromeos::LoginUtils::Get()),
    651                  ProfileManager::GetActiveUserProfile(), host_));
    652   host_ = NULL;
    653 }
    654 
    655 void WizardController::OnUserImageSkipped() {
    656   OnUserImageSelected();
    657 }
    658 
    659 void WizardController::OnEnrollmentDone() {
    660   // Mark OOBE as completed only if enterprise enrollment was part of the
    661   // forced flow (i.e. app kiosk).
    662   if (ShouldAutoStartEnrollment() || enrollment_recovery_)
    663     PerformOOBECompletedActions();
    664 
    665   // TODO(mnissler): Unify the logic for auto-login for Public Sessions and
    666   // Kiosk Apps and make this code cover both cases: http://crbug.com/234694.
    667   if (KioskAppManager::Get()->IsAutoLaunchEnabled())
    668     AutoLaunchKioskApp();
    669   else
    670     ShowLoginScreen(LoginScreenContext());
    671 }
    672 
    673 void WizardController::OnResetCanceled() {
    674   if (previous_screen_) {
    675     SetCurrentScreen(previous_screen_);
    676   } else {
    677     ShowLoginScreen(LoginScreenContext());
    678   }
    679 }
    680 
    681 void WizardController::OnKioskAutolaunchCanceled() {
    682   ShowLoginScreen(LoginScreenContext());
    683 }
    684 
    685 void WizardController::OnKioskAutolaunchConfirmed() {
    686   DCHECK(KioskAppManager::Get()->IsAutoLaunchEnabled());
    687   AutoLaunchKioskApp();
    688 }
    689 
    690 void WizardController::OnKioskEnableCompleted() {
    691   ShowLoginScreen(LoginScreenContext());
    692 }
    693 
    694 void WizardController::OnWrongHWIDWarningSkipped() {
    695   if (previous_screen_)
    696     SetCurrentScreen(previous_screen_);
    697   else
    698     ShowLoginScreen(LoginScreenContext());
    699 }
    700 
    701 void WizardController::OnAutoEnrollmentDone() {
    702   VLOG(1) << "Automagic enrollment done, resuming previous signin";
    703   ResumeLoginScreen();
    704 }
    705 
    706 void WizardController::OnOOBECompleted() {
    707   if (ShouldAutoStartEnrollment() || enrollment_recovery_) {
    708     ShowEnrollmentScreen();
    709   } else {
    710     PerformOOBECompletedActions();
    711     ShowLoginScreen(LoginScreenContext());
    712   }
    713 }
    714 
    715 void WizardController::OnTermsOfServiceDeclined() {
    716   // If the user declines the Terms of Service, end the session and return to
    717   // the login screen.
    718   DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
    719 }
    720 
    721 void WizardController::OnTermsOfServiceAccepted() {
    722   // If the user accepts the Terms of Service, advance to the user image screen.
    723   ShowUserImageScreen();
    724 }
    725 
    726 void WizardController::InitiateOOBEUpdate() {
    727   PerformPostEulaActions();
    728   SetCurrentScreenSmooth(GetUpdateScreen(), true);
    729   GetUpdateScreen()->StartNetworkCheck();
    730 }
    731 
    732 void WizardController::StartTimezoneResolve() {
    733   geolocation_provider_.reset(new SimpleGeolocationProvider(
    734       g_browser_process->system_request_context(),
    735       SimpleGeolocationProvider::DefaultGeolocationProviderURL()));
    736   geolocation_provider_->RequestGeolocation(
    737       base::TimeDelta::FromSeconds(kResolveTimeZoneTimeoutSeconds),
    738       base::Bind(&WizardController::OnLocationResolved,
    739                  weak_factory_.GetWeakPtr()));
    740 }
    741 
    742 void WizardController::PerformPostEulaActions() {
    743   DelayNetworkCall(
    744       base::Bind(&WizardController::StartTimezoneResolve,
    745                  weak_factory_.GetWeakPtr()),
    746       base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS));
    747   DelayNetworkCall(
    748       ServicesCustomizationDocument::GetInstance()
    749           ->EnsureCustomizationAppliedClosure(),
    750       base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS));
    751 
    752   // Now that EULA has been accepted (for official builds), enable portal check.
    753   // ChromiumOS builds would go though this code path too.
    754   NetworkHandler::Get()->network_state_handler()->SetCheckPortalList(
    755       NetworkStateHandler::kDefaultCheckPortalList);
    756   host_->GetAutoEnrollmentController()->Start();
    757   host_->PrewarmAuthentication();
    758   NetworkPortalDetector::Get()->Enable(true);
    759 }
    760 
    761 void WizardController::PerformOOBECompletedActions() {
    762   StartupUtils::MarkOobeCompleted();
    763   UMA_HISTOGRAM_COUNTS_100(
    764       "HIDDetection.TimesDialogShownPerOOBECompleted",
    765       GetLocalState()->GetInteger(prefs::kTimesHIDDialogShown));
    766   GetLocalState()->ClearPref(prefs::kTimesHIDDialogShown);
    767 
    768   if (enrollment_recovery_)
    769     chrome::AttemptRestart();
    770 }
    771 
    772 void WizardController::SetCurrentScreen(WizardScreen* new_current) {
    773   SetCurrentScreenSmooth(new_current, false);
    774 }
    775 
    776 void WizardController::ShowCurrentScreen() {
    777   // ShowCurrentScreen may get called by smooth_show_timer_ even after
    778   // flow has been switched to sign in screen (ExistingUserController).
    779   if (!oobe_display_)
    780     return;
    781 
    782   // First remember how far have we reached so that we can resume if needed.
    783   if (is_out_of_box_ && IsResumableScreen(current_screen_->GetName()))
    784     StartupUtils::SaveOobePendingScreen(current_screen_->GetName());
    785 
    786   smooth_show_timer_.Stop();
    787 
    788   FOR_EACH_OBSERVER(Observer, observer_list_, OnScreenChanged(current_screen_));
    789 
    790   oobe_display_->ShowScreen(current_screen_);
    791 }
    792 
    793 void WizardController::SetCurrentScreenSmooth(WizardScreen* new_current,
    794                                               bool use_smoothing) {
    795   if (current_screen_ == new_current ||
    796       new_current == NULL ||
    797       oobe_display_ == NULL) {
    798     return;
    799   }
    800 
    801   smooth_show_timer_.Stop();
    802 
    803   if (current_screen_)
    804     oobe_display_->HideScreen(current_screen_);
    805 
    806   previous_screen_ = current_screen_;
    807   current_screen_ = new_current;
    808 
    809   if (use_smoothing) {
    810     smooth_show_timer_.Start(
    811         FROM_HERE,
    812         base::TimeDelta::FromMilliseconds(kShowDelayMs),
    813         this,
    814         &WizardController::ShowCurrentScreen);
    815   } else {
    816     ShowCurrentScreen();
    817   }
    818 }
    819 
    820 void WizardController::SetStatusAreaVisible(bool visible) {
    821   host_->SetStatusAreaVisible(visible);
    822 }
    823 
    824 void WizardController::AdvanceToScreen(const std::string& screen_name) {
    825   if (screen_name == kNetworkScreenName) {
    826     ShowNetworkScreen();
    827   } else if (screen_name == kLoginScreenName) {
    828     ShowLoginScreen(LoginScreenContext());
    829   } else if (screen_name == kUpdateScreenName) {
    830     InitiateOOBEUpdate();
    831   } else if (screen_name == kUserImageScreenName) {
    832     ShowUserImageScreen();
    833   } else if (screen_name == kEulaScreenName) {
    834     ShowEulaScreen();
    835   } else if (screen_name == kResetScreenName) {
    836     ShowResetScreen();
    837   } else if (screen_name == kKioskEnableScreenName) {
    838     ShowKioskEnableScreen();
    839   } else if (screen_name == kKioskAutolaunchScreenName) {
    840     ShowKioskAutolaunchScreen();
    841   } else if (screen_name == kEnrollmentScreenName) {
    842     ShowEnrollmentScreen();
    843   } else if (screen_name == kTermsOfServiceScreenName) {
    844     ShowTermsOfServiceScreen();
    845   } else if (screen_name == kWrongHWIDScreenName) {
    846     ShowWrongHWIDScreen();
    847   } else if (screen_name == kAutoEnrollmentCheckScreenName) {
    848     ShowAutoEnrollmentCheckScreen();
    849   } else if (screen_name == kLocallyManagedUserCreationScreenName) {
    850     ShowLocallyManagedUserCreationScreen();
    851   } else if (screen_name == kAppLaunchSplashScreenName) {
    852     AutoLaunchKioskApp();
    853   } else if (screen_name == kHIDDetectionScreenName) {
    854     ShowHIDDetectionScreen();
    855   } else if (screen_name != kTestNoScreenName) {
    856     if (is_out_of_box_) {
    857       if (CanShowHIDDetectionScreen())
    858         ShowHIDDetectionScreen();
    859       else
    860         ShowNetworkScreen();
    861     } else {
    862       ShowLoginScreen(LoginScreenContext());
    863     }
    864   }
    865 }
    866 
    867 ///////////////////////////////////////////////////////////////////////////////
    868 // WizardController, chromeos::ScreenObserver overrides:
    869 void WizardController::OnExit(ExitCodes exit_code) {
    870   VLOG(1) << "Wizard screen exit code: " << exit_code;
    871   switch (exit_code) {
    872     case HID_DETECTION_COMPLETED:
    873       OnHIDDetectionCompleted();
    874       break;
    875     case NETWORK_CONNECTED:
    876       OnNetworkConnected();
    877       break;
    878     case CONNECTION_FAILED:
    879       OnConnectionFailed();
    880       break;
    881     case UPDATE_INSTALLED:
    882     case UPDATE_NOUPDATE:
    883       OnUpdateCompleted();
    884       break;
    885     case UPDATE_ERROR_CHECKING_FOR_UPDATE:
    886       OnUpdateErrorCheckingForUpdate();
    887       break;
    888     case UPDATE_ERROR_UPDATING:
    889       OnUpdateErrorUpdating();
    890       break;
    891     case USER_IMAGE_SELECTED:
    892       OnUserImageSelected();
    893       break;
    894     case EULA_ACCEPTED:
    895       OnEulaAccepted();
    896       break;
    897     case EULA_BACK:
    898       ShowNetworkScreen();
    899       break;
    900     case ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED:
    901       if (skip_update_enroll_after_eula_)
    902         ShowEnrollmentScreen();
    903       else
    904         OnOOBECompleted();
    905       break;
    906     case ENTERPRISE_ENROLLMENT_COMPLETED:
    907       OnEnrollmentDone();
    908       break;
    909     case ENTERPRISE_ENROLLMENT_BACK:
    910       ShowNetworkScreen();
    911       break;
    912     case RESET_CANCELED:
    913       OnResetCanceled();
    914       break;
    915     case KIOSK_AUTOLAUNCH_CANCELED:
    916       OnKioskAutolaunchCanceled();
    917       break;
    918     case KIOSK_AUTOLAUNCH_CONFIRMED:
    919       OnKioskAutolaunchConfirmed();
    920       break;
    921     case KIOSK_ENABLE_COMPLETED:
    922       OnKioskEnableCompleted();
    923       break;
    924     case ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED:
    925       OnAutoEnrollmentDone();
    926       break;
    927     case TERMS_OF_SERVICE_DECLINED:
    928       OnTermsOfServiceDeclined();
    929       break;
    930     case TERMS_OF_SERVICE_ACCEPTED:
    931       OnTermsOfServiceAccepted();
    932       break;
    933     case WRONG_HWID_WARNING_SKIPPED:
    934       OnWrongHWIDWarningSkipped();
    935       break;
    936     default:
    937       NOTREACHED();
    938   }
    939 }
    940 
    941 void WizardController::OnSetUserNamePassword(const std::string& username,
    942                                              const std::string& password) {
    943   username_ = username;
    944   password_ = password;
    945 }
    946 
    947 void WizardController::SetUsageStatisticsReporting(bool val) {
    948   usage_statistics_reporting_ = val;
    949 }
    950 
    951 bool WizardController::GetUsageStatisticsReporting() const {
    952   return usage_statistics_reporting_;
    953 }
    954 
    955 chromeos::ErrorScreen* WizardController::GetErrorScreen() {
    956   if (!error_screen_.get()) {
    957     error_screen_.reset(
    958         new chromeos::ErrorScreen(this, oobe_display_->GetErrorScreenActor()));
    959   }
    960   return error_screen_.get();
    961 }
    962 
    963 void WizardController::ShowErrorScreen() {
    964   VLOG(1) << "Showing error screen.";
    965   SetCurrentScreen(GetErrorScreen());
    966 }
    967 
    968 void WizardController::HideErrorScreen(WizardScreen* parent_screen) {
    969   DCHECK(parent_screen);
    970   VLOG(1) << "Hiding error screen.";
    971   SetCurrentScreen(parent_screen);
    972 }
    973 
    974 void WizardController::OnAccessibilityStatusChanged(
    975     const AccessibilityStatusEventDetails& details) {
    976   enum AccessibilityNotificationType type = details.notification_type;
    977   if (type == ACCESSIBILITY_MANAGER_SHUTDOWN) {
    978     accessibility_subscription_.reset();
    979     return;
    980   } else if (type != ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK || !details.enabled) {
    981     return;
    982   }
    983 
    984   CrasAudioHandler* cras = CrasAudioHandler::Get();
    985   if (cras->IsOutputMuted()) {
    986     cras->SetOutputMute(false);
    987     cras->SetOutputVolumePercent(kMinAudibleOutputVolumePercent);
    988   } else if (cras->GetOutputVolumePercent() < kMinAudibleOutputVolumePercent) {
    989     cras->SetOutputVolumePercent(kMinAudibleOutputVolumePercent);
    990   }
    991 }
    992 
    993 void WizardController::AutoLaunchKioskApp() {
    994   KioskAppManager::App app_data;
    995   std::string app_id = KioskAppManager::Get()->GetAutoLaunchApp();
    996   CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data));
    997 
    998   host_->StartAppLaunch(app_id, false /* diagnostic_mode */);
    999 }
   1000 
   1001 // static
   1002 void WizardController::SetZeroDelays() {
   1003   kShowDelayMs = 0;
   1004   zero_delay_enabled_ = true;
   1005 }
   1006 
   1007 // static
   1008 bool WizardController::IsZeroDelayEnabled() {
   1009   return zero_delay_enabled_;
   1010 }
   1011 
   1012 // static
   1013 void WizardController::SkipPostLoginScreensForTesting() {
   1014   skip_post_login_screens_ = true;
   1015 }
   1016 
   1017 // static
   1018 bool WizardController::ShouldAutoStartEnrollment() {
   1019   policy::BrowserPolicyConnectorChromeOS* connector =
   1020       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1021   return connector->GetDeviceCloudPolicyManager()->ShouldAutoStartEnrollment();
   1022 }
   1023 
   1024 // static
   1025 bool WizardController::ShouldRecoverEnrollment() {
   1026   policy::BrowserPolicyConnectorChromeOS* connector =
   1027       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1028   return connector->GetDeviceCloudPolicyManager()->ShouldRecoverEnrollment();
   1029 }
   1030 
   1031 // static
   1032 std::string WizardController::GetEnrollmentRecoveryDomain() {
   1033   policy::BrowserPolicyConnectorChromeOS* connector =
   1034       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1035   return
   1036       connector->GetDeviceCloudPolicyManager()->GetEnrollmentRecoveryDomain();
   1037 }
   1038 
   1039 // static
   1040 bool WizardController::CanExitEnrollment() {
   1041   policy::BrowserPolicyConnectorChromeOS* connector =
   1042       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1043   return connector->GetDeviceCloudPolicyManager()->CanExitEnrollment();
   1044 }
   1045 
   1046 // static
   1047 std::string WizardController::GetForcedEnrollmentDomain() {
   1048   policy::BrowserPolicyConnectorChromeOS* connector =
   1049       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1050   return connector->GetDeviceCloudPolicyManager()->GetForcedEnrollmentDomain();
   1051 }
   1052 
   1053 void WizardController::OnLocalStateInitialized(bool /* succeeded */) {
   1054   if (GetLocalState()->GetInitializationStatus() !=
   1055       PrefService::INITIALIZATION_STATUS_ERROR) {
   1056     return;
   1057   }
   1058   GetErrorScreen()->SetUIState(ErrorScreen::UI_STATE_LOCAL_STATE_ERROR);
   1059   SetStatusAreaVisible(false);
   1060   ShowErrorScreen();
   1061 }
   1062 
   1063 PrefService* WizardController::GetLocalState() {
   1064   if (local_state_for_testing_)
   1065     return local_state_for_testing_;
   1066   return g_browser_process->local_state();
   1067 }
   1068 
   1069 void WizardController::OnTimezoneResolved(
   1070     scoped_ptr<TimeZoneResponseData> timezone,
   1071     bool server_error) {
   1072   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1073   DCHECK(timezone.get());
   1074   // To check that "this" is not destroyed try to access some member
   1075   // (timezone_provider_) in this case. Expect crash here.
   1076   DCHECK(timezone_provider_.get());
   1077 
   1078   timezone_resolved_ = true;
   1079   base::ScopedClosureRunner inform_test(on_timezone_resolved_for_testing_);
   1080   on_timezone_resolved_for_testing_.Reset();
   1081 
   1082   VLOG(1) << "Resolved local timezone={" << timezone->ToStringForDebug()
   1083           << "}.";
   1084 
   1085   if (timezone->status != TimeZoneResponseData::OK) {
   1086     LOG(WARNING) << "Resolve TimeZone: failed to resolve timezone.";
   1087     return;
   1088   }
   1089 
   1090   policy::BrowserPolicyConnectorChromeOS* connector =
   1091       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1092   if (connector->IsEnterpriseManaged()) {
   1093     std::string policy_timezone;
   1094     if (chromeos::CrosSettings::Get()->GetString(
   1095             chromeos::kSystemTimezonePolicy, &policy_timezone) &&
   1096         !policy_timezone.empty()) {
   1097       VLOG(1) << "Resolve TimeZone: TimeZone settings are overridden"
   1098               << " by DevicePolicy.";
   1099       return;
   1100     }
   1101   }
   1102 
   1103   if (!timezone->timeZoneId.empty()) {
   1104     VLOG(1) << "Resolve TimeZone: setting timezone to '" << timezone->timeZoneId
   1105             << "'";
   1106 
   1107     chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
   1108         base::UTF8ToUTF16(timezone->timeZoneId));
   1109   }
   1110 }
   1111 
   1112 TimeZoneProvider* WizardController::GetTimezoneProvider() {
   1113   if (!timezone_provider_) {
   1114     timezone_provider_.reset(
   1115         new TimeZoneProvider(g_browser_process->system_request_context(),
   1116                              DefaultTimezoneProviderURL()));
   1117   }
   1118   return timezone_provider_.get();
   1119 }
   1120 
   1121 void WizardController::OnLocationResolved(const Geoposition& position,
   1122                                           bool server_error,
   1123                                           const base::TimeDelta elapsed) {
   1124   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1125 
   1126   const base::TimeDelta timeout =
   1127       base::TimeDelta::FromSeconds(kResolveTimeZoneTimeoutSeconds);
   1128   // Ignore invalid position.
   1129   if (!position.Valid())
   1130     return;
   1131 
   1132   if (elapsed >= timeout) {
   1133     LOG(WARNING) << "Resolve TimeZone: got location after timeout ("
   1134                  << elapsed.InSecondsF() << " seconds elapsed). Ignored.";
   1135     return;
   1136   }
   1137 
   1138   // WizardController owns TimezoneProvider, so timezone request is silently
   1139   // cancelled on destruction.
   1140   GetTimezoneProvider()->RequestTimezone(
   1141       position,
   1142       false,  // sensor
   1143       timeout - elapsed,
   1144       base::Bind(&WizardController::OnTimezoneResolved,
   1145                  base::Unretained(this)));
   1146 }
   1147 
   1148 bool WizardController::SetOnTimeZoneResolvedForTesting(
   1149     const base::Closure& callback) {
   1150   if (timezone_resolved_)
   1151     return false;
   1152 
   1153   on_timezone_resolved_for_testing_ = callback;
   1154   return true;
   1155 }
   1156 
   1157 }  // namespace chromeos
   1158