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
79using content::BrowserThread;
80
81namespace {
82// If reboot didn't happen, ask user to reboot device manually.
83const int kWaitForRebootTimeSec = 3;
84
85// Interval in ms which is used for smooth screen showing.
86static int kShowDelayMs = 400;
87
88// Total timezone resolving process timeout.
89const unsigned int kResolveTimeZoneTimeoutSeconds = 60;
90
91// Stores the list of all screens that should be shown when resuming OOBE.
92const 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.
102bool CanShowHIDDetectionScreen() {
103  return !CommandLine::ForCurrentProcess()->HasSwitch(
104        chromeos::switches::kDisableHIDDetectionOnOOBE);
105}
106
107bool 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
117namespace chromeos {
118
119const char WizardController::kNetworkScreenName[] = "network";
120const char WizardController::kLoginScreenName[] = "login";
121const char WizardController::kUpdateScreenName[] = "update";
122const char WizardController::kUserImageScreenName[] = "image";
123const char WizardController::kEulaScreenName[] = "eula";
124const char WizardController::kEnrollmentScreenName[] = "enroll";
125const char WizardController::kResetScreenName[] = "reset";
126const char WizardController::kKioskEnableScreenName[] = "kiosk-enable";
127const char WizardController::kKioskAutolaunchScreenName[] = "autolaunch";
128const char WizardController::kErrorScreenName[] = "error-message";
129const char WizardController::kTermsOfServiceScreenName[] = "tos";
130const char WizardController::kAutoEnrollmentCheckScreenName[] =
131  "auto-enrollment-check";
132const char WizardController::kWrongHWIDScreenName[] = "wrong-hwid";
133const char WizardController::kLocallyManagedUserCreationScreenName[] =
134  "locally-managed-user-creation-flow";
135const char WizardController::kAppLaunchSplashScreenName[] =
136  "app-launch-splash";
137const char WizardController::kHIDDetectionScreenName[] = "hid-detection";
138
139// static
140const int WizardController::kMinAudibleOutputVolumePercent = 10;
141
142// Passing this parameter as a "first screen" initiates full OOBE flow.
143const char WizardController::kOutOfBoxScreenName[] = "oobe";
144
145// Special test value that commands not to create any window yet.
146const char WizardController::kTestNoScreenName[] = "test:nowindow";
147
148// Initialize default controller.
149// static
150WizardController* WizardController::default_controller_ = NULL;
151
152// static
153bool WizardController::skip_post_login_screens_ = false;
154
155// static
156bool WizardController::zero_delay_enabled_ = false;
157
158///////////////////////////////////////////////////////////////////////////////
159// WizardController, public:
160
161PrefService* WizardController::local_state_for_testing_ = NULL;
162
163WizardController::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
191WizardController::~WizardController() {
192  if (default_controller_ == this) {
193    default_controller_ = NULL;
194  } else {
195    NOTREACHED() << "More than one controller are alive.";
196  }
197}
198
199void 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
249chromeos::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
256chromeos::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
265chromeos::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
273chromeos::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
280chromeos::EnrollmentScreen*
281    WizardController::GetEnrollmentScreen() {
282  if (!enrollment_screen_.get()) {
283    enrollment_screen_.reset(
284        new chromeos::EnrollmentScreen(
285            this, oobe_display_->GetEnrollmentScreenActor()));
286  }
287  return enrollment_screen_.get();
288}
289
290chromeos::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
298chromeos::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
308chromeos::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
317chromeos::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
326chromeos::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
335chromeos::AutoEnrollmentCheckScreen*
336    WizardController::GetAutoEnrollmentCheckScreen() {
337  if (!auto_enrollment_check_screen_.get()) {
338    auto_enrollment_check_screen_.reset(
339        new chromeos::AutoEnrollmentCheckScreen(
340            this,
341            oobe_display_->GetAutoEnrollmentCheckScreenActor()));
342  }
343  return auto_enrollment_check_screen_.get();
344}
345
346chromeos::LocallyManagedUserCreationScreen*
347    WizardController::GetLocallyManagedUserCreationScreen() {
348  if (!locally_managed_user_creation_screen_.get()) {
349    locally_managed_user_creation_screen_.reset(
350        new chromeos::LocallyManagedUserCreationScreen(
351            this, oobe_display_->GetLocallyManagedUserCreationScreenActor()));
352  }
353  return locally_managed_user_creation_screen_.get();
354}
355
356chromeos::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
365void 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
373void 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
386void 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
394void WizardController::ShowUpdateScreen() {
395  VLOG(1) << "Showing update screen.";
396  SetStatusAreaVisible(true);
397  SetCurrentScreen(GetUpdateScreen());
398}
399
400void 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
431void WizardController::ShowEulaScreen() {
432  VLOG(1) << "Showing EULA screen.";
433  SetStatusAreaVisible(true);
434  SetCurrentScreen(GetEulaScreen());
435}
436
437void 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
466void WizardController::ShowResetScreen() {
467  VLOG(1) << "Showing reset screen.";
468  SetStatusAreaVisible(false);
469  SetCurrentScreen(GetResetScreen());
470}
471
472void WizardController::ShowKioskEnableScreen() {
473  VLOG(1) << "Showing kiosk enable screen.";
474  SetStatusAreaVisible(false);
475  SetCurrentScreen(GetKioskEnableScreen());
476}
477
478void WizardController::ShowKioskAutolaunchScreen() {
479  VLOG(1) << "Showing kiosk autolaunch screen.";
480  SetStatusAreaVisible(false);
481  SetCurrentScreen(GetKioskAutolaunchScreen());
482}
483
484void 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
500void WizardController::ShowWrongHWIDScreen() {
501  VLOG(1) << "Showing wrong HWID screen.";
502  SetStatusAreaVisible(false);
503  SetCurrentScreen(GetWrongHWIDScreen());
504}
505
506void 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
514void 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
522void WizardController::ShowHIDDetectionScreen() {
523  VLOG(1) << "Showing HID discovery screen.";
524  SetStatusAreaVisible(true);
525  SetCurrentScreen(GetHIDDetectionScreen());
526}
527
528void WizardController::SkipToLoginForTesting(
529    const LoginScreenContext& context) {
530  VLOG(1) << "SkipToLoginForTesting.";
531  StartupUtils::MarkEulaAccepted();
532  PerformPostEulaActions();
533  OnOOBECompleted();
534}
535
536void WizardController::AddObserver(Observer* observer) {
537  observer_list_.AddObserver(observer);
538}
539
540void WizardController::RemoveObserver(Observer* observer) {
541  observer_list_.RemoveObserver(observer);
542}
543
544void WizardController::OnSessionStart() {
545  FOR_EACH_OBSERVER(Observer, observer_list_, OnSessionStart());
546}
547
548void WizardController::SkipUpdateEnrollAfterEula() {
549  skip_update_enroll_after_eula_ = true;
550}
551
552///////////////////////////////////////////////////////////////////////////////
553// WizardController, ExitHandlers:
554void WizardController::OnHIDDetectionCompleted() {
555  // Check for tests configuration.
556  if (!StartupUtils::IsOobeCompleted())
557    ShowNetworkScreen();
558}
559
560void 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
576void 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
582void WizardController::OnConnectionFailed() {
583  // TODO(dpolukhin): show error message after login screen is displayed.
584  ShowLoginScreen(LoginScreenContext());
585}
586
587void WizardController::OnUpdateCompleted() {
588  ShowAutoEnrollmentCheckScreen();
589}
590
591void 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
614void 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
623void 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
632void WizardController::EnableUserImageScreenReturnToPreviousHack() {
633  user_image_screen_return_to_previous_hack_ = true;
634}
635
636void 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
655void WizardController::OnUserImageSkipped() {
656  OnUserImageSelected();
657}
658
659void 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
673void WizardController::OnResetCanceled() {
674  if (previous_screen_) {
675    SetCurrentScreen(previous_screen_);
676  } else {
677    ShowLoginScreen(LoginScreenContext());
678  }
679}
680
681void WizardController::OnKioskAutolaunchCanceled() {
682  ShowLoginScreen(LoginScreenContext());
683}
684
685void WizardController::OnKioskAutolaunchConfirmed() {
686  DCHECK(KioskAppManager::Get()->IsAutoLaunchEnabled());
687  AutoLaunchKioskApp();
688}
689
690void WizardController::OnKioskEnableCompleted() {
691  ShowLoginScreen(LoginScreenContext());
692}
693
694void WizardController::OnWrongHWIDWarningSkipped() {
695  if (previous_screen_)
696    SetCurrentScreen(previous_screen_);
697  else
698    ShowLoginScreen(LoginScreenContext());
699}
700
701void WizardController::OnAutoEnrollmentDone() {
702  VLOG(1) << "Automagic enrollment done, resuming previous signin";
703  ResumeLoginScreen();
704}
705
706void WizardController::OnOOBECompleted() {
707  if (ShouldAutoStartEnrollment() || enrollment_recovery_) {
708    ShowEnrollmentScreen();
709  } else {
710    PerformOOBECompletedActions();
711    ShowLoginScreen(LoginScreenContext());
712  }
713}
714
715void 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
721void WizardController::OnTermsOfServiceAccepted() {
722  // If the user accepts the Terms of Service, advance to the user image screen.
723  ShowUserImageScreen();
724}
725
726void WizardController::InitiateOOBEUpdate() {
727  PerformPostEulaActions();
728  SetCurrentScreenSmooth(GetUpdateScreen(), true);
729  GetUpdateScreen()->StartNetworkCheck();
730}
731
732void 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
742void 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
761void 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
772void WizardController::SetCurrentScreen(WizardScreen* new_current) {
773  SetCurrentScreenSmooth(new_current, false);
774}
775
776void 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
793void 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
820void WizardController::SetStatusAreaVisible(bool visible) {
821  host_->SetStatusAreaVisible(visible);
822}
823
824void 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:
869void 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
941void WizardController::OnSetUserNamePassword(const std::string& username,
942                                             const std::string& password) {
943  username_ = username;
944  password_ = password;
945}
946
947void WizardController::SetUsageStatisticsReporting(bool val) {
948  usage_statistics_reporting_ = val;
949}
950
951bool WizardController::GetUsageStatisticsReporting() const {
952  return usage_statistics_reporting_;
953}
954
955chromeos::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
963void WizardController::ShowErrorScreen() {
964  VLOG(1) << "Showing error screen.";
965  SetCurrentScreen(GetErrorScreen());
966}
967
968void WizardController::HideErrorScreen(WizardScreen* parent_screen) {
969  DCHECK(parent_screen);
970  VLOG(1) << "Hiding error screen.";
971  SetCurrentScreen(parent_screen);
972}
973
974void 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
993void 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
1002void WizardController::SetZeroDelays() {
1003  kShowDelayMs = 0;
1004  zero_delay_enabled_ = true;
1005}
1006
1007// static
1008bool WizardController::IsZeroDelayEnabled() {
1009  return zero_delay_enabled_;
1010}
1011
1012// static
1013void WizardController::SkipPostLoginScreensForTesting() {
1014  skip_post_login_screens_ = true;
1015}
1016
1017// static
1018bool 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
1025bool 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
1032std::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
1040bool 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
1047std::string WizardController::GetForcedEnrollmentDomain() {
1048  policy::BrowserPolicyConnectorChromeOS* connector =
1049      g_browser_process->platform_part()->browser_policy_connector_chromeos();
1050  return connector->GetDeviceCloudPolicyManager()->GetForcedEnrollmentDomain();
1051}
1052
1053void 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
1063PrefService* WizardController::GetLocalState() {
1064  if (local_state_for_testing_)
1065    return local_state_for_testing_;
1066  return g_browser_process->local_state();
1067}
1068
1069void 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
1112TimeZoneProvider* 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
1121void 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
1148bool 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