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