• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 <gdk/gdk.h>
8 #include <signal.h>
9 #include <sys/types.h>
10 
11 #include <string>
12 #include <vector>
13 
14 #include "base/command_line.h"
15 #include "base/file_util.h"
16 #include "base/logging.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chromeos/cros/cros_library.h"
20 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
21 #include "chrome/browser/chromeos/customization_document.h"
22 #include "chrome/browser/chromeos/language_preferences.h"
23 #include "chrome/browser/chromeos/login/account_screen.h"
24 #include "chrome/browser/chromeos/login/enterprise_enrollment_screen.h"
25 #include "chrome/browser/chromeos/login/eula_view.h"
26 #include "chrome/browser/chromeos/login/existing_user_controller.h"
27 #include "chrome/browser/chromeos/login/helper.h"
28 #include "chrome/browser/chromeos/login/html_page_screen.h"
29 #include "chrome/browser/chromeos/login/login_display_host.h"
30 #include "chrome/browser/chromeos/login/login_utils.h"
31 #include "chrome/browser/chromeos/login/network_screen.h"
32 #include "chrome/browser/chromeos/login/registration_screen.h"
33 #include "chrome/browser/chromeos/login/update_screen.h"
34 #include "chrome/browser/chromeos/login/user_image_screen.h"
35 #include "chrome/browser/chromeos/login/user_manager.h"
36 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
37 #include "chrome/browser/chromeos/metrics_cros_settings_provider.h"
38 #include "chrome/browser/prefs/pref_service.h"
39 #include "chrome/browser/profiles/profile_manager.h"
40 #include "chrome/common/pref_names.h"
41 #include "content/common/notification_service.h"
42 #include "content/common/notification_type.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "views/accelerator.h"
45 #include "views/view.h"
46 #include "views/widget/widget_gtk.h"
47 
48 namespace {
49 
50 // A boolean pref of the EULA accepted flag.
51 const char kEulaAccepted[] = "EulaAccepted";
52 
53 // A string pref with initial locale set in VPD or manifest.
54 const char kInitialLocale[] = "intl.initial_locale";
55 
56 // A boolean pref of the OOBE complete flag (first OOBE part before login).
57 const char kOobeComplete[] = "OobeComplete";
58 
59 // A boolean pref of the device registered flag (second part after first login).
60 const char kDeviceRegistered[] = "DeviceRegistered";
61 
62 // Path to flag file indicating that both parts of OOBE were completed.
63 const char kOobeCompleteFlagFilePath[] = "/home/chronos/.oobe_completed";
64 
65 // Time in seconds that we wait for the device to reboot.
66 // If reboot didn't happen, ask user to reboot device manually.
67 const int kWaitForRebootTimeSec = 3;
68 
69 // Interval in ms which is used for smooth screen showing.
70 static int kShowDelayMs = 400;
71 
72 // RootView of the Widget WizardController creates. Contains the contents of the
73 // WizardController.
74 class ContentView : public views::View {
75  public:
ContentView()76   ContentView()
77       : accel_toggle_accessibility_(
78             chromeos::WizardAccessibilityHelper::GetAccelerator()) {
79 #if defined(OFFICIAL_BUILD)
80     accel_cancel_update_ =  views::Accelerator(ui::VKEY_ESCAPE,
81                                                true, true, true);
82 #else
83     accel_cancel_update_ =  views::Accelerator(ui::VKEY_ESCAPE,
84                                                false, false, false);
85     accel_account_screen_ = views::Accelerator(ui::VKEY_A,
86                                                false, true, true);
87     accel_login_screen_ = views::Accelerator(ui::VKEY_L,
88                                              false, true, true);
89     accel_network_screen_ = views::Accelerator(ui::VKEY_N,
90                                                false, true, true);
91     accel_update_screen_ = views::Accelerator(ui::VKEY_U,
92                                               false, true, true);
93     accel_image_screen_ = views::Accelerator(ui::VKEY_I,
94                                              false, true, true);
95     accel_eula_screen_ = views::Accelerator(ui::VKEY_E,
96                                             false, true, true);
97     accel_register_screen_ = views::Accelerator(ui::VKEY_R,
98                                                 false, true, true);
99     accel_enterprise_enrollment_screen_ =
100         views::Accelerator(ui::VKEY_P, false, true, true);
101     AddAccelerator(accel_account_screen_);
102     AddAccelerator(accel_login_screen_);
103     AddAccelerator(accel_network_screen_);
104     AddAccelerator(accel_update_screen_);
105     AddAccelerator(accel_image_screen_);
106     AddAccelerator(accel_eula_screen_);
107     AddAccelerator(accel_register_screen_);
108     AddAccelerator(accel_enterprise_enrollment_screen_);
109 #endif
110     AddAccelerator(accel_toggle_accessibility_);
111     AddAccelerator(accel_cancel_update_);
112   }
113 
~ContentView()114   ~ContentView() {
115     NotificationService::current()->Notify(
116         NotificationType::WIZARD_CONTENT_VIEW_DESTROYED,
117         NotificationService::AllSources(),
118         NotificationService::NoDetails());
119   }
120 
AcceleratorPressed(const views::Accelerator & accel)121   bool AcceleratorPressed(const views::Accelerator& accel) {
122     WizardController* controller = WizardController::default_controller();
123     if (!controller)
124       return false;
125 
126     if (accel == accel_toggle_accessibility_) {
127       chromeos::WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
128     } else if (accel == accel_cancel_update_) {
129       controller->CancelOOBEUpdate();
130 #if !defined(OFFICIAL_BUILD)
131     } else if (accel == accel_account_screen_) {
132       controller->ShowAccountScreen();
133     } else if (accel == accel_login_screen_) {
134       controller->ShowLoginScreen();
135     } else if (accel == accel_network_screen_) {
136       controller->ShowNetworkScreen();
137     } else if (accel == accel_update_screen_) {
138       controller->ShowUpdateScreen();
139     } else if (accel == accel_image_screen_) {
140       controller->ShowUserImageScreen();
141     } else if (accel == accel_eula_screen_) {
142       controller->ShowEulaScreen();
143     } else if (accel == accel_register_screen_) {
144       controller->ShowRegistrationScreen();
145     } else if (accel == accel_enterprise_enrollment_screen_) {
146       controller->ShowEnterpriseEnrollmentScreen();
147 #endif
148     } else {
149       return false;
150     }
151 
152     return true;
153   }
154 
Layout()155   virtual void Layout() {
156     for (int i = 0; i < child_count(); ++i) {
157       views::View* cur = GetChildViewAt(i);
158       if (cur->IsVisible())
159         cur->SetBounds(0, 0, width(), height());
160     }
161   }
162 
163  private:
164 #if !defined(OFFICIAL_BUILD)
165   views::Accelerator accel_account_screen_;
166   views::Accelerator accel_login_screen_;
167   views::Accelerator accel_network_screen_;
168   views::Accelerator accel_update_screen_;
169   views::Accelerator accel_image_screen_;
170   views::Accelerator accel_eula_screen_;
171   views::Accelerator accel_register_screen_;
172   views::Accelerator accel_enterprise_enrollment_screen_;
173 #endif
174   views::Accelerator accel_toggle_accessibility_;
175   views::Accelerator accel_cancel_update_;
176 
177   DISALLOW_COPY_AND_ASSIGN(ContentView);
178 };
179 
180 // Saves boolean "Local State" preference and forces its persistence to disk.
SaveBoolPreferenceForced(const char * pref_name,bool value)181 void SaveBoolPreferenceForced(const char* pref_name, bool value) {
182   PrefService* prefs = g_browser_process->local_state();
183   prefs->SetBoolean(pref_name, value);
184   prefs->SavePersistentPrefs();
185 }
186 
187 // Saves integer "Local State" preference and forces its persistence to disk.
SaveIntegerPreferenceForced(const char * pref_name,int value)188 void SaveIntegerPreferenceForced(const char* pref_name, int value) {
189   PrefService* prefs = g_browser_process->local_state();
190   prefs->SetInteger(pref_name, value);
191   prefs->SavePersistentPrefs();
192 }
193 
194 // Saves string "Local State" preference and forces its persistence to disk.
SaveStringPreferenceForced(const char * pref_name,const std::string & value)195 void SaveStringPreferenceForced(const char* pref_name,
196                                 const std::string& value) {
197   PrefService* prefs = g_browser_process->local_state();
198   prefs->SetString(pref_name, value);
199   prefs->SavePersistentPrefs();
200 }
201 
202 }  // namespace
203 
204 const char WizardController::kNetworkScreenName[] = "network";
205 const char WizardController::kLoginScreenName[] = "login";
206 const char WizardController::kAccountScreenName[] = "account";
207 const char WizardController::kUpdateScreenName[] = "update";
208 const char WizardController::kUserImageScreenName[] = "image";
209 const char WizardController::kEulaScreenName[] = "eula";
210 const char WizardController::kRegistrationScreenName[] = "register";
211 const char WizardController::kHTMLPageScreenName[] = "html";
212 const char WizardController::kEnterpriseEnrollmentScreenName[] = "enroll";
213 
214 // Passing this parameter as a "first screen" initiates full OOBE flow.
215 const char WizardController::kOutOfBoxScreenName[] = "oobe";
216 
217 // Special test value that commands not to create any window yet.
218 const char WizardController::kTestNoScreenName[] = "test:nowindow";
219 
220 // Initialize default controller.
221 // static
222 WizardController* WizardController::default_controller_ = NULL;
223 
224 ///////////////////////////////////////////////////////////////////////////////
225 // WizardController, public:
226 
WizardController(chromeos::LoginDisplayHost * host,const gfx::Rect & screen_bounds)227 WizardController::WizardController(chromeos::LoginDisplayHost* host,
228                                    const gfx::Rect& screen_bounds)
229     : widget_(NULL),
230       contents_(NULL),
231       screen_bounds_(screen_bounds),
232       current_screen_(NULL),
233       initial_show_(true),
234       is_active_(true),
235 #if defined(OFFICIAL_BUILD)
236       is_official_build_(true),
237 #else
238       is_official_build_(false),
239 #endif
240       is_out_of_box_(false),
241       host_(host),
242       observer_(NULL),
243       usage_statistics_reporting_(true) {
244   DCHECK(default_controller_ == NULL);
245   default_controller_ = this;
246 }
247 
~WizardController()248 WizardController::~WizardController() {
249   if (widget_) {
250     widget_->Close();
251     widget_ = NULL;
252   }
253 
254   if (default_controller_ == this) {
255     default_controller_ = NULL;
256   } else {
257     NOTREACHED() << "More than one controller are alive.";
258   }
259 
260   chromeos::WizardAccessibilityHelper::GetInstance()->
261       UnregisterNotifications();
262 }
263 
Init(const std::string & first_screen_name)264 void WizardController::Init(const std::string& first_screen_name) {
265   VLOG(1) << "Starting OOBE wizard with screen: " << first_screen_name;
266   DCHECK(!contents_);
267   first_screen_name_ = first_screen_name;
268 
269   contents_ = new ContentView();
270 
271   bool oobe_complete = IsOobeCompleted();
272   if (!oobe_complete || first_screen_name == kOutOfBoxScreenName) {
273     is_out_of_box_ = true;
274   }
275 
276   ShowFirstScreen(first_screen_name);
277 }
278 
CancelOOBEUpdate()279 void WizardController::CancelOOBEUpdate() {
280   if (update_screen_.get() &&
281       update_screen_.get() == current_screen_) {
282     GetUpdateScreen()->CancelUpdate();
283   }
284 }
285 
GetNetworkScreen()286 chromeos::NetworkScreen* WizardController::GetNetworkScreen() {
287   if (!network_screen_.get())
288     network_screen_.reset(new chromeos::NetworkScreen(this));
289   return network_screen_.get();
290 }
291 
GetAccountScreen()292 chromeos::AccountScreen* WizardController::GetAccountScreen() {
293   if (!account_screen_.get())
294     account_screen_.reset(new chromeos::AccountScreen(this));
295   return account_screen_.get();
296 }
297 
GetUpdateScreen()298 chromeos::UpdateScreen* WizardController::GetUpdateScreen() {
299   if (!update_screen_.get()) {
300     update_screen_.reset(new chromeos::UpdateScreen(this));
301     update_screen_->SetRebootCheckDelay(kWaitForRebootTimeSec);
302   }
303   return update_screen_.get();
304 }
305 
GetUserImageScreen()306 chromeos::UserImageScreen* WizardController::GetUserImageScreen() {
307   if (!user_image_screen_.get())
308     user_image_screen_.reset(new chromeos::UserImageScreen(this));
309   return user_image_screen_.get();
310 }
311 
GetEulaScreen()312 chromeos::EulaScreen* WizardController::GetEulaScreen() {
313   if (!eula_screen_.get())
314     eula_screen_.reset(new chromeos::EulaScreen(this));
315   return eula_screen_.get();
316 }
317 
GetRegistrationScreen()318 chromeos::RegistrationScreen* WizardController::GetRegistrationScreen() {
319   if (!registration_screen_.get())
320     registration_screen_.reset(new chromeos::RegistrationScreen(this));
321   return registration_screen_.get();
322 }
323 
GetHTMLPageScreen()324 chromeos::HTMLPageScreen* WizardController::GetHTMLPageScreen() {
325   if (!html_page_screen_.get()) {
326     CommandLine* command_line = CommandLine::ForCurrentProcess();
327     std::string url;
328     // It's strange but args may contains empty strings.
329     for (size_t i = 0; i < command_line->args().size(); i++) {
330       if (!command_line->args()[i].empty()) {
331         DCHECK(url.empty()) << "More than one URL in command line";
332         url = command_line->args()[i];
333       }
334     }
335     DCHECK(!url.empty()) << "No URL in commane line";
336     html_page_screen_.reset(new chromeos::HTMLPageScreen(this, url));
337   }
338   return html_page_screen_.get();
339 }
340 
341 chromeos::EnterpriseEnrollmentScreen*
GetEnterpriseEnrollmentScreen()342     WizardController::GetEnterpriseEnrollmentScreen() {
343   if (!enterprise_enrollment_screen_.get()) {
344     enterprise_enrollment_screen_.reset(
345         new chromeos::EnterpriseEnrollmentScreen(this));
346   }
347   return enterprise_enrollment_screen_.get();
348 }
349 
ShowNetworkScreen()350 void WizardController::ShowNetworkScreen() {
351   SetStatusAreaVisible(false);
352   SetCurrentScreen(GetNetworkScreen());
353   host_->SetOobeProgress(chromeos::BackgroundView::SELECT_NETWORK);
354 }
355 
ShowLoginScreen()356 void WizardController::ShowLoginScreen() {
357   SetStatusAreaVisible(true);
358   host_->SetOobeProgress(chromeos::BackgroundView::SIGNIN);
359   host_->StartSignInScreen();
360   smooth_show_timer_.Stop();
361   if (widget_) {
362     widget_->Close();
363     widget_ = NULL;
364   }
365   is_active_ = false;
366 }
367 
ShowAccountScreen()368 void WizardController::ShowAccountScreen() {
369   VLOG(1) << "Showing create account screen.";
370   SetStatusAreaVisible(true);
371   SetCurrentScreen(GetAccountScreen());
372 }
373 
ShowUpdateScreen()374 void WizardController::ShowUpdateScreen() {
375   VLOG(1) << "Showing update screen.";
376   SetStatusAreaVisible(true);
377   SetCurrentScreen(GetUpdateScreen());
378   // There is no special step for update.
379 #if defined(OFFICIAL_BUILD)
380   host_->SetOobeProgress(chromeos::BackgroundView::EULA);
381 #else
382   host_->SetOobeProgress(chromeos::BackgroundView::SELECT_NETWORK);
383 #endif
384 }
385 
ShowUserImageScreen()386 void WizardController::ShowUserImageScreen() {
387   VLOG(1) << "Showing user image screen.";
388   SetStatusAreaVisible(false);
389   SetCurrentScreen(GetUserImageScreen());
390   host_->SetOobeProgress(chromeos::BackgroundView::PICTURE);
391   host_->SetShutdownButtonEnabled(false);
392 }
393 
ShowEulaScreen()394 void WizardController::ShowEulaScreen() {
395   VLOG(1) << "Showing EULA screen.";
396   SetStatusAreaVisible(false);
397   SetCurrentScreen(GetEulaScreen());
398 #if defined(OFFICIAL_BUILD)
399   host_->SetOobeProgress(chromeos::BackgroundView::EULA);
400 #endif
401 }
402 
ShowRegistrationScreen()403 void WizardController::ShowRegistrationScreen() {
404   if (!IsRegisterScreenDefined()) {
405     VLOG(1) << "Skipping registration screen: manifest not defined or invalid "
406                "URL.";
407     OnRegistrationSkipped();
408     return;
409   }
410   VLOG(1) << "Showing registration screen.";
411   SetStatusAreaVisible(true);
412   SetCurrentScreen(GetRegistrationScreen());
413 #if defined(OFFICIAL_BUILD)
414   host_->SetOobeProgress(chromeos::BackgroundView::REGISTRATION);
415 #endif
416 }
417 
ShowHTMLPageScreen()418 void WizardController::ShowHTMLPageScreen() {
419   VLOG(1) << "Showing HTML page screen.";
420   SetStatusAreaVisible(true);
421   host_->SetOobeProgressBarVisible(false);
422   SetCurrentScreen(GetHTMLPageScreen());
423 }
424 
ShowEnterpriseEnrollmentScreen()425 void WizardController::ShowEnterpriseEnrollmentScreen() {
426   SetStatusAreaVisible(true);
427   host_->SetOobeProgress(chromeos::BackgroundView::SIGNIN);
428   SetCurrentScreen(GetEnterpriseEnrollmentScreen());
429 }
430 
SkipRegistration()431 void WizardController::SkipRegistration() {
432   if (current_screen_ == GetRegistrationScreen())
433     OnRegistrationSkipped();
434   else
435     LOG(ERROR) << "Registration screen is not active.";
436 }
437 
438 // static
RegisterPrefs(PrefService * local_state)439 void WizardController::RegisterPrefs(PrefService* local_state) {
440   local_state->RegisterBooleanPref(kOobeComplete, false);
441   local_state->RegisterIntegerPref(kDeviceRegistered, -1);
442   local_state->RegisterBooleanPref(kEulaAccepted, false);
443   local_state->RegisterStringPref(kInitialLocale, "en-US");
444   // Check if the pref is already registered in case
445   // Preferences::RegisterUserPrefs runs before this code in the future.
446   if (local_state->FindPreference(prefs::kAccessibilityEnabled) == NULL) {
447     local_state->RegisterBooleanPref(prefs::kAccessibilityEnabled, false);
448   }
449 }
450 
451 ///////////////////////////////////////////////////////////////////////////////
452 // WizardController, ExitHandlers:
OnNetworkConnected()453 void WizardController::OnNetworkConnected() {
454   if (is_official_build_) {
455     if (!IsEulaAccepted()) {
456       ShowEulaScreen();
457     } else {
458       // Possible cases:
459       // 1. EULA was accepted, forced shutdown/reboot during update.
460       // 2. EULA was accepted, planned reboot after update.
461       // Make sure that device is up-to-date.
462       InitiateOOBEUpdate();
463     }
464   } else {
465     InitiateOOBEUpdate();
466   }
467 }
468 
OnNetworkOffline()469 void WizardController::OnNetworkOffline() {
470   // TODO(dpolukhin): if(is_out_of_box_) we cannot work offline and
471   // should report some error message here and stay on the same screen.
472   ShowLoginScreen();
473 }
474 
OnAccountCreateBack()475 void WizardController::OnAccountCreateBack() {
476   ShowLoginScreen();
477 }
478 
OnAccountCreated()479 void WizardController::OnAccountCreated() {
480   ShowLoginScreen();
481   // TODO(dpolukhin): clear password memory for real. Now it is not
482   // a problem because we can't extract password from the form.
483   password_.clear();
484 }
485 
OnConnectionFailed()486 void WizardController::OnConnectionFailed() {
487   // TODO(dpolukhin): show error message after login screen is displayed.
488   ShowLoginScreen();
489 }
490 
OnUpdateCompleted()491 void WizardController::OnUpdateCompleted() {
492   OnOOBECompleted();
493 }
494 
OnEulaAccepted()495 void WizardController::OnEulaAccepted() {
496   MarkEulaAccepted();
497   chromeos::MetricsCrosSettingsProvider::SetMetricsStatus(
498       usage_statistics_reporting_);
499   InitiateOOBEUpdate();
500 }
501 
OnUpdateErrorCheckingForUpdate()502 void WizardController::OnUpdateErrorCheckingForUpdate() {
503   // TODO(nkostylev): Update should be required during OOBE.
504   // We do not want to block users from being able to proceed to the login
505   // screen if there is any error checking for an update.
506   // They could use "browse without sign-in" feature to set up the network to be
507   // able to perform the update later.
508   OnOOBECompleted();
509 }
510 
OnUpdateErrorUpdating()511 void WizardController::OnUpdateErrorUpdating() {
512   // If there was an error while getting or applying the update,
513   // return to network selection screen.
514   // TODO(nkostylev): Show message to the user explaining update error.
515   // TODO(nkostylev): Update should be required during OOBE.
516   // Temporary fix, need to migrate to new API. http://crosbug.com/4321
517   OnOOBECompleted();
518 }
519 
OnUserImageSelected()520 void WizardController::OnUserImageSelected() {
521   // Notify host that we're about to launch browser session.
522   // Host will mark itself (and all controllers/windows) for deletion.
523   host_->OnSessionStart();
524   // Launch browser after controller is deleted and its windows are closed.
525   BrowserThread::PostTask(
526       BrowserThread::UI,
527       FROM_HERE,
528       NewRunnableFunction(&chromeos::LoginUtils::DoBrowserLaunch,
529                           ProfileManager::GetDefaultProfile()));
530   // TODO(avayvod): Sync image with Google Sync.
531 }
532 
OnUserImageSkipped()533 void WizardController::OnUserImageSkipped() {
534   OnUserImageSelected();
535 }
536 
OnRegistrationSuccess()537 void WizardController::OnRegistrationSuccess() {
538   MarkDeviceRegistered();
539   if (chromeos::UserManager::Get()->IsLoggedInAsGuest()) {
540     chromeos::LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
541   } else {
542     ShowUserImageScreen();
543   }
544 }
545 
OnRegistrationSkipped()546 void WizardController::OnRegistrationSkipped() {
547   // TODO(nkostylev): Track in a histogram?
548   OnRegistrationSuccess();
549 }
550 
OnEnterpriseEnrollmentDone()551 void WizardController::OnEnterpriseEnrollmentDone() {
552   ShowLoginScreen();
553 }
554 
OnOOBECompleted()555 void WizardController::OnOOBECompleted() {
556   MarkOobeCompleted();
557   ShowLoginScreen();
558 }
559 
InitiateOOBEUpdate()560 void WizardController::InitiateOOBEUpdate() {
561   GetUpdateScreen()->StartUpdate();
562   SetCurrentScreenSmooth(GetUpdateScreen(), true);
563 }
564 
565 ///////////////////////////////////////////////////////////////////////////////
566 // WizardController, private:
567 
CreateScreenWindow(const gfx::Rect & bounds,bool initial_show)568 views::Widget* WizardController::CreateScreenWindow(
569     const gfx::Rect& bounds, bool initial_show) {
570   views::Widget::CreateParams widget_params(
571       views::Widget::CreateParams::TYPE_WINDOW);
572   widget_params.transparent = true;
573   widget_ = views::Widget::CreateWidget(widget_params);
574   // Window transparency makes background flicker through controls that
575   // are constantly updating its contents (like image view with video
576   // stream). Hence enabling double buffer.
577   static_cast<views::WidgetGtk*>(widget_)->EnableDoubleBuffer(true);
578   widget_->Init(NULL, bounds);
579   std::vector<int> params;
580   // For initial show WM would animate background window.
581   // Otherwise it stays unchaged.
582   params.push_back(initial_show);
583   chromeos::WmIpc::instance()->SetWindowType(
584       widget_->GetNativeView(),
585       chromeos::WM_IPC_WINDOW_LOGIN_GUEST,
586       &params);
587   widget_->SetContentsView(contents_);
588   return widget_;
589 }
590 
GetWizardScreenBounds(int screen_width,int screen_height) const591 gfx::Rect WizardController::GetWizardScreenBounds(int screen_width,
592                                                   int screen_height) const {
593   int offset_x = (screen_bounds_.width() - screen_width) / 2;
594   int offset_y = (screen_bounds_.height() - screen_height) / 2;
595   int window_x = screen_bounds_.x() + offset_x;
596   int window_y = screen_bounds_.y() + offset_y;
597   return gfx::Rect(window_x, window_y, screen_width, screen_height);
598 }
599 
600 
SetCurrentScreen(WizardScreen * new_current)601 void WizardController::SetCurrentScreen(WizardScreen* new_current) {
602   SetCurrentScreenSmooth(new_current, false);
603 }
604 
ShowCurrentScreen()605 void WizardController::ShowCurrentScreen() {
606   // ShowCurrentScreen may get called by smooth_show_timer_ even after
607   // flow has been switched to sign in screen (ExistingUserController).
608   if (!is_active_)
609     return;
610 
611   smooth_show_timer_.Stop();
612 
613   bool force_widget_show = false;
614   views::Widget* window = NULL;
615 
616   gfx::Rect current_bounds;
617   if (widget_)
618     current_bounds = widget_->GetClientAreaScreenBounds();
619   gfx::Size new_screen_size = current_screen_->GetScreenSize();
620   gfx::Rect new_bounds = GetWizardScreenBounds(new_screen_size.width(),
621                                                new_screen_size.height());
622   if (new_bounds != current_bounds) {
623     if (widget_)
624       widget_->Close();
625     force_widget_show = true;
626     window = CreateScreenWindow(new_bounds, initial_show_);
627   }
628   current_screen_->Show();
629   contents_->Layout();
630   contents_->SchedulePaint();
631   if (force_widget_show) {
632     // This keeps the window from flashing at startup.
633     GdkWindow* gdk_window = window->GetNativeView()->window;
634     gdk_window_set_back_pixmap(gdk_window, NULL, false);
635     if (widget_)
636       widget_->Show();
637   }
638 }
639 
SetCurrentScreenSmooth(WizardScreen * new_current,bool use_smoothing)640 void WizardController::SetCurrentScreenSmooth(WizardScreen* new_current,
641                                               bool use_smoothing) {
642   if (current_screen_ == new_current || new_current == NULL)
643     return;
644 
645   smooth_show_timer_.Stop();
646 
647   if (current_screen_) {
648     initial_show_ = false;
649     current_screen_->Hide();
650   }
651 
652   current_screen_ = new_current;
653 
654   if (use_smoothing) {
655     smooth_show_timer_.Start(
656         base::TimeDelta::FromMilliseconds(kShowDelayMs),
657         this,
658         &WizardController::ShowCurrentScreen);
659     contents_->Layout();
660     contents_->SchedulePaint();
661   } else {
662     ShowCurrentScreen();
663   }
664 }
665 
SetStatusAreaVisible(bool visible)666 void WizardController::SetStatusAreaVisible(bool visible) {
667   host_->SetStatusAreaVisible(visible);
668 }
669 
ShowFirstScreen(const std::string & first_screen_name)670 void WizardController::ShowFirstScreen(const std::string& first_screen_name) {
671   if (first_screen_name == kNetworkScreenName) {
672     ShowNetworkScreen();
673   } else if (first_screen_name == kLoginScreenName) {
674     ShowLoginScreen();
675   } else if (first_screen_name == kAccountScreenName) {
676     ShowAccountScreen();
677   } else if (first_screen_name == kUpdateScreenName) {
678     InitiateOOBEUpdate();
679   } else if (first_screen_name == kUserImageScreenName) {
680     ShowUserImageScreen();
681   } else if (first_screen_name == kEulaScreenName) {
682     ShowEulaScreen();
683   } else if (first_screen_name == kRegistrationScreenName) {
684     if (is_official_build_) {
685       ShowRegistrationScreen();
686     } else {
687       // Just proceed to image screen.
688       OnRegistrationSuccess();
689     }
690   } else if (first_screen_name == kHTMLPageScreenName) {
691     ShowHTMLPageScreen();
692   } else if (first_screen_name == kEnterpriseEnrollmentScreenName) {
693     ShowEnterpriseEnrollmentScreen();
694   } else if (first_screen_name != kTestNoScreenName) {
695     if (is_out_of_box_) {
696       ShowNetworkScreen();
697     } else {
698       ShowLoginScreen();
699     }
700   }
701 }
702 
703 // static
IsEulaAccepted()704 bool WizardController::IsEulaAccepted() {
705   return g_browser_process->local_state()->GetBoolean(kEulaAccepted);
706 }
707 
708 // static
IsOobeCompleted()709 bool WizardController::IsOobeCompleted() {
710   return g_browser_process->local_state()->GetBoolean(kOobeComplete);
711 }
712 
713 // static
MarkEulaAccepted()714 void WizardController::MarkEulaAccepted() {
715   SaveBoolPreferenceForced(kEulaAccepted, true);
716 }
717 
718 // static
MarkOobeCompleted()719 void WizardController::MarkOobeCompleted() {
720   SaveBoolPreferenceForced(kOobeComplete, true);
721 }
722 
CreateOobeCompleteFlagFile()723 static void CreateOobeCompleteFlagFile() {
724   // Create flag file for boot-time init scripts.
725   FilePath oobe_complete_path(kOobeCompleteFlagFilePath);
726   if (!file_util::PathExists(oobe_complete_path)) {
727     FILE* oobe_flag_file = file_util::OpenFile(oobe_complete_path, "w+b");
728     if (oobe_flag_file == NULL)
729       DLOG(WARNING) << kOobeCompleteFlagFilePath << " doesn't exist.";
730     else
731       file_util::CloseFile(oobe_flag_file);
732   }
733 }
734 
735 // static
IsDeviceRegistered()736 bool WizardController::IsDeviceRegistered() {
737   int value = g_browser_process->local_state()->GetInteger(kDeviceRegistered);
738   if (value > 0) {
739     // Recreate flag file in case it was lost.
740     BrowserThread::PostTask(
741         BrowserThread::FILE,
742         FROM_HERE,
743         NewRunnableFunction(&CreateOobeCompleteFlagFile));
744     return true;
745   } else if (value == 0) {
746     return false;
747   } else {
748     // Pref is not set. For compatibility check flag file. It causes blocking
749     // IO on UI thread. But it's required for update from old versions.
750     base::ThreadRestrictions::ScopedAllowIO allow_io;
751     FilePath oobe_complete_flag_file_path(kOobeCompleteFlagFilePath);
752     bool file_exists = file_util::PathExists(oobe_complete_flag_file_path);
753     SaveIntegerPreferenceForced(kDeviceRegistered, file_exists ? 1 : 0);
754     return file_exists;
755   }
756 }
757 
758 // static
MarkDeviceRegistered()759 void WizardController::MarkDeviceRegistered() {
760   SaveIntegerPreferenceForced(kDeviceRegistered, 1);
761   BrowserThread::PostTask(
762       BrowserThread::FILE,
763       FROM_HERE,
764       NewRunnableFunction(&CreateOobeCompleteFlagFile));
765 }
766 
767 // static
GetInitialLocale()768 std::string WizardController::GetInitialLocale() {
769   std::string locale =
770       g_browser_process->local_state()->GetString(kInitialLocale);
771   if (!l10n_util::IsValidLocaleSyntax(locale))
772     locale = "en-US";
773   return locale;
774 }
775 
776 // static
SetInitialLocale(const std::string & locale)777 void WizardController::SetInitialLocale(const std::string& locale) {
778   if (l10n_util::IsValidLocaleSyntax(locale))
779     SaveStringPreferenceForced(kInitialLocale, locale);
780   else
781     NOTREACHED();
782 }
783 
784 // static
IsRegisterScreenDefined()785 bool WizardController::IsRegisterScreenDefined() {
786   const chromeos::StartupCustomizationDocument* manifest =
787       chromeos::StartupCustomizationDocument::GetInstance();
788   return manifest->IsReady() &&
789          GURL(manifest->registration_url()).is_valid();
790 }
791 
792 ///////////////////////////////////////////////////////////////////////////////
793 // WizardController, chromeos::ScreenObserver overrides:
OnExit(ExitCodes exit_code)794 void WizardController::OnExit(ExitCodes exit_code) {
795   LOG(INFO) << "Wizard screen exit code: " << exit_code;
796   switch (exit_code) {
797     case NETWORK_CONNECTED:
798       OnNetworkConnected();
799       break;
800     case NETWORK_OFFLINE:
801       OnNetworkOffline();
802       break;
803     case ACCOUNT_CREATE_BACK:
804       OnAccountCreateBack();
805       break;
806     case ACCOUNT_CREATED:
807       OnAccountCreated();
808       break;
809     case CONNECTION_FAILED:
810       OnConnectionFailed();
811       break;
812     case UPDATE_INSTALLED:
813     case UPDATE_NOUPDATE:
814       OnUpdateCompleted();
815       break;
816     case UPDATE_ERROR_CHECKING_FOR_UPDATE:
817       OnUpdateErrorCheckingForUpdate();
818       break;
819     case UPDATE_ERROR_UPDATING:
820       OnUpdateErrorUpdating();
821       break;
822     case USER_IMAGE_SELECTED:
823       OnUserImageSelected();
824       break;
825     case USER_IMAGE_SKIPPED:
826       OnUserImageSkipped();
827       break;
828     case EULA_ACCEPTED:
829       OnEulaAccepted();
830       break;
831     case EULA_BACK:
832       ShowNetworkScreen();
833       break;
834     case REGISTRATION_SUCCESS:
835       OnRegistrationSuccess();
836       break;
837     case REGISTRATION_SKIPPED:
838       OnRegistrationSkipped();
839       break;
840     case ENTERPRISE_ENROLLMENT_CANCELLED:
841     case ENTERPRISE_ENROLLMENT_COMPLETED:
842       OnEnterpriseEnrollmentDone();
843       break;
844     default:
845       NOTREACHED();
846   }
847 }
848 
OnSetUserNamePassword(const std::string & username,const std::string & password)849 void WizardController::OnSetUserNamePassword(const std::string& username,
850                                              const std::string& password) {
851   username_ = username;
852   password_ = password;
853 }
854 
855 ///////////////////////////////////////////////////////////////////////////////
856 // WizardController, WizardScreen overrides:
GetWizardView()857 views::View* WizardController::GetWizardView() {
858   return contents_;
859 }
860 
GetObserver(WizardScreen * screen)861 chromeos::ScreenObserver* WizardController::GetObserver(WizardScreen* screen) {
862   return observer_ ? observer_ : this;
863 }
864 
SetZeroDelays()865 void WizardController::SetZeroDelays() {
866   kShowDelayMs = 0;
867 }
868