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: 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 114 ~ContentView() { 115 NotificationService::current()->Notify( 116 NotificationType::WIZARD_CONTENT_VIEW_DESTROYED, 117 NotificationService::AllSources(), 118 NotificationService::NoDetails()); 119 } 120 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 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. 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. 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. 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 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 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 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 279 void WizardController::CancelOOBEUpdate() { 280 if (update_screen_.get() && 281 update_screen_.get() == current_screen_) { 282 GetUpdateScreen()->CancelUpdate(); 283 } 284 } 285 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 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 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 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 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 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 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* 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 350 void WizardController::ShowNetworkScreen() { 351 SetStatusAreaVisible(false); 352 SetCurrentScreen(GetNetworkScreen()); 353 host_->SetOobeProgress(chromeos::BackgroundView::SELECT_NETWORK); 354 } 355 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 368 void WizardController::ShowAccountScreen() { 369 VLOG(1) << "Showing create account screen."; 370 SetStatusAreaVisible(true); 371 SetCurrentScreen(GetAccountScreen()); 372 } 373 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 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 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 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 418 void WizardController::ShowHTMLPageScreen() { 419 VLOG(1) << "Showing HTML page screen."; 420 SetStatusAreaVisible(true); 421 host_->SetOobeProgressBarVisible(false); 422 SetCurrentScreen(GetHTMLPageScreen()); 423 } 424 425 void WizardController::ShowEnterpriseEnrollmentScreen() { 426 SetStatusAreaVisible(true); 427 host_->SetOobeProgress(chromeos::BackgroundView::SIGNIN); 428 SetCurrentScreen(GetEnterpriseEnrollmentScreen()); 429 } 430 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 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: 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 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 475 void WizardController::OnAccountCreateBack() { 476 ShowLoginScreen(); 477 } 478 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 486 void WizardController::OnConnectionFailed() { 487 // TODO(dpolukhin): show error message after login screen is displayed. 488 ShowLoginScreen(); 489 } 490 491 void WizardController::OnUpdateCompleted() { 492 OnOOBECompleted(); 493 } 494 495 void WizardController::OnEulaAccepted() { 496 MarkEulaAccepted(); 497 chromeos::MetricsCrosSettingsProvider::SetMetricsStatus( 498 usage_statistics_reporting_); 499 InitiateOOBEUpdate(); 500 } 501 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 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 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 533 void WizardController::OnUserImageSkipped() { 534 OnUserImageSelected(); 535 } 536 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 546 void WizardController::OnRegistrationSkipped() { 547 // TODO(nkostylev): Track in a histogram? 548 OnRegistrationSuccess(); 549 } 550 551 void WizardController::OnEnterpriseEnrollmentDone() { 552 ShowLoginScreen(); 553 } 554 555 void WizardController::OnOOBECompleted() { 556 MarkOobeCompleted(); 557 ShowLoginScreen(); 558 } 559 560 void WizardController::InitiateOOBEUpdate() { 561 GetUpdateScreen()->StartUpdate(); 562 SetCurrentScreenSmooth(GetUpdateScreen(), true); 563 } 564 565 /////////////////////////////////////////////////////////////////////////////// 566 // WizardController, private: 567 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 591 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 601 void WizardController::SetCurrentScreen(WizardScreen* new_current) { 602 SetCurrentScreenSmooth(new_current, false); 603 } 604 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 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 666 void WizardController::SetStatusAreaVisible(bool visible) { 667 host_->SetStatusAreaVisible(visible); 668 } 669 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 704 bool WizardController::IsEulaAccepted() { 705 return g_browser_process->local_state()->GetBoolean(kEulaAccepted); 706 } 707 708 // static 709 bool WizardController::IsOobeCompleted() { 710 return g_browser_process->local_state()->GetBoolean(kOobeComplete); 711 } 712 713 // static 714 void WizardController::MarkEulaAccepted() { 715 SaveBoolPreferenceForced(kEulaAccepted, true); 716 } 717 718 // static 719 void WizardController::MarkOobeCompleted() { 720 SaveBoolPreferenceForced(kOobeComplete, true); 721 } 722 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 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 759 void WizardController::MarkDeviceRegistered() { 760 SaveIntegerPreferenceForced(kDeviceRegistered, 1); 761 BrowserThread::PostTask( 762 BrowserThread::FILE, 763 FROM_HERE, 764 NewRunnableFunction(&CreateOobeCompleteFlagFile)); 765 } 766 767 // static 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 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 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: 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 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: 857 views::View* WizardController::GetWizardView() { 858 return contents_; 859 } 860 861 chromeos::ScreenObserver* WizardController::GetObserver(WizardScreen* screen) { 862 return observer_ ? observer_ : this; 863 } 864 865 void WizardController::SetZeroDelays() { 866 kShowDelayMs = 0; 867 } 868