This source file includes following definitions.
- DetermineAndSaveHardwareKeyboard
- OnImplicitAnimationsCompleted
- ShowLoginWizardFinish
- OnLanguageSwitchedCallback
- EnableSystemSoundsForAccessibility
- AddToSetIfIsGaiaAuthIframe
- DeleteDelegate
- GetWidget
- GetWidget
- CanActivate
- ShouldAdvanceFocusToTopLevelWidget
- GetGaiaAuthIframe
- is_observing_keyboard_
- CreateLoginDisplay
- GetNativeWindow
- GetWebUILoginView
- BeforeSessionStart
- Finalize
- OnCompleteLogin
- OpenProxySettings
- SetStatusAreaVisible
- GetAutoEnrollmentController
- StartWizard
- GetWizardController
- GetAppLaunchController
- StartUserAdding
- StartSignInScreen
- ResumeSignInScreen
- OnPreferencesChanged
- PrewarmAuthentication
- StartDemoAppLaunch
- StartAppLaunch
- CreateWizardController
- OnBrowserCreated
- GetOobeUI
- Observe
- RenderProcessGone
- EmitLoginPromptVisibleCalled
- OnActiveOutputNodeChanged
- OnVirtualKeyboardStateChanged
- OnKeyboardBoundsChanging
- ShutdownDisplayHost
- ScheduleWorkspaceAnimation
- ScheduleFadeOutAnimation
- OnAutoEnrollmentProgress
- LoadURL
- ShowWebUI
- StartPostponedWebUI
- InitLoginWindowAndView
- ResetLoginWindowAndView
- OnAuthPrewarmDone
- SetOobeProgressBarVisible
- TryToPlayStartupSound
- OnLoginPromptVisible
- ShowLoginWizard
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include <vector>
#include "ash/audio/sounds.h"
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/charger_replace/charger_replacement_dialog.h"
#include "chrome/browser/chromeos/first_run/drive_first_run_controller.h"
#include "chrome/browser/chromeos/first_run/first_run.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/input_events_blocker.h"
#include "chrome/browser/chromeos/login/keyboard_driven_oobe_key_handler.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/oobe_display.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/login/webui_login_view.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/mobile_config.h"
#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/system/input_device_settings.h"
#include "chrome/browser/chromeos/ui/focus_ring_controller.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chromeos/audio/chromeos_sounds.h"
#include "chromeos/chromeos_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/ime/extension_ime_util.h"
#include "chromeos/ime/input_method_manager.h"
#include "chromeos/login/login_state.h"
#include "chromeos/settings/timezone_settings.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/web_ui.h"
#include "grit/browser_resources.h"
#include "media/audio/sounds/sounds_manager.h"
#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/window_animations.h"
#include "url/gurl.h"
namespace {
const int kStartupSoundMaxDelayMs = 2000;
const char kLoginURL[] = "chrome://oobe/login";
const char kOobeURL[] = "chrome://oobe/oobe";
const char kUserAddingURL[] = "chrome://oobe/user-adding";
const char kAppLaunchSplashURL[] = "chrome://oobe/app-launch-splash";
const int kLoginFadeoutTransitionDurationMs = 700;
const int kCrashCountLimit = 5;
const bool kHiddenWebUIInitializationDefault = true;
const char kWebUIInitParallel[] = "parallel";
const char kWebUIInitPostpone[] = "postpone";
const int64 kPolicyServiceInitializationDelayMilliseconds = 100;
void DetermineAndSaveHardwareKeyboard(const std::string& locale,
const std::string& oem_layout) {
chromeos::input_method::InputMethodManager* manager =
chromeos::input_method::InputMethodManager::Get();
std::string layout;
if (!oem_layout.empty()) {
layout = oem_layout;
} else {
std::vector<std::string> input_method_ids;
if (manager->GetInputMethodUtil()->GetInputMethodIdsFromLanguageCode(
locale,
chromeos::input_method::kKeyboardLayoutsOnly,
&input_method_ids)) {
layout = input_method_ids[0];
}
}
if (!layout.empty()) {
std::vector<std::string> layouts;
base::SplitString(layout, ',', &layouts);
manager->MigrateXkbInputMethods(&layouts);
PrefService* prefs = g_browser_process->local_state();
prefs->SetString(prefs::kHardwareKeyboardLayout, JoinString(layouts, ","));
prefs->CommitPendingWrite();
manager->GetInputMethodUtil()->UpdateHardwareLayoutCache();
manager->SetInputMethodLoginDefault();
}
}
class AnimationObserver : public ui::ImplicitAnimationObserver {
public:
explicit AnimationObserver(const base::Closure& callback)
: callback_(callback) {}
virtual ~AnimationObserver() {}
private:
virtual void OnImplicitAnimationsCompleted() OVERRIDE {
callback_.Run();
delete this;
}
base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(AnimationObserver);
};
void ShowLoginWizardFinish(
const std::string& first_screen_name,
const chromeos::StartupCustomizationDocument* startup_manifest,
chromeos::LoginDisplayHost* display_host) {
TRACE_EVENT0("chromeos", "ShowLoginWizard::ShowLoginWizardFinish");
scoped_ptr<base::DictionaryValue> params;
display_host->StartWizard(first_screen_name, params.Pass());
const std::string timezone_name = startup_manifest->initial_timezone();
VLOG(1) << "Initial time zone: " << timezone_name;
if (!timezone_name.empty()) {
chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
base::UTF8ToUTF16(timezone_name));
}
}
struct ShowLoginWizardSwitchLanguageCallbackData {
explicit ShowLoginWizardSwitchLanguageCallbackData(
const std::string& first_screen_name,
const chromeos::StartupCustomizationDocument* startup_manifest,
chromeos::LoginDisplayHost* display_host)
: first_screen_name(first_screen_name),
startup_manifest(startup_manifest),
display_host(display_host) {}
const std::string first_screen_name;
const chromeos::StartupCustomizationDocument* const startup_manifest;
chromeos::LoginDisplayHost* const display_host;
chromeos::InputEventsBlocker events_blocker;
};
void OnLanguageSwitchedCallback(
scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> self,
const std::string& locale,
const std::string& loaded_locale,
const bool success) {
if (!success)
LOG(WARNING) << "Locale could not be found for '" << locale << "'";
ShowLoginWizardFinish(
self->first_screen_name, self->startup_manifest, self->display_host);
}
void EnableSystemSoundsForAccessibility() {
chromeos::AccessibilityManager::Get()->EnableSystemSounds(true);
}
void AddToSetIfIsGaiaAuthIframe(std::set<content::RenderFrameHost*>* frame_set,
content::RenderFrameHost* frame) {
content::RenderFrameHost* parent = frame->GetParent();
if (parent && parent->GetFrameName() == "signin-frame")
frame_set->insert(frame);
}
class LoginWidgetDelegate : public views::WidgetDelegate {
public:
explicit LoginWidgetDelegate(views::Widget* widget) : widget_(widget) {
}
virtual ~LoginWidgetDelegate() {}
virtual void DeleteDelegate() OVERRIDE {
delete this;
}
virtual views::Widget* GetWidget() OVERRIDE {
return widget_;
}
virtual const views::Widget* GetWidget() const OVERRIDE {
return widget_;
}
virtual bool CanActivate() const OVERRIDE {
return true;
}
virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
return true;
}
private:
views::Widget* widget_;
DISALLOW_COPY_AND_ASSIGN(LoginWidgetDelegate);
};
}
namespace chromeos {
LoginDisplayHost* LoginDisplayHostImpl::default_host_ = NULL;
const int LoginDisplayHostImpl::kShowLoginWebUIid = 0x1111;
content::RenderFrameHost* LoginDisplayHostImpl::GetGaiaAuthIframe(
content::WebContents* web_contents) {
std::set<content::RenderFrameHost*> frame_set;
web_contents->ForEachFrame(
base::Bind(&AddToSetIfIsGaiaAuthIframe, &frame_set));
DCHECK_EQ(1U, frame_set.size());
return *frame_set.begin();
}
LoginDisplayHostImpl::LoginDisplayHostImpl(const gfx::Rect& background_bounds)
: background_bounds_(background_bounds),
pointer_factory_(this),
shutting_down_(false),
oobe_progress_bar_visible_(false),
session_starting_(false),
login_window_(NULL),
login_view_(NULL),
webui_login_display_(NULL),
is_showing_login_(false),
is_wallpaper_loaded_(false),
status_area_saved_visibility_(false),
crash_count_(0),
restore_path_(RESTORE_UNKNOWN),
finalize_animation_type_(ANIMATION_WORKSPACE),
animation_weak_ptr_factory_(this),
startup_sound_played_(false),
startup_sound_honors_spoken_feedback_(false),
is_observing_keyboard_(false) {
DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
CrasAudioHandler::Get()->AddAudioObserver(this);
if (ash::Shell::GetInstance()->keyboard_controller()) {
ash::Shell::GetInstance()->keyboard_controller()->AddObserver(this);
is_observing_keyboard_ = true;
}
ash::Shell::GetInstance()->delegate()->AddVirtualKeyboardStateObserver(this);
registrar_.Add(this,
chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
content::NotificationService::AllSources());
registrar_.Add(this,
chrome::NOTIFICATION_BROWSER_OPENED,
content::NotificationService::AllSources());
registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources());
DCHECK(default_host_ == NULL);
default_host_ = this;
chrome::IncrementKeepAliveCount();
bool is_registered = StartupUtils::IsDeviceRegistered();
bool zero_delay_enabled = WizardController::IsZeroDelayEnabled();
bool disable_boot_animation = CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableBootAnimation);
waiting_for_wallpaper_load_ = !zero_delay_enabled &&
(!is_registered || !disable_boot_animation);
waiting_for_user_pods_ = !zero_delay_enabled && !waiting_for_wallpaper_load_;
initialize_webui_hidden_ =
kHiddenWebUIInitializationDefault && !zero_delay_enabled;
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshWebUIInit)) {
const std::string override_type =
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kAshWebUIInit);
if (override_type == kWebUIInitParallel)
initialize_webui_hidden_ = true;
else if (override_type == kWebUIInitPostpone)
initialize_webui_hidden_ = false;
}
if (!StartupUtils::IsOobeCompleted())
initialize_webui_hidden_ = false;
if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
initialize_webui_hidden_ = false;
if (waiting_for_wallpaper_load_) {
registrar_.Add(this,
chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
content::NotificationService::AllSources());
}
if ((waiting_for_user_pods_ || waiting_for_wallpaper_load_) &&
initialize_webui_hidden_) {
registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
content::NotificationService::AllSources());
registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
content::NotificationService::AllSources());
}
LOG(WARNING) << "Login WebUI >> "
<< "zero_delay: " << zero_delay_enabled
<< " wait_for_wp_load_: " << waiting_for_wallpaper_load_
<< " wait_for_pods_: " << waiting_for_user_pods_
<< " init_webui_hidden_: " << initialize_webui_hidden_;
media::SoundsManager* manager = media::SoundsManager::Get();
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
manager->Initialize(chromeos::SOUND_STARTUP,
bundle.GetRawDataResource(IDR_SOUND_STARTUP_WAV));
}
LoginDisplayHostImpl::~LoginDisplayHostImpl() {
DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
CrasAudioHandler::Get()->RemoveAudioObserver(this);
if (ash::Shell::GetInstance()->keyboard_controller() &&
is_observing_keyboard_) {
ash::Shell::GetInstance()->keyboard_controller()->RemoveObserver(this);
is_observing_keyboard_ = false;
}
ash::Shell::GetInstance()->delegate()->
RemoveVirtualKeyboardStateObserver(this);
views::FocusManager::set_arrow_key_traversal_enabled(false);
ResetLoginWindowAndView();
chrome::DecrementKeepAliveCount();
default_host_ = NULL;
if (UserManager::Get()->IsCurrentUserNew()) {
(new DriveFirstRunController(
ProfileManager::GetActiveUserProfile()))->EnableOfflineMode();
}
}
LoginDisplay* LoginDisplayHostImpl::CreateLoginDisplay(
LoginDisplay::Delegate* delegate) {
webui_login_display_ = new WebUILoginDisplay(delegate);
webui_login_display_->set_background_bounds(background_bounds());
return webui_login_display_;
}
gfx::NativeWindow LoginDisplayHostImpl::GetNativeWindow() const {
return login_window_ ? login_window_->GetNativeWindow() : NULL;
}
WebUILoginView* LoginDisplayHostImpl::GetWebUILoginView() const {
return login_view_;
}
void LoginDisplayHostImpl::BeforeSessionStart() {
session_starting_ = true;
}
void LoginDisplayHostImpl::Finalize() {
DVLOG(1) << "Session starting";
if (ash::Shell::HasInstance()) {
ash::Shell::GetInstance()->
desktop_background_controller()->MoveDesktopToUnlockedContainer();
}
if (wizard_controller_.get())
wizard_controller_->OnSessionStart();
switch (finalize_animation_type_) {
case ANIMATION_NONE:
ShutdownDisplayHost(false);
break;
case ANIMATION_WORKSPACE:
if (ash::Shell::HasInstance())
ScheduleWorkspaceAnimation();
ShutdownDisplayHost(false);
break;
case ANIMATION_FADE_OUT:
ScheduleFadeOutAnimation();
break;
}
}
void LoginDisplayHostImpl::OnCompleteLogin() {
if (auto_enrollment_controller_)
auto_enrollment_controller_->Cancel();
}
void LoginDisplayHostImpl::OpenProxySettings() {
if (login_view_)
login_view_->OpenProxySettings();
}
void LoginDisplayHostImpl::SetStatusAreaVisible(bool visible) {
if (initialize_webui_hidden_)
status_area_saved_visibility_ = visible;
else if (login_view_)
login_view_->SetStatusAreaVisible(visible);
}
AutoEnrollmentController* LoginDisplayHostImpl::GetAutoEnrollmentController() {
if (!auto_enrollment_controller_) {
auto_enrollment_controller_.reset(new AutoEnrollmentController());
auto_enrollment_progress_subscription_ =
auto_enrollment_controller_->RegisterProgressCallback(
base::Bind(&LoginDisplayHostImpl::OnAutoEnrollmentProgress,
base::Unretained(this)));
}
return auto_enrollment_controller_.get();
}
void LoginDisplayHostImpl::StartWizard(
const std::string& first_screen_name,
scoped_ptr<base::DictionaryValue> screen_parameters) {
startup_sound_honors_spoken_feedback_ = true;
TryToPlayStartupSound();
restore_path_ = RESTORE_WIZARD;
wizard_first_screen_name_ = first_screen_name;
if (screen_parameters.get())
wizard_screen_parameters_.reset(screen_parameters->DeepCopy());
else
wizard_screen_parameters_.reset();
is_showing_login_ = false;
if (waiting_for_wallpaper_load_ && !initialize_webui_hidden_) {
LOG(WARNING) << "Login WebUI >> wizard postponed";
return;
}
LOG(WARNING) << "Login WebUI >> wizard";
if (!login_window_)
LoadURL(GURL(kOobeURL));
DVLOG(1) << "Starting wizard, first_screen_name: " << first_screen_name;
wizard_controller_.reset();
wizard_controller_.reset(CreateWizardController());
oobe_progress_bar_visible_ = !StartupUtils::IsDeviceRegistered();
SetOobeProgressBarVisible(oobe_progress_bar_visible_);
wizard_controller_->Init(first_screen_name, screen_parameters.Pass());
}
WizardController* LoginDisplayHostImpl::GetWizardController() {
return wizard_controller_.get();
}
AppLaunchController* LoginDisplayHostImpl::GetAppLaunchController() {
return app_launch_controller_.get();
}
void LoginDisplayHostImpl::StartUserAdding(
const base::Closure& completion_callback) {
restore_path_ = RESTORE_ADD_USER_INTO_SESSION;
completion_callback_ = completion_callback;
finalize_animation_type_ = ANIMATION_NONE;
LOG(WARNING) << "Login WebUI >> user adding";
if (!login_window_)
LoadURL(GURL(kUserAddingURL));
login_view_->set_should_emit_login_prompt_visible(false);
aura::Window* lock_container = ash::Shell::GetContainer(
ash::Shell::GetPrimaryRootWindow(),
ash::kShellWindowId_LockScreenContainersContainer);
lock_container->layer()->SetOpacity(1.0);
ash::Shell::GetInstance()->
desktop_background_controller()->MoveDesktopToLockedContainer();
sign_in_controller_.reset();
sign_in_controller_.reset(new chromeos::ExistingUserController(this));
SetOobeProgressBarVisible(oobe_progress_bar_visible_ = false);
SetStatusAreaVisible(true);
sign_in_controller_->Init(
chromeos::UserManager::Get()->GetUsersAdmittedForMultiProfile());
CHECK(webui_login_display_);
GetOobeUI()->ShowSigninScreen(LoginScreenContext(),
webui_login_display_,
webui_login_display_);
}
void LoginDisplayHostImpl::StartSignInScreen(
const LoginScreenContext& context) {
startup_sound_honors_spoken_feedback_ = true;
TryToPlayStartupSound();
restore_path_ = RESTORE_SIGN_IN;
is_showing_login_ = true;
finalize_animation_type_ = ANIMATION_WORKSPACE;
PrewarmAuthentication();
if (waiting_for_wallpaper_load_ && !initialize_webui_hidden_) {
LOG(WARNING) << "Login WebUI >> sign in postponed";
return;
}
LOG(WARNING) << "Login WebUI >> sign in";
if (!login_window_) {
TRACE_EVENT_ASYNC_BEGIN0("ui", "ShowLoginWebUI", kShowLoginWebUIid);
TRACE_EVENT_ASYNC_STEP_INTO0(
"ui", "ShowLoginWebUI", kShowLoginWebUIid, "StartSignInScreen");
BootTimesLoader::Get()->RecordCurrentStats("login-start-signin-screen");
LoadURL(GURL(kLoginURL));
}
DVLOG(1) << "Starting sign in screen";
const chromeos::UserList& users = chromeos::UserManager::Get()->GetUsers();
if (!StartupUtils::IsDeviceRegistered() && !users.empty()) {
VLOG(1) << "Mark device registered because there are remembered users: "
<< users.size();
StartupUtils::MarkDeviceRegistered();
}
sign_in_controller_.reset();
sign_in_controller_.reset(new chromeos::ExistingUserController(this));
oobe_progress_bar_visible_ = !StartupUtils::IsDeviceRegistered();
SetOobeProgressBarVisible(oobe_progress_bar_visible_);
SetStatusAreaVisible(true);
sign_in_controller_->Init(users);
if (GetAutoEnrollmentController()->ShouldEnrollSilently())
sign_in_controller_->DoAutoEnrollment();
else
GetAutoEnrollmentController()->Start();
MobileConfig::GetInstance();
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
connector->ScheduleServiceInitialization(
kPolicyServiceInitializationDelayMilliseconds);
CHECK(webui_login_display_);
GetOobeUI()->ShowSigninScreen(context,
webui_login_display_,
webui_login_display_);
if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
SetStatusAreaVisible(false);
TRACE_EVENT_ASYNC_STEP_INTO0("ui",
"ShowLoginWebUI",
kShowLoginWebUIid,
"WaitForScreenStateInitialize");
BootTimesLoader::Get()->RecordCurrentStats(
"login-wait-for-signin-state-initialize");
}
void LoginDisplayHostImpl::ResumeSignInScreen() {
DVLOG(1) << "Resuming sign in screen";
CHECK(sign_in_controller_.get());
SetOobeProgressBarVisible(oobe_progress_bar_visible_);
SetStatusAreaVisible(true);
sign_in_controller_->ResumeLogin();
}
void LoginDisplayHostImpl::OnPreferencesChanged() {
if (is_showing_login_)
webui_login_display_->OnPreferencesChanged();
}
void LoginDisplayHostImpl::PrewarmAuthentication() {
auth_prewarmer_.reset(new AuthPrewarmer());
auth_prewarmer_->PrewarmAuthentication(
base::Bind(&LoginDisplayHostImpl::OnAuthPrewarmDone,
pointer_factory_.GetWeakPtr()));
}
void LoginDisplayHostImpl::StartDemoAppLaunch() {
LOG(WARNING) << "Login WebUI >> starting demo app.";
SetStatusAreaVisible(false);
demo_app_launcher_.reset(new DemoAppLauncher());
demo_app_launcher_->StartDemoAppLaunch();
}
void LoginDisplayHostImpl::StartAppLaunch(const std::string& app_id,
bool diagnostic_mode) {
LOG(WARNING) << "Login WebUI >> start app launch.";
SetStatusAreaVisible(false);
finalize_animation_type_ = ANIMATION_FADE_OUT;
if (!login_window_)
LoadURL(GURL(kAppLaunchSplashURL));
login_view_->set_should_emit_login_prompt_visible(false);
app_launch_controller_.reset(new AppLaunchController(
app_id, diagnostic_mode, this, GetOobeUI()));
app_launch_controller_->StartAppLaunch();
}
WizardController* LoginDisplayHostImpl::CreateWizardController() {
OobeDisplay* oobe_display = GetOobeUI();
return new WizardController(this, oobe_display);
}
void LoginDisplayHostImpl::OnBrowserCreated() {
ResetLoginWindowAndView();
}
OobeUI* LoginDisplayHostImpl::GetOobeUI() const {
if (!login_view_)
return NULL;
return static_cast<OobeUI*>(login_view_->GetWebUI()->GetController());
}
void LoginDisplayHostImpl::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED == type) {
LOG(WARNING) << "Login WebUI >> wp animation done";
is_wallpaper_loaded_ = true;
ash::Shell::GetInstance()->user_wallpaper_delegate()
->OnWallpaperBootAnimationFinished();
if (waiting_for_wallpaper_load_) {
waiting_for_wallpaper_load_ = false;
if (initialize_webui_hidden_)
ShowWebUI();
else
StartPostponedWebUI();
}
registrar_.Remove(this,
chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
content::NotificationService::AllSources());
} else if (chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE == type ||
chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN == type) {
LOG(WARNING) << "Login WebUI >> WEBUI_VISIBLE";
if (waiting_for_user_pods_ && initialize_webui_hidden_) {
waiting_for_user_pods_ = false;
ShowWebUI();
} else if (waiting_for_wallpaper_load_ && initialize_webui_hidden_) {
waiting_for_wallpaper_load_ = false;
ShowWebUI();
}
registrar_.Remove(this,
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
content::NotificationService::AllSources());
registrar_.Remove(this,
chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
content::NotificationService::AllSources());
} else if (type == chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST) {
ShutdownDisplayHost(true);
} else if (type == chrome::NOTIFICATION_BROWSER_OPENED && session_starting_) {
OnBrowserCreated();
registrar_.Remove(this,
chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
content::NotificationService::AllSources());
registrar_.Remove(this,
chrome::NOTIFICATION_BROWSER_OPENED,
content::NotificationService::AllSources());
} else if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED &&
chromeos::UserManager::Get()->IsCurrentUserNew()) {
ash::Shell::GetInstance()->
desktop_background_controller()->MoveDesktopToLockedContainer();
registrar_.Remove(this,
chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources());
}
}
void LoginDisplayHostImpl::RenderProcessGone(base::TerminationStatus status) {
if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID)
return;
crash_count_++;
if (crash_count_ > kCrashCountLimit)
return;
if (status != base::TERMINATION_STATUS_NORMAL_TERMINATION) {
LOG(FATAL) << "Renderer crash on login window";
}
}
void LoginDisplayHostImpl::EmitLoginPromptVisibleCalled() {
OnLoginPromptVisible();
}
void LoginDisplayHostImpl::OnActiveOutputNodeChanged() {
TryToPlayStartupSound();
}
void LoginDisplayHostImpl::OnVirtualKeyboardStateChanged(bool activated) {
if (ash::Shell::GetInstance()->keyboard_controller()) {
if (activated) {
if (!is_observing_keyboard_) {
ash::Shell::GetInstance()->keyboard_controller()->AddObserver(this);
is_observing_keyboard_ = true;
}
} else {
ash::Shell::GetInstance()->keyboard_controller()->RemoveObserver(this);
is_observing_keyboard_ = false;
}
}
}
void LoginDisplayHostImpl::OnKeyboardBoundsChanging(
const gfx::Rect& new_bounds) {
if (new_bounds.IsEmpty() && !keyboard_bounds_.IsEmpty()) {
if (webui_login_display_)
webui_login_display_->ShowControlBar(true);
} else if (!new_bounds.IsEmpty() && keyboard_bounds_.IsEmpty()) {
if (webui_login_display_)
webui_login_display_->ShowControlBar(false);
}
keyboard_bounds_ = new_bounds;
}
void LoginDisplayHostImpl::ShutdownDisplayHost(bool post_quit_task) {
if (shutting_down_)
return;
shutting_down_ = true;
registrar_.RemoveAll();
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
if (post_quit_task)
base::MessageLoop::current()->Quit();
if (!completion_callback_.is_null())
completion_callback_.Run();
}
void LoginDisplayHostImpl::ScheduleWorkspaceAnimation() {
if (ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(),
ash::kShellWindowId_DesktopBackgroundContainer)
->children()
.empty()) {
return;
}
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableLoginAnimations))
ash::Shell::GetInstance()->DoInitialWorkspaceAnimation();
}
void LoginDisplayHostImpl::ScheduleFadeOutAnimation() {
ui::Layer* layer = login_window_->GetLayer();
ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
animation.AddObserver(new AnimationObserver(
base::Bind(&LoginDisplayHostImpl::ShutdownDisplayHost,
animation_weak_ptr_factory_.GetWeakPtr(),
false)));
layer->SetOpacity(0);
}
void LoginDisplayHostImpl::OnAutoEnrollmentProgress(
policy::AutoEnrollmentState state) {
VLOG(1) << "OnAutoEnrollmentProgress, state " << state;
if (sign_in_controller_ &&
auto_enrollment_controller_->ShouldEnrollSilently()) {
sign_in_controller_->DoAutoEnrollment();
}
}
void LoginDisplayHostImpl::LoadURL(const GURL& url) {
InitLoginWindowAndView();
content::WebContentsObserver::Observe(login_view_->GetWebContents());
login_view_->LoadURL(url);
ChargerReplacementDialog::SetFocusOnChargerDialogIfVisible();
}
void LoginDisplayHostImpl::ShowWebUI() {
if (!login_window_ || !login_view_) {
NOTREACHED();
return;
}
LOG(WARNING) << "Login WebUI >> Show already initialized UI";
login_window_->Show();
login_view_->GetWebContents()->GetView()->Focus();
login_view_->SetStatusAreaVisible(status_area_saved_visibility_);
login_view_->OnPostponedShow();
ChargerReplacementDialog::SetFocusOnChargerDialogIfVisible();
initialize_webui_hidden_ = false;
}
void LoginDisplayHostImpl::StartPostponedWebUI() {
if (!is_wallpaper_loaded_) {
NOTREACHED();
return;
}
LOG(WARNING) << "Login WebUI >> Init postponed WebUI";
if (restore_path_ == RESTORE_UNKNOWN) {
NOTREACHED();
return;
}
switch (restore_path_) {
case RESTORE_WIZARD:
StartWizard(wizard_first_screen_name_,
wizard_screen_parameters_.Pass());
break;
case RESTORE_SIGN_IN:
StartSignInScreen(LoginScreenContext());
break;
case RESTORE_ADD_USER_INTO_SESSION:
StartUserAdding(completion_callback_);
break;
default:
NOTREACHED();
break;
}
}
void LoginDisplayHostImpl::InitLoginWindowAndView() {
if (login_window_)
return;
if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation()) {
views::FocusManager::set_arrow_key_traversal_enabled(true);
focus_ring_controller_.reset(new FocusRingController);
focus_ring_controller_->SetVisible(true);
keyboard_driven_oobe_key_handler_.reset(new KeyboardDrivenOobeKeyHandler);
}
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.bounds = background_bounds();
params.show_state = ui::SHOW_STATE_MAXIMIZED;
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.parent =
ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(),
ash::kShellWindowId_LockScreenContainer);
login_window_ = new views::Widget;
params.delegate = new LoginWidgetDelegate(login_window_);
login_window_->Init(params);
login_view_ = new WebUILoginView();
login_view_->Init();
if (login_view_->webui_visible())
OnLoginPromptVisible();
wm::SetWindowVisibilityAnimationDuration(
login_window_->GetNativeView(),
base::TimeDelta::FromMilliseconds(kLoginFadeoutTransitionDurationMs));
wm::SetWindowVisibilityAnimationTransition(
login_window_->GetNativeView(),
wm::ANIMATE_HIDE);
login_window_->SetContentsView(login_view_);
if (!initialize_webui_hidden_ ||
(!waiting_for_wallpaper_load_ && !waiting_for_user_pods_)) {
LOG(WARNING) << "Login WebUI >> show login wnd on create";
login_window_->Show();
} else {
LOG(WARNING) << "Login WebUI >> login wnd is hidden on create";
login_view_->set_is_hidden(true);
}
login_window_->GetNativeView()->SetName("WebUILoginView");
}
void LoginDisplayHostImpl::ResetLoginWindowAndView() {
if (!login_window_)
return;
login_window_->Close();
login_window_ = NULL;
login_view_ = NULL;
}
void LoginDisplayHostImpl::OnAuthPrewarmDone() {
auth_prewarmer_.reset();
}
void LoginDisplayHostImpl::SetOobeProgressBarVisible(bool visible) {
GetOobeUI()->ShowOobeUI(visible);
}
void LoginDisplayHostImpl::TryToPlayStartupSound() {
if (startup_sound_played_ || login_prompt_visible_time_.is_null() ||
!CrasAudioHandler::Get()->GetActiveOutputNode()) {
return;
}
startup_sound_played_ = true;
if (base::TimeTicks::Now() - login_prompt_visible_time_ >
base::TimeDelta::FromMilliseconds(kStartupSoundMaxDelayMs)) {
EnableSystemSoundsForAccessibility();
return;
}
if (!startup_sound_honors_spoken_feedback_ &&
!ash::PlaySystemSoundAlways(SOUND_STARTUP)) {
EnableSystemSoundsForAccessibility();
return;
}
if (startup_sound_honors_spoken_feedback_ &&
!ash::PlaySystemSoundIfSpokenFeedback(SOUND_STARTUP)) {
EnableSystemSoundsForAccessibility();
return;
}
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&EnableSystemSoundsForAccessibility),
media::SoundsManager::Get()->GetDuration(SOUND_STARTUP));
}
void LoginDisplayHostImpl::OnLoginPromptVisible() {
if (!login_prompt_visible_time_.is_null())
return;
login_prompt_visible_time_ = base::TimeTicks::Now();
TryToPlayStartupSound();
}
void ShowLoginWizard(const std::string& first_screen_name) {
if (browser_shutdown::IsTryingToQuit())
return;
VLOG(1) << "Showing OOBE screen: " << first_screen_name;
chromeos::input_method::InputMethodManager* manager =
chromeos::input_method::InputMethodManager::Get();
if (g_browser_process && g_browser_process->local_state()) {
manager->SetInputMethodLoginDefault();
PrefService* prefs = g_browser_process->local_state();
system::InputDeviceSettings::Get()->SetPrimaryButtonRight(
prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight));
system::InputDeviceSettings::Get()->SetTapToClick(
prefs->GetBoolean(prefs::kOwnerTapToClickEnabled));
}
system::InputDeviceSettings::Get()->SetNaturalScroll(
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNaturalScrollDefault));
gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size()));
bool oobe_complete = chromeos::StartupUtils::IsOobeCompleted();
if (!oobe_complete) {
LoginState::Get()->SetLoggedInState(
LoginState::LOGGED_IN_OOBE, LoginState::LOGGED_IN_USER_NONE);
} else {
LoginState::Get()->SetLoggedInState(
LoginState::LOGGED_IN_NONE, LoginState::LOGGED_IN_USER_NONE);
}
LoginDisplayHost* display_host = new LoginDisplayHostImpl(screen_bounds);
bool show_app_launch_splash_screen = (first_screen_name ==
chromeos::WizardController::kAppLaunchSplashScreenName);
if (show_app_launch_splash_screen) {
const std::string& auto_launch_app_id =
chromeos::KioskAppManager::Get()->GetAutoLaunchApp();
display_host->StartAppLaunch(auto_launch_app_id,
false );
return;
}
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
bool should_show_enrollment_screen =
first_screen_name.empty() && oobe_complete &&
chromeos::WizardController::ShouldAutoStartEnrollment() &&
!connector->IsEnterpriseManaged();
if (should_show_enrollment_screen) {
display_host->StartWizard(chromeos::WizardController::kNetworkScreenName,
scoped_ptr<base::DictionaryValue>());
return;
}
bool show_login_screen =
(first_screen_name.empty() && oobe_complete) ||
first_screen_name == chromeos::WizardController::kLoginScreenName;
if (show_login_screen) {
PrefService* prefs = g_browser_process->local_state();
if (!prefs->HasPrefPath(prefs::kApplicationLocale)) {
std::string locale = chromeos::StartupUtils::GetInitialLocale();
prefs->SetString(prefs::kApplicationLocale, locale);
manager->EnableLoginLayouts(
locale,
manager->GetInputMethodUtil()->GetHardwareInputMethodIds());
base::ThreadRestrictions::ScopedAllowIO allow_io;
const std::string loaded_locale =
ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
g_browser_process->SetApplicationLocale(loaded_locale);
}
display_host->StartSignInScreen(LoginScreenContext());
return;
}
const chromeos::StartupCustomizationDocument* startup_manifest =
chromeos::StartupCustomizationDocument::GetInstance();
PrefService* prefs = g_browser_process->local_state();
const std::string current_locale =
prefs->GetString(prefs::kApplicationLocale);
VLOG(1) << "Current locale: " << current_locale;
std::string locale = startup_manifest->initial_locale_default();
std::string layout = startup_manifest->keyboard_layout();
VLOG(1) << "Initial locale: " << locale << "keyboard layout " << layout;
DetermineAndSaveHardwareKeyboard(locale, layout);
if (!current_locale.empty() || locale.empty()) {
ShowLoginWizardFinish(first_screen_name, startup_manifest, display_host);
return;
}
prefs->SetString(prefs::kApplicationLocale, locale);
chromeos::StartupUtils::SetInitialLocale(locale);
scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> data(
new ShowLoginWizardSwitchLanguageCallbackData(
first_screen_name, startup_manifest, display_host));
scoped_ptr<locale_util::SwitchLanguageCallback> callback(
new locale_util::SwitchLanguageCallback(
base::Bind(&OnLanguageSwitchedCallback, base::Passed(data.Pass()))));
locale_util::SwitchLanguage(
locale, true, true , callback.Pass());
}
}