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