wizard_controller.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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 "app/l10n_util.h" 15#include "base/command_line.h" 16#include "base/logging.h" 17#include "chrome/browser/browser_process.h" 18#include "chrome/browser/chromeos/cros/cros_library.h" 19#include "chrome/browser/chromeos/cros/login_library.h" 20#include "chrome/browser/chromeos/cros/system_library.h" 21#include "chrome/browser/chromeos/customization_document.h" 22#include "chrome/browser/chromeos/input_method/input_method_util.h" 23#include "chrome/browser/chromeos/login/account_screen.h" 24#include "chrome/browser/chromeos/login/background_view.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/language_switch_menu.h" 29#include "chrome/browser/chromeos/login/login_screen.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/rounded_rect_painter.h" 34#include "chrome/browser/chromeos/login/update_screen.h" 35#include "chrome/browser/chromeos/login/user_image_screen.h" 36#include "chrome/browser/chromeos/login/user_manager.h" 37#include "chrome/browser/chromeos/wm_ipc.h" 38#include "chrome/browser/pref_service.h" 39#include "chrome/browser/profile_manager.h" 40#include "chrome/common/chrome_switches.h" 41#include "chrome/common/notification_service.h" 42#include "cros/chromeos_wm_ipc_enums.h" 43#include "unicode/timezone.h" 44#include "views/accelerator.h" 45#include "views/painter.h" 46#include "views/view.h" 47#include "views/widget/widget_gtk.h" 48 49namespace { 50 51// A boolean pref of the OOBE complete flag. 52const wchar_t kOobeComplete[] = L"OobeComplete"; 53 54// Default size of the OOBE screen. 55const int kWizardScreenWidth = 700; 56const int kWizardScreenHeight = 416; 57 58// RootView of the Widget WizardController creates. Contains the contents of the 59// WizardController. 60class ContentView : public views::View { 61 public: 62 ContentView(int window_x, int window_y, int screen_w, int screen_h) 63 : window_x_(window_x), 64 window_y_(window_y), 65 screen_w_(screen_w), 66 screen_h_(screen_h), 67 accel_account_screen_(views::Accelerator(base::VKEY_A, 68 false, true, true)), 69 accel_login_screen_(views::Accelerator(base::VKEY_L, 70 false, true, true)), 71 accel_network_screen_(views::Accelerator(base::VKEY_N, 72 false, true, true)), 73 accel_update_screen_(views::Accelerator(base::VKEY_U, 74 false, true, true)), 75 accel_image_screen_(views::Accelerator(base::VKEY_I, 76 false, true, true)), 77 accel_eula_screen_(views::Accelerator(base::VKEY_E, 78 false, true, true)) { 79 AddAccelerator(accel_account_screen_); 80 AddAccelerator(accel_login_screen_); 81 AddAccelerator(accel_network_screen_); 82 AddAccelerator(accel_update_screen_); 83 AddAccelerator(accel_image_screen_); 84 AddAccelerator(accel_eula_screen_); 85 } 86 87 ~ContentView() { 88 NotificationService::current()->Notify( 89 NotificationType::WIZARD_CONTENT_VIEW_DESTROYED, 90 NotificationService::AllSources(), 91 NotificationService::NoDetails()); 92 } 93 94 bool AcceleratorPressed(const views::Accelerator& accel) { 95 WizardController* controller = WizardController::default_controller(); 96 if (!controller) 97 return false; 98 99 if (accel == accel_account_screen_) { 100 controller->ShowAccountScreen(); 101 } else if (accel == accel_login_screen_) { 102 controller->ShowLoginScreen(); 103 } else if (accel == accel_network_screen_) { 104 controller->ShowNetworkScreen(); 105 } else if (accel == accel_update_screen_) { 106 controller->ShowUpdateScreen(); 107 } else if (accel == accel_image_screen_) { 108 controller->ShowUserImageScreen(); 109 } else if (accel == accel_eula_screen_) { 110 controller->ShowEulaScreen(); 111 } else { 112 return false; 113 } 114 115 return true; 116 } 117 118 void PaintBackground(gfx::Canvas* canvas) { 119 if (painter_.get()) { 120 // TODO(sky): nuke this once new login manager is in place. This needs to 121 // exist because with no window manager transparency isn't really 122 // supported. 123 canvas->TranslateInt(-window_x_, -window_y_); 124 painter_->Paint(screen_w_, screen_h_, canvas); 125 } 126 } 127 128 virtual void Layout() { 129 for (int i = 0; i < GetChildViewCount(); ++i) { 130 views::View* cur = GetChildViewAt(i); 131 if (cur->IsVisible()) 132 cur->SetBounds(0, 0, width(), height()); 133 } 134 } 135 136 private: 137 scoped_ptr<views::Painter> painter_; 138 139 const int window_x_; 140 const int window_y_; 141 const int screen_w_; 142 const int screen_h_; 143 144 views::Accelerator accel_account_screen_; 145 views::Accelerator accel_login_screen_; 146 views::Accelerator accel_network_screen_; 147 views::Accelerator accel_update_screen_; 148 views::Accelerator accel_image_screen_; 149 views::Accelerator accel_eula_screen_; 150 151 DISALLOW_COPY_AND_ASSIGN(ContentView); 152}; 153 154void DeleteWizardControllerAndLaunchBrowser(WizardController* controller) { 155 delete controller; 156 // Launch browser after controller is deleted and its windows are closed. 157 chromeos::LoginUtils::Get()->EnableBrowserLaunch(true); 158 ChromeThread::PostTask( 159 ChromeThread::UI, 160 FROM_HERE, 161 NewRunnableFunction(&chromeos::LoginUtils::DoBrowserLaunch, 162 ProfileManager::GetDefaultProfile())); 163} 164 165} // namespace 166 167const char WizardController::kNetworkScreenName[] = "network"; 168const char WizardController::kLoginScreenName[] = "login"; 169const char WizardController::kAccountScreenName[] = "account"; 170const char WizardController::kUpdateScreenName[] = "update"; 171const char WizardController::kUserImageScreenName[] = "image"; 172const char WizardController::kEulaScreenName[] = "eula"; 173const char WizardController::kRegistrationScreenName[] = "register"; 174 175// Passing this parameter as a "first screen" initiates full OOBE flow. 176const char WizardController::kOutOfBoxScreenName[] = "oobe"; 177 178// Special test value that commands not to create any window yet. 179const char WizardController::kTestNoScreenName[] = "test:nowindow"; 180 181// Initialize default controller. 182// static 183WizardController* WizardController::default_controller_ = NULL; 184 185/////////////////////////////////////////////////////////////////////////////// 186// WizardController, public: 187 188WizardController::WizardController() 189 : widget_(NULL), 190 background_widget_(NULL), 191 background_view_(NULL), 192 contents_(NULL), 193 current_screen_(NULL), 194 is_out_of_box_(false), 195 is_test_mode_(false), 196 observer_(NULL) { 197 DCHECK(default_controller_ == NULL); 198 default_controller_ = this; 199} 200 201WizardController::~WizardController() { 202 // Close ends up deleting the widget. 203 if (background_widget_) 204 background_widget_->Close(); 205 206 if (widget_) 207 widget_->Close(); 208 209 default_controller_ = NULL; 210} 211 212void WizardController::Init(const std::string& first_screen_name, 213 const gfx::Rect& screen_bounds) { 214 DCHECK(!contents_); 215 216 int offset_x = (screen_bounds.width() - kWizardScreenWidth) / 2; 217 int offset_y = (screen_bounds.height() - kWizardScreenHeight) / 2; 218 int window_x = screen_bounds.x() + offset_x; 219 int window_y = screen_bounds.y() + offset_y; 220 221 contents_ = new ContentView(offset_x, offset_y, 222 screen_bounds.width(), screen_bounds.height()); 223 224 views::WidgetGtk* window = 225 new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); 226 widget_ = window; 227 window->MakeTransparent(); 228 // Window transparency makes background flicker through controls that 229 // are constantly updating its contents (like image view with video 230 // stream). Hence enabling double buffer. 231 window->EnableDoubleBuffer(true); 232 window->Init(NULL, gfx::Rect(window_x, window_y, kWizardScreenWidth, 233 kWizardScreenHeight)); 234 chromeos::WmIpc::instance()->SetWindowType( 235 window->GetNativeView(), 236 chromeos::WM_IPC_WINDOW_LOGIN_GUEST, 237 NULL); 238 window->SetContentsView(contents_); 239 240 PrefService* prefs = g_browser_process->local_state(); 241 bool oobe_complete = prefs->GetBoolean(kOobeComplete); 242 243 if (!oobe_complete || first_screen_name == kOutOfBoxScreenName) { 244 is_out_of_box_ = true; 245 } 246 247 ShowFirstScreen(first_screen_name); 248 249 // This keeps the window from flashing at startup. 250 GdkWindow* gdk_window = window->GetNativeView()->window; 251 gdk_window_set_back_pixmap(gdk_window, NULL, false); 252} 253 254void WizardController::Show() { 255 DCHECK(widget_); 256 widget_->Show(); 257} 258 259void WizardController::ShowBackground(const gfx::Rect& bounds) { 260 DCHECK(!background_widget_); 261 background_widget_ = 262 chromeos::BackgroundView::CreateWindowContainingView(bounds, 263 &background_view_); 264 background_widget_->Show(); 265} 266 267void WizardController::OwnBackground( 268 views::Widget* background_widget, 269 chromeos::BackgroundView* background_view) { 270 DCHECK(!background_widget_); 271 background_widget_ = background_widget; 272 background_view_ = background_view; 273} 274 275chromeos::NetworkScreen* WizardController::GetNetworkScreen() { 276 if (!network_screen_.get()) 277 network_screen_.reset(new chromeos::NetworkScreen(this, is_out_of_box_)); 278 return network_screen_.get(); 279} 280 281chromeos::LoginScreen* WizardController::GetLoginScreen() { 282 if (!login_screen_.get()) 283 login_screen_.reset(new chromeos::LoginScreen(this)); 284 return login_screen_.get(); 285} 286 287chromeos::AccountScreen* WizardController::GetAccountScreen() { 288 if (!account_screen_.get()) 289 account_screen_.reset(new chromeos::AccountScreen(this)); 290 return account_screen_.get(); 291} 292 293chromeos::UpdateScreen* WizardController::GetUpdateScreen() { 294 if (!update_screen_.get()) 295 update_screen_.reset(new chromeos::UpdateScreen(this)); 296 return update_screen_.get(); 297} 298 299chromeos::UserImageScreen* WizardController::GetUserImageScreen() { 300 if (!user_image_screen_.get()) 301 user_image_screen_.reset(new chromeos::UserImageScreen(this)); 302 return user_image_screen_.get(); 303} 304 305chromeos::EulaScreen* WizardController::GetEulaScreen() { 306 if (!eula_screen_.get()) 307 eula_screen_.reset(new chromeos::EulaScreen(this)); 308 return eula_screen_.get(); 309} 310 311chromeos::RegistrationScreen* WizardController::GetRegistrationScreen() { 312 if (!registration_screen_.get()) 313 registration_screen_.reset(new chromeos::RegistrationScreen(this)); 314 return registration_screen_.get(); 315} 316 317void WizardController::ShowNetworkScreen() { 318 SetStatusAreaVisible(false); 319 SetCurrentScreen(GetNetworkScreen()); 320} 321 322void WizardController::ShowLoginScreen() { 323 SetStatusAreaVisible(true); 324 325 // When run under automation test show plain login screen. 326 if (!is_test_mode_ && 327 chromeos::CrosLibrary::Get()->EnsureLoaded() && 328 CommandLine::ForCurrentProcess()->HasSwitch( 329 switches::kEnableLoginImages)) { 330 std::vector<chromeos::UserManager::User> users = 331 chromeos::UserManager::Get()->GetUsers(); 332 // ExistingUserController deletes itself. 333 gfx::Rect screen_bounds; 334 background_widget_->GetBounds(&screen_bounds, true); 335 chromeos::ExistingUserController* controller = 336 new chromeos::ExistingUserController(users, screen_bounds); 337 controller->OwnBackground(background_widget_, background_view_); 338 controller->Init(); 339 background_widget_ = NULL; 340 background_view_ = NULL; 341 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 342 return; 343 } 344 345 SetCurrentScreen(GetLoginScreen()); 346} 347 348void WizardController::ShowAccountScreen() { 349 SetStatusAreaVisible(true); 350 SetCurrentScreen(GetAccountScreen()); 351} 352 353void WizardController::ShowUpdateScreen() { 354 SetStatusAreaVisible(true); 355 SetCurrentScreen(GetUpdateScreen()); 356} 357 358void WizardController::ShowUserImageScreen() { 359 SetStatusAreaVisible(true); 360 SetCurrentScreen(GetUserImageScreen()); 361} 362 363void WizardController::ShowEulaScreen() { 364 SetStatusAreaVisible(false); 365 SetCurrentScreen(GetEulaScreen()); 366} 367 368void WizardController::ShowRegistrationScreen() { 369 SetStatusAreaVisible(true); 370 SetCurrentScreen(GetRegistrationScreen()); 371} 372 373void WizardController::SetStatusAreaVisible(bool visible) { 374 // When ExistingUserController passes background ownership 375 // to WizardController it happens after screen is shown. 376 if (background_view_) { 377 background_view_->SetStatusAreaVisible(visible); 378 } 379} 380 381void WizardController::SetCustomization( 382 const chromeos::StartupCustomizationDocument* customization) { 383 customization_.reset(customization); 384} 385 386const chromeos::StartupCustomizationDocument* 387 WizardController::GetCustomization() { 388 return customization_.get(); 389} 390 391// static 392void WizardController::RegisterPrefs(PrefService* local_state) { 393 local_state->RegisterBooleanPref(kOobeComplete, false); 394} 395 396/////////////////////////////////////////////////////////////////////////////// 397// WizardController, ExitHandlers: 398void WizardController::OnLoginSignInSelected() { 399 // Don't show user image screen in case of automated testing. 400 if (is_test_mode_) { 401 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 402 return; 403 } 404 // Don't launch browser until we pass image screen. 405 chromeos::LoginUtils::Get()->EnableBrowserLaunch(false); 406 ShowUserImageScreen(); 407} 408 409void WizardController::OnLoginGuestUser() { 410 // We're on the stack, so don't try and delete us now. 411 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 412} 413 414void WizardController::OnLoginCreateAccount() { 415 ShowAccountScreen(); 416} 417 418void WizardController::OnNetworkConnected() { 419 if (is_out_of_box_) { 420 ShowUpdateScreen(); 421 GetUpdateScreen()->StartUpdate(); 422 } else { 423 // TODO(nkostylev): Remove this path after accelerator is removed. 424 ShowLoginScreen(); 425 } 426} 427 428void WizardController::OnNetworkOffline() { 429 // TODO(dpolukhin): if(is_out_of_box_) we cannot work offline and 430 // should report some error message here and stay on the same screen. 431 ShowLoginScreen(); 432} 433 434void WizardController::OnAccountCreateBack() { 435 ShowLoginScreen(); 436} 437 438void WizardController::OnAccountCreated() { 439 ShowLoginScreen(); 440 chromeos::LoginScreen* login = GetLoginScreen(); 441 if (!username_.empty()) { 442 login->view()->SetUsername(username_); 443 if (!password_.empty()) { 444 login->view()->SetPassword(password_); 445 // TODO(dpolukhin): clear password memory for real. Now it is not 446 // a problem becuase we can't extract password from the form. 447 password_.clear(); 448 login->view()->Login(); 449 } 450 } 451} 452 453void WizardController::OnConnectionFailed() { 454 // TODO(dpolukhin): show error message after login screen is displayed. 455 ShowLoginScreen(); 456} 457 458void WizardController::OnUpdateCompleted() { 459 ShowEulaScreen(); 460} 461 462void WizardController::OnEulaAccepted() { 463 MarkOobeCompleted(); 464 ShowLoginScreen(); 465} 466 467void WizardController::OnUpdateErrorCheckingForUpdate() { 468 // TODO(nkostylev): Update should be required during OOBE. 469 // We do not want to block users from being able to proceed to the login 470 // screen if there is any error checking for an update. 471 // They could use "browse without sign-in" feature to set up the network to be 472 // able to perform the update later. 473 ShowEulaScreen(); 474} 475 476void WizardController::OnUpdateErrorUpdating() { 477 // If there was an error while getting or applying the update, 478 // return to network selection screen. 479 // TODO(nkostylev): Show message to the user explaining update error. 480 // TODO(nkostylev): Update should be required during OOBE. 481 // Temporary fix, need to migrate to new API. http://crosbug.com/4321 482 ShowEulaScreen(); 483} 484 485void WizardController::OnUserImageSelected() { 486 // We're on the stack, so don't try and delete us now. 487 // We should launch browser only after we delete the controller and close 488 // its windows. 489 ChromeThread::PostTask( 490 ChromeThread::UI, 491 FROM_HERE, 492 NewRunnableFunction(&DeleteWizardControllerAndLaunchBrowser, 493 this)); 494 // TODO(avayvod): Sync image with Google Sync. 495} 496 497void WizardController::OnUserImageSkipped() { 498 OnUserImageSelected(); 499} 500 501void WizardController::OnRegistrationSuccess() { 502 // TODO(nkostylev): Registration screen should be shown on first sign in. 503 ShowLoginScreen(); 504} 505 506void WizardController::OnRegistrationSkipped() { 507 // TODO(nkostylev): Track in a histogram? 508 OnRegistrationSuccess(); 509} 510 511/////////////////////////////////////////////////////////////////////////////// 512// WizardController, private: 513 514void WizardController::SetCurrentScreen(WizardScreen* new_current) { 515 if (current_screen_ == new_current) 516 return; 517 if (current_screen_) 518 current_screen_->Hide(); 519 current_screen_ = new_current; 520 if (current_screen_) { 521 current_screen_->Show(); 522 contents_->Layout(); 523 } 524 contents_->SchedulePaint(); 525} 526 527void WizardController::OnSetUserNamePassword(const std::string& username, 528 const std::string& password) { 529 username_ = username; 530 password_ = password; 531} 532 533void WizardController::ShowFirstScreen(const std::string& first_screen_name) { 534 if (first_screen_name == kNetworkScreenName) { 535 ShowNetworkScreen(); 536 } else if (first_screen_name == kLoginScreenName) { 537 // This flag is passed if we're running under automation test. 538 is_test_mode_ = true; 539 ShowLoginScreen(); 540 } else if (first_screen_name == kAccountScreenName) { 541 ShowAccountScreen(); 542 } else if (first_screen_name == kUpdateScreenName) { 543 ShowUpdateScreen(); 544 GetUpdateScreen()->StartUpdate(); 545 } else if (first_screen_name == kUserImageScreenName) { 546 ShowUserImageScreen(); 547 } else if (first_screen_name == kEulaScreenName) { 548 ShowEulaScreen(); 549 } else if (first_screen_name == kRegistrationScreenName) { 550 ShowRegistrationScreen(); 551 } else if (first_screen_name != kTestNoScreenName) { 552 if (is_out_of_box_) { 553 ShowNetworkScreen(); 554 } else { 555 ShowLoginScreen(); 556 } 557 } 558} 559 560void WizardController::MarkOobeCompleted() { 561 PrefService* prefs = g_browser_process->local_state(); 562 prefs->SetBoolean(kOobeComplete, true); 563 // Make sure that changes are reflected immediately. 564 prefs->SavePersistentPrefs(); 565} 566 567/////////////////////////////////////////////////////////////////////////////// 568// WizardController, chromeos::ScreenObserver overrides: 569void WizardController::OnExit(ExitCodes exit_code) { 570 switch (exit_code) { 571 case LOGIN_SIGN_IN_SELECTED: 572 OnLoginSignInSelected(); 573 break; 574 case LOGIN_GUEST_SELECTED: 575 OnLoginGuestUser(); 576 break; 577 case LOGIN_CREATE_ACCOUNT: 578 OnLoginCreateAccount(); 579 break; 580 case NETWORK_CONNECTED: 581 OnNetworkConnected(); 582 break; 583 case NETWORK_OFFLINE: 584 OnNetworkOffline(); 585 break; 586 case ACCOUNT_CREATE_BACK: 587 OnAccountCreateBack(); 588 break; 589 case ACCOUNT_CREATED: 590 OnAccountCreated(); 591 break; 592 case CONNECTION_FAILED: 593 OnConnectionFailed(); 594 break; 595 case UPDATE_INSTALLED: 596 case UPDATE_NOUPDATE: 597 OnUpdateCompleted(); 598 break; 599 case UPDATE_ERROR_CHECKING_FOR_UPDATE: 600 OnUpdateErrorCheckingForUpdate(); 601 break; 602 case UPDATE_ERROR_UPDATING: 603 OnUpdateErrorUpdating(); 604 break; 605 case USER_IMAGE_SELECTED: 606 OnUserImageSelected(); 607 break; 608 case USER_IMAGE_SKIPPED: 609 OnUserImageSkipped(); 610 break; 611 case EULA_ACCEPTED: 612 OnEulaAccepted(); 613 break; 614 case REGISTRATION_SUCCESS: 615 OnRegistrationSuccess(); 616 break; 617 case REGISTRATION_SKIPPED: 618 OnRegistrationSkipped(); 619 break; 620 default: 621 NOTREACHED(); 622 } 623} 624 625/////////////////////////////////////////////////////////////////////////////// 626// WizardController, WizardScreen overrides: 627views::View* WizardController::GetWizardView() { 628 return contents_; 629} 630 631chromeos::ScreenObserver* WizardController::GetObserver(WizardScreen* screen) { 632 return observer_ ? observer_ : this; 633} 634 635namespace browser { 636 637// Declared in browser_dialogs.h so that others don't need to depend on our .h. 638void ShowLoginWizard(const std::string& first_screen_name, 639 const gfx::Size& size) { 640 LOG(INFO) << "showing login screen: " << first_screen_name; 641 642 // Tell the window manager that the user isn't logged in. 643 chromeos::WmIpc::instance()->SetLoggedInProperty(false); 644 645 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty 646 // and US dvorak keyboard layouts. 647 if (g_browser_process && g_browser_process->local_state()) { 648 const std::string locale = g_browser_process->GetApplicationLocale(); 649 const std::string initial_input_method_id = 650 g_browser_process->local_state()->GetString( 651 chromeos::kPreferredKeyboardLayout); 652 chromeos::input_method::EnableInputMethods( 653 locale, chromeos::input_method::kKeyboardLayoutsOnly, 654 initial_input_method_id); 655 } 656 657 gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(size)); 658 659 // Check whether we need to execute OOBE process. 660 bool oobe_complete = g_browser_process->local_state()-> 661 GetBoolean(kOobeComplete); 662 663 if (first_screen_name.empty() && 664 oobe_complete && 665 chromeos::CrosLibrary::Get()->EnsureLoaded() && 666 CommandLine::ForCurrentProcess()->HasSwitch( 667 switches::kEnableLoginImages)) { 668 std::vector<chromeos::UserManager::User> users = 669 chromeos::UserManager::Get()->GetUsers(); 670 // ExistingUserController deletes itself. 671 (new chromeos::ExistingUserController(users, screen_bounds))->Init(); 672 return; 673 } 674 675 scoped_ptr<chromeos::StartupCustomizationDocument> customization; 676 677 if (!oobe_complete) { 678 // Load partner customization startup manifest if needed. 679 if (CommandLine::ForCurrentProcess()->HasSwitch( 680 switches::kStartupManifest)) { 681 customization.reset(new chromeos::StartupCustomizationDocument()); 682 FilePath manifest_path = 683 CommandLine::ForCurrentProcess()->GetSwitchValuePath( 684 switches::kStartupManifest); 685 bool manifest_loaded = customization->LoadManifestFromFile(manifest_path); 686 DCHECK(manifest_loaded) << manifest_path.value(); 687 } 688 689 // Do UX customizations if needed. 690 if (customization != NULL) { 691 // Switch to initial locale if specified by customization. 692 const std::string locale = customization->initial_locale(); 693 if (!locale.empty()) { 694 chromeos::LanguageSwitchMenu::SwitchLanguage(locale); 695 } 696 697 // Set initial timezone if specified by customization. 698 const std::string timezone_name = customization->initial_timezone(); 699 if (!timezone_name.empty()) { 700 icu::TimeZone* timezone = icu::TimeZone::createTimeZone( 701 icu::UnicodeString::fromUTF8(timezone_name)); 702 chromeos::CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone); 703 } 704 } 705 } 706 707 // Create and show the wizard. 708 WizardController* controller = new WizardController(); 709 if (!oobe_complete) 710 controller->SetCustomization(customization.release()); 711 controller->ShowBackground(screen_bounds); 712 controller->Init(first_screen_name, screen_bounds); 713 controller->Show(); 714 if (chromeos::CrosLibrary::Get()->EnsureLoaded()) 715 chromeos::CrosLibrary::Get()->GetLoginLibrary()->EmitLoginPromptReady(); 716} 717 718} // namespace browser 719