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