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 ¶ms);
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