1 // Copyright 2014 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.
5 #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h"
8 #include "ash/wm/lock_state_controller.h"
9 #include "ash/wm/lock_state_observer.h"
10 #include "base/command_line.h"
11 #include "base/metrics/histogram.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_shutdown.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
17 #include "chrome/browser/chromeos/login/helper.h"
18 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
19 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
20 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
21 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
22 #include "chrome/common/url_constants.h"
23 #include "chromeos/dbus/dbus_thread_manager.h"
24 #include "components/user_manager/user.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_types.h"
28 #include "content/public/browser/render_widget_host_view.h"
29 #include "content/public/browser/web_ui.h"
30 #include "ui/aura/client/capture_client.h"
31 #include "ui/aura/window_event_dispatcher.h"
32 #include "ui/base/x/x11_util.h"
33 #include "ui/gfx/screen.h"
34 #include "ui/keyboard/keyboard_controller.h"
35 #include "ui/keyboard/keyboard_util.h"
36 #include "ui/views/controls/webview/webview.h"
40 // URL which corresponds to the login WebUI.
41 const char kLoginURL[] = "chrome://oobe/lock";
43 // Disables virtual keyboard overscroll. Login UI will scroll user pods
44 // into view on JS side when virtual keyboard is shown.
45 void DisableKeyboardOverscroll() {
46 keyboard::SetKeyboardOverscrollOverride(
47 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED);
50 void ResetKeyboardOverscrollOverride() {
51 keyboard::SetKeyboardOverscrollOverride(
52 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE);
59 ////////////////////////////////////////////////////////////////////////////////
60 // WebUIScreenLocker implementation.
62 WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker)
63 : ScreenLockerDelegate(screen_locker),
66 network_state_helper_(new login::NetworkStateHelper),
67 is_observing_keyboard_(false),
69 set_should_emit_login_prompt_visible(false);
70 ash::Shell::GetInstance()->lock_state_controller()->AddObserver(this);
71 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
73 if (keyboard::KeyboardController::GetInstance()) {
74 keyboard::KeyboardController::GetInstance()->AddObserver(this);
75 is_observing_keyboard_ = true;
78 ash::Shell::GetInstance()->delegate()->AddVirtualKeyboardStateObserver(this);
81 void WebUIScreenLocker::LockScreen() {
82 gfx::Rect bounds(ash::Shell::GetScreen()->GetPrimaryDisplay().bounds());
84 lock_time_ = base::TimeTicks::Now();
85 LockWindow* lock_window = LockWindow::Create();
86 lock_window->set_observer(this);
87 lock_window->set_initially_focused_view(this);
88 lock_window_ = lock_window->GetWidget();
89 lock_window_->AddObserver(this);
90 WebUILoginView::Init();
91 lock_window_->SetContentsView(this);
93 LoadURL(GURL(kLoginURL));
96 login_display_.reset(new WebUILoginDisplay(this));
97 login_display_->set_background_bounds(bounds);
98 login_display_->set_parent_window(GetNativeWindow());
99 login_display_->Init(screen_locker()->users(), false, true, false);
101 GetOobeUI()->ShowSigninScreen(
102 LoginScreenContext(), login_display_.get(), login_display_.get());
105 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
106 content::NotificationService::AllSources());
108 if (login::LoginScrollIntoViewEnabled())
109 DisableKeyboardOverscroll();
112 void WebUIScreenLocker::ScreenLockReady() {
113 UMA_HISTOGRAM_TIMES("LockScreen.LockReady",
114 base::TimeTicks::Now() - lock_time_);
115 ScreenLockerDelegate::ScreenLockReady();
116 SetInputEnabled(true);
119 void WebUIScreenLocker::OnAuthenticate() {
122 void WebUIScreenLocker::SetInputEnabled(bool enabled) {
123 login_display_->SetUIEnabled(enabled);
126 void WebUIScreenLocker::ShowErrorMessage(
128 HelpAppLauncher::HelpTopic help_topic_id) {
129 login_display_->ShowError(error_msg_id,
130 0 /* login_attempts */,
134 void WebUIScreenLocker::AnimateAuthenticationSuccess() {
135 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateAuthenticationSuccess");
138 void WebUIScreenLocker::ClearErrors() {
139 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.clearErrors");
142 gfx::NativeWindow WebUIScreenLocker::GetNativeWindow() const {
143 return lock_window_->GetNativeWindow();
146 content::WebUI* WebUIScreenLocker::GetAssociatedWebUI() {
150 void WebUIScreenLocker::FocusUserPod() {
153 webui_login_->RequestFocus();
154 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.forceLockedUserPodFocus");
157 WebUIScreenLocker::~WebUIScreenLocker() {
158 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
159 ash::Shell::GetInstance()->
160 lock_state_controller()->RemoveObserver(this);
161 // In case of shutdown, lock_window_ may be deleted before WebUIScreenLocker.
163 lock_window_->RemoveObserver(this);
164 lock_window_->Close();
166 // If LockScreen() was called, we need to clear the signin screen handler
167 // delegate set in ShowSigninScreen so that it no longer points to us.
168 if (login_display_.get()) {
169 static_cast<OobeUI*>(GetWebUI()->GetController())->
170 ResetSigninScreenHandlerDelegate();
173 if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) {
174 keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
175 is_observing_keyboard_ = false;
178 ash::Shell::GetInstance()->delegate()->
179 RemoveVirtualKeyboardStateObserver(this);
181 if (login::LoginScrollIntoViewEnabled())
182 ResetKeyboardOverscrollOverride();
185 void WebUIScreenLocker::OnLockWebUIReady() {
186 VLOG(1) << "WebUI ready; lock window is "
187 << (lock_ready_ ? "too" : "not");
193 void WebUIScreenLocker::OnLockBackgroundDisplayed() {
194 UMA_HISTOGRAM_TIMES("LockScreen.BackgroundReady",
195 base::TimeTicks::Now() - lock_time_);
198 OobeUI* WebUIScreenLocker::GetOobeUI() {
199 return static_cast<OobeUI*>(GetWebUI()->GetController());
202 ////////////////////////////////////////////////////////////////////////////////
203 // WebUIScreenLocker, content::NotificationObserver implementation:
205 void WebUIScreenLocker::Observe(
207 const content::NotificationSource& source,
208 const content::NotificationDetails& details) {
210 case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
211 const user_manager::User& user =
212 *content::Details<user_manager::User>(details).ptr();
213 login_display_->OnUserImageChanged(user);
217 WebUILoginView::Observe(type, source, details);
221 ////////////////////////////////////////////////////////////////////////////////
222 // WebUIScreenLocker, LoginDisplay::Delegate implementation:
224 void WebUIScreenLocker::CancelPasswordChangedFlow() {
228 void WebUIScreenLocker::CreateAccount() {
232 void WebUIScreenLocker::CompleteLogin(const UserContext& user_context) {
236 base::string16 WebUIScreenLocker::GetConnectedNetworkName() {
237 return network_state_helper_->GetCurrentNetworkName();
240 bool WebUIScreenLocker::IsSigninInProgress() const {
241 // The way how screen locker is implemented right now there's no
242 // GAIA sign in in progress in any case.
246 void WebUIScreenLocker::Login(const UserContext& user_context,
247 const SigninSpecifics& specifics) {
248 chromeos::ScreenLocker::default_screen_locker()->Authenticate(user_context);
251 void WebUIScreenLocker::MigrateUserData(const std::string& old_password) {
255 void WebUIScreenLocker::OnSigninScreenReady() {
258 void WebUIScreenLocker::OnStartEnterpriseEnrollment() {
262 void WebUIScreenLocker::OnStartKioskEnableScreen() {
266 void WebUIScreenLocker::OnStartKioskAutolaunchScreen() {
270 void WebUIScreenLocker::ShowWrongHWIDScreen() {
274 void WebUIScreenLocker::ResetPublicSessionAutoLoginTimer() {
277 void WebUIScreenLocker::ResyncUserData() {
281 void WebUIScreenLocker::SetDisplayEmail(const std::string& email) {
285 void WebUIScreenLocker::Signout() {
286 chromeos::ScreenLocker::default_screen_locker()->Signout();
289 ////////////////////////////////////////////////////////////////////////////////
290 // LockWindow::Observer implementation:
292 void WebUIScreenLocker::OnLockWindowReady() {
293 VLOG(1) << "Lock window ready; WebUI is " << (webui_ready_ ? "too" : "not");
299 ////////////////////////////////////////////////////////////////////////////////
300 // SessionLockStateObserver override.
302 void WebUIScreenLocker::OnLockStateEvent(
303 ash::LockStateObserver::EventType event) {
304 if (event == ash::LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED) {
305 // Release capture if any.
306 aura::client::GetCaptureClient(GetNativeWindow()->GetRootWindow())->
308 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateOnceFullyDisplayed");
312 ////////////////////////////////////////////////////////////////////////////////
313 // WidgetObserver override.
315 void WebUIScreenLocker::OnWidgetDestroying(views::Widget* widget) {
316 lock_window_->RemoveObserver(this);
320 ////////////////////////////////////////////////////////////////////////////////
321 // PowerManagerClient::Observer overrides.
323 void WebUIScreenLocker::LidEventReceived(bool open,
324 const base::TimeTicks& time) {
325 content::BrowserThread::PostTask(
326 content::BrowserThread::UI,
328 base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
331 void WebUIScreenLocker::SuspendDone(const base::TimeDelta& sleep_duration) {
332 content::BrowserThread::PostTask(
333 content::BrowserThread::UI,
335 base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
338 void WebUIScreenLocker::RenderProcessGone(base::TerminationStatus status) {
339 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID &&
340 status != base::TERMINATION_STATUS_NORMAL_TERMINATION) {
341 LOG(ERROR) << "Renderer crash on lock screen";
346 ////////////////////////////////////////////////////////////////////////////////
347 // ash::KeyboardStateObserver overrides.
349 void WebUIScreenLocker::OnVirtualKeyboardStateChanged(bool activated) {
350 if (keyboard::KeyboardController::GetInstance()) {
352 if (!is_observing_keyboard_) {
353 keyboard::KeyboardController::GetInstance()->AddObserver(this);
354 is_observing_keyboard_ = true;
357 keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
358 is_observing_keyboard_ = false;
363 ////////////////////////////////////////////////////////////////////////////////
364 // keyboard::KeyboardControllerObserver overrides.
366 void WebUIScreenLocker::OnKeyboardBoundsChanging(
367 const gfx::Rect& new_bounds) {
368 if (new_bounds.IsEmpty() && !keyboard_bounds_.IsEmpty()) {
369 // Keyboard has been hidden.
371 GetOobeUI()->GetCoreOobeActor()->ShowControlBar(true);
372 if (login::LoginScrollIntoViewEnabled())
373 GetOobeUI()->GetCoreOobeActor()->SetKeyboardState(false, new_bounds);
375 } else if (!new_bounds.IsEmpty() && keyboard_bounds_.IsEmpty()) {
376 // Keyboard has been shown.
378 GetOobeUI()->GetCoreOobeActor()->ShowControlBar(false);
379 if (login::LoginScrollIntoViewEnabled())
380 GetOobeUI()->GetCoreOobeActor()->SetKeyboardState(true, new_bounds);
384 keyboard_bounds_ = new_bounds;
387 } // namespace chromeos