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.
CanShowHIDDetectionScreen()102 bool CanShowHIDDetectionScreen() {
103 return !CommandLine::ForCurrentProcess()->HasSwitch(
104 chromeos::switches::kDisableHIDDetectionOnOOBE);
105 }
106
IsResumableScreen(const std::string & screen)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
WizardController(chromeos::LoginDisplayHost * host,chromeos::OobeDisplay * oobe_display)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
~WizardController()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
Init(const std::string & first_screen_name,scoped_ptr<base::DictionaryValue> screen_parameters)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
GetNetworkScreen()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
GetUpdateScreen()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
GetUserImageScreen()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
GetEulaScreen()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*
GetEnrollmentScreen()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
GetResetScreen()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
GetKioskEnableScreen()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
GetKioskAutolaunchScreen()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
GetTermsOfServiceScreen()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
GetWrongHWIDScreen()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*
GetAutoEnrollmentCheckScreen()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*
GetLocallyManagedUserCreationScreen()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
GetHIDDetectionScreen()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
ShowNetworkScreen()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
ShowLoginScreen(const LoginScreenContext & context)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
ResumeLoginScreen()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
ShowUpdateScreen()394 void WizardController::ShowUpdateScreen() {
395 VLOG(1) << "Showing update screen.";
396 SetStatusAreaVisible(true);
397 SetCurrentScreen(GetUpdateScreen());
398 }
399
ShowUserImageScreen()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
ShowEulaScreen()431 void WizardController::ShowEulaScreen() {
432 VLOG(1) << "Showing EULA screen.";
433 SetStatusAreaVisible(true);
434 SetCurrentScreen(GetEulaScreen());
435 }
436
ShowEnrollmentScreen()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
ShowResetScreen()466 void WizardController::ShowResetScreen() {
467 VLOG(1) << "Showing reset screen.";
468 SetStatusAreaVisible(false);
469 SetCurrentScreen(GetResetScreen());
470 }
471
ShowKioskEnableScreen()472 void WizardController::ShowKioskEnableScreen() {
473 VLOG(1) << "Showing kiosk enable screen.";
474 SetStatusAreaVisible(false);
475 SetCurrentScreen(GetKioskEnableScreen());
476 }
477
ShowKioskAutolaunchScreen()478 void WizardController::ShowKioskAutolaunchScreen() {
479 VLOG(1) << "Showing kiosk autolaunch screen.";
480 SetStatusAreaVisible(false);
481 SetCurrentScreen(GetKioskAutolaunchScreen());
482 }
483
ShowTermsOfServiceScreen()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
ShowWrongHWIDScreen()500 void WizardController::ShowWrongHWIDScreen() {
501 VLOG(1) << "Showing wrong HWID screen.";
502 SetStatusAreaVisible(false);
503 SetCurrentScreen(GetWrongHWIDScreen());
504 }
505
ShowAutoEnrollmentCheckScreen()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
ShowLocallyManagedUserCreationScreen()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
ShowHIDDetectionScreen()522 void WizardController::ShowHIDDetectionScreen() {
523 VLOG(1) << "Showing HID discovery screen.";
524 SetStatusAreaVisible(true);
525 SetCurrentScreen(GetHIDDetectionScreen());
526 }
527
SkipToLoginForTesting(const LoginScreenContext & context)528 void WizardController::SkipToLoginForTesting(
529 const LoginScreenContext& context) {
530 VLOG(1) << "SkipToLoginForTesting.";
531 StartupUtils::MarkEulaAccepted();
532 PerformPostEulaActions();
533 OnOOBECompleted();
534 }
535
AddObserver(Observer * observer)536 void WizardController::AddObserver(Observer* observer) {
537 observer_list_.AddObserver(observer);
538 }
539
RemoveObserver(Observer * observer)540 void WizardController::RemoveObserver(Observer* observer) {
541 observer_list_.RemoveObserver(observer);
542 }
543
OnSessionStart()544 void WizardController::OnSessionStart() {
545 FOR_EACH_OBSERVER(Observer, observer_list_, OnSessionStart());
546 }
547
SkipUpdateEnrollAfterEula()548 void WizardController::SkipUpdateEnrollAfterEula() {
549 skip_update_enroll_after_eula_ = true;
550 }
551
552 ///////////////////////////////////////////////////////////////////////////////
553 // WizardController, ExitHandlers:
OnHIDDetectionCompleted()554 void WizardController::OnHIDDetectionCompleted() {
555 // Check for tests configuration.
556 if (!StartupUtils::IsOobeCompleted())
557 ShowNetworkScreen();
558 }
559
OnNetworkConnected()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
OnNetworkOffline()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
OnConnectionFailed()582 void WizardController::OnConnectionFailed() {
583 // TODO(dpolukhin): show error message after login screen is displayed.
584 ShowLoginScreen(LoginScreenContext());
585 }
586
OnUpdateCompleted()587 void WizardController::OnUpdateCompleted() {
588 ShowAutoEnrollmentCheckScreen();
589 }
590
OnEulaAccepted()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
OnUpdateErrorCheckingForUpdate()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
OnUpdateErrorUpdating()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
EnableUserImageScreenReturnToPreviousHack()632 void WizardController::EnableUserImageScreenReturnToPreviousHack() {
633 user_image_screen_return_to_previous_hack_ = true;
634 }
635
OnUserImageSelected()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
OnUserImageSkipped()655 void WizardController::OnUserImageSkipped() {
656 OnUserImageSelected();
657 }
658
OnEnrollmentDone()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
OnResetCanceled()673 void WizardController::OnResetCanceled() {
674 if (previous_screen_) {
675 SetCurrentScreen(previous_screen_);
676 } else {
677 ShowLoginScreen(LoginScreenContext());
678 }
679 }
680
OnKioskAutolaunchCanceled()681 void WizardController::OnKioskAutolaunchCanceled() {
682 ShowLoginScreen(LoginScreenContext());
683 }
684
OnKioskAutolaunchConfirmed()685 void WizardController::OnKioskAutolaunchConfirmed() {
686 DCHECK(KioskAppManager::Get()->IsAutoLaunchEnabled());
687 AutoLaunchKioskApp();
688 }
689
OnKioskEnableCompleted()690 void WizardController::OnKioskEnableCompleted() {
691 ShowLoginScreen(LoginScreenContext());
692 }
693
OnWrongHWIDWarningSkipped()694 void WizardController::OnWrongHWIDWarningSkipped() {
695 if (previous_screen_)
696 SetCurrentScreen(previous_screen_);
697 else
698 ShowLoginScreen(LoginScreenContext());
699 }
700
OnAutoEnrollmentDone()701 void WizardController::OnAutoEnrollmentDone() {
702 VLOG(1) << "Automagic enrollment done, resuming previous signin";
703 ResumeLoginScreen();
704 }
705
OnOOBECompleted()706 void WizardController::OnOOBECompleted() {
707 if (ShouldAutoStartEnrollment() || enrollment_recovery_) {
708 ShowEnrollmentScreen();
709 } else {
710 PerformOOBECompletedActions();
711 ShowLoginScreen(LoginScreenContext());
712 }
713 }
714
OnTermsOfServiceDeclined()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
OnTermsOfServiceAccepted()721 void WizardController::OnTermsOfServiceAccepted() {
722 // If the user accepts the Terms of Service, advance to the user image screen.
723 ShowUserImageScreen();
724 }
725
InitiateOOBEUpdate()726 void WizardController::InitiateOOBEUpdate() {
727 PerformPostEulaActions();
728 SetCurrentScreenSmooth(GetUpdateScreen(), true);
729 GetUpdateScreen()->StartNetworkCheck();
730 }
731
StartTimezoneResolve()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
PerformPostEulaActions()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
PerformOOBECompletedActions()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
SetCurrentScreen(WizardScreen * new_current)772 void WizardController::SetCurrentScreen(WizardScreen* new_current) {
773 SetCurrentScreenSmooth(new_current, false);
774 }
775
ShowCurrentScreen()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
SetCurrentScreenSmooth(WizardScreen * new_current,bool use_smoothing)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
SetStatusAreaVisible(bool visible)820 void WizardController::SetStatusAreaVisible(bool visible) {
821 host_->SetStatusAreaVisible(visible);
822 }
823
AdvanceToScreen(const std::string & screen_name)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:
OnExit(ExitCodes exit_code)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
OnSetUserNamePassword(const std::string & username,const std::string & password)941 void WizardController::OnSetUserNamePassword(const std::string& username,
942 const std::string& password) {
943 username_ = username;
944 password_ = password;
945 }
946
SetUsageStatisticsReporting(bool val)947 void WizardController::SetUsageStatisticsReporting(bool val) {
948 usage_statistics_reporting_ = val;
949 }
950
GetUsageStatisticsReporting() const951 bool WizardController::GetUsageStatisticsReporting() const {
952 return usage_statistics_reporting_;
953 }
954
GetErrorScreen()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
ShowErrorScreen()963 void WizardController::ShowErrorScreen() {
964 VLOG(1) << "Showing error screen.";
965 SetCurrentScreen(GetErrorScreen());
966 }
967
HideErrorScreen(WizardScreen * parent_screen)968 void WizardController::HideErrorScreen(WizardScreen* parent_screen) {
969 DCHECK(parent_screen);
970 VLOG(1) << "Hiding error screen.";
971 SetCurrentScreen(parent_screen);
972 }
973
OnAccessibilityStatusChanged(const AccessibilityStatusEventDetails & details)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
AutoLaunchKioskApp()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
SetZeroDelays()1002 void WizardController::SetZeroDelays() {
1003 kShowDelayMs = 0;
1004 zero_delay_enabled_ = true;
1005 }
1006
1007 // static
IsZeroDelayEnabled()1008 bool WizardController::IsZeroDelayEnabled() {
1009 return zero_delay_enabled_;
1010 }
1011
1012 // static
SkipPostLoginScreensForTesting()1013 void WizardController::SkipPostLoginScreensForTesting() {
1014 skip_post_login_screens_ = true;
1015 }
1016
1017 // static
ShouldAutoStartEnrollment()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
ShouldRecoverEnrollment()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
GetEnrollmentRecoveryDomain()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
CanExitEnrollment()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
GetForcedEnrollmentDomain()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
OnLocalStateInitialized(bool)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
GetLocalState()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
OnTimezoneResolved(scoped_ptr<TimeZoneResponseData> timezone,bool server_error)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
GetTimezoneProvider()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
OnLocationResolved(const Geoposition & position,bool server_error,const base::TimeDelta elapsed)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
SetOnTimeZoneResolvedForTesting(const base::Closure & callback)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