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