Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / lock / webui_screen_locker.cc
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.
4
5 #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h"
6
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/browser_shutdown.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
14 #include "chrome/browser/chromeos/login/helper.h"
15 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
16 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
17 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
18 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
19 #include "chrome/common/url_constants.h"
20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "components/user_manager/user.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/browser/web_ui.h"
27 #include "ui/aura/client/capture_client.h"
28 #include "ui/aura/window_event_dispatcher.h"
29 #include "ui/base/x/x11_util.h"
30 #include "ui/gfx/screen.h"
31 #include "ui/keyboard/keyboard_controller.h"
32 #include "ui/keyboard/keyboard_util.h"
33 #include "ui/views/controls/webview/webview.h"
34
35 #if !defined(USE_ATHENA)
36 #include "ash/wm/lock_state_controller.h"
37 #include "ash/wm/lock_state_observer.h"
38 #endif
39
40 namespace {
41
42 // URL which corresponds to the login WebUI.
43 const char kLoginURL[] = "chrome://oobe/lock";
44
45 // Disables virtual keyboard overscroll. Login UI will scroll user pods
46 // into view on JS side when virtual keyboard is shown.
47 void DisableKeyboardOverscroll() {
48   keyboard::SetKeyboardOverscrollOverride(
49       keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED);
50 }
51
52 void ResetKeyboardOverscrollOverride() {
53   keyboard::SetKeyboardOverscrollOverride(
54       keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE);
55 }
56
57 }  // namespace
58
59 namespace chromeos {
60
61 ////////////////////////////////////////////////////////////////////////////////
62 // WebUIScreenLocker implementation.
63
64 WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker)
65     : ScreenLockerDelegate(screen_locker),
66       lock_ready_(false),
67       webui_ready_(false),
68       network_state_helper_(new login::NetworkStateHelper),
69       is_observing_keyboard_(false),
70       weak_factory_(this) {
71   set_should_emit_login_prompt_visible(false);
72 #if !defined(USE_ATHENA)
73   ash::Shell::GetInstance()->lock_state_controller()->AddObserver(this);
74   ash::Shell::GetInstance()->delegate()->AddVirtualKeyboardStateObserver(this);
75 #endif
76   DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
77
78   if (keyboard::KeyboardController::GetInstance()) {
79     keyboard::KeyboardController::GetInstance()->AddObserver(this);
80     is_observing_keyboard_ = true;
81   }
82 }
83
84 void WebUIScreenLocker::LockScreen() {
85   gfx::Rect bounds =
86       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().bounds();
87
88   lock_time_ = base::TimeTicks::Now();
89   LockWindow* lock_window = LockWindow::Create();
90   lock_window->set_observer(this);
91   lock_window->set_initially_focused_view(this);
92   lock_window_ = lock_window->GetWidget();
93   lock_window_->AddObserver(this);
94   WebUILoginView::Init();
95   lock_window_->SetContentsView(this);
96   lock_window_->SetBounds(bounds);
97   lock_window_->Show();
98   LoadURL(GURL(kLoginURL));
99   lock_window->Grab();
100
101   login_display_.reset(new WebUILoginDisplay(this));
102   login_display_->set_background_bounds(bounds);
103   login_display_->set_parent_window(GetNativeWindow());
104   login_display_->Init(screen_locker()->users(), false, true, false);
105
106   GetOobeUI()->ShowSigninScreen(
107       LoginScreenContext(), login_display_.get(), login_display_.get());
108
109   registrar_.Add(this,
110                  chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
111                  content::NotificationService::AllSources());
112
113   if (login::LoginScrollIntoViewEnabled())
114     DisableKeyboardOverscroll();
115 }
116
117 void WebUIScreenLocker::ScreenLockReady() {
118   UMA_HISTOGRAM_TIMES("LockScreen.LockReady",
119                       base::TimeTicks::Now() - lock_time_);
120   ScreenLockerDelegate::ScreenLockReady();
121   SetInputEnabled(true);
122 }
123
124 void WebUIScreenLocker::OnAuthenticate() {
125 }
126
127 void WebUIScreenLocker::SetInputEnabled(bool enabled) {
128   login_display_->SetUIEnabled(enabled);
129 }
130
131 void WebUIScreenLocker::ShowErrorMessage(
132     int error_msg_id,
133     HelpAppLauncher::HelpTopic help_topic_id) {
134   login_display_->ShowError(error_msg_id,
135                   0 /* login_attempts */,
136                   help_topic_id);
137 }
138
139 void WebUIScreenLocker::AnimateAuthenticationSuccess() {
140   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateAuthenticationSuccess");
141 }
142
143 void WebUIScreenLocker::ClearErrors() {
144   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.clearErrors");
145 }
146
147 gfx::NativeWindow WebUIScreenLocker::GetNativeWindow() const {
148   return lock_window_->GetNativeWindow();
149 }
150
151 content::WebUI* WebUIScreenLocker::GetAssociatedWebUI() {
152   return GetWebUI();
153 }
154
155 void WebUIScreenLocker::FocusUserPod() {
156   if (!webui_ready_)
157     return;
158   webui_login_->RequestFocus();
159   GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.forceLockedUserPodFocus");
160 }
161
162 WebUIScreenLocker::~WebUIScreenLocker() {
163   DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
164 #if !defined(USE_ATHENA)
165   ash::Shell::GetInstance()->
166       lock_state_controller()->RemoveObserver(this);
167
168   ash::Shell::GetInstance()->delegate()->
169       RemoveVirtualKeyboardStateObserver(this);
170 #endif
171   // In case of shutdown, lock_window_ may be deleted before WebUIScreenLocker.
172   if (lock_window_) {
173     lock_window_->RemoveObserver(this);
174     lock_window_->Close();
175   }
176   // If LockScreen() was called, we need to clear the signin screen handler
177   // delegate set in ShowSigninScreen so that it no longer points to us.
178   if (login_display_.get()) {
179     static_cast<OobeUI*>(GetWebUI()->GetController())->
180         ResetSigninScreenHandlerDelegate();
181   }
182
183   if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) {
184     keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
185     is_observing_keyboard_ = false;
186   }
187
188   if (login::LoginScrollIntoViewEnabled())
189     ResetKeyboardOverscrollOverride();
190 }
191
192 void WebUIScreenLocker::OnLockWebUIReady() {
193   VLOG(1) << "WebUI ready; lock window is "
194           << (lock_ready_ ? "too" : "not");
195   webui_ready_ = true;
196   if (lock_ready_)
197     ScreenLockReady();
198 }
199
200 void WebUIScreenLocker::OnLockBackgroundDisplayed() {
201   UMA_HISTOGRAM_TIMES("LockScreen.BackgroundReady",
202                       base::TimeTicks::Now() - lock_time_);
203 }
204
205 OobeUI* WebUIScreenLocker::GetOobeUI() {
206   return static_cast<OobeUI*>(GetWebUI()->GetController());
207 }
208
209 ////////////////////////////////////////////////////////////////////////////////
210 // WebUIScreenLocker, content::NotificationObserver implementation:
211
212 void WebUIScreenLocker::Observe(
213     int type,
214     const content::NotificationSource& source,
215     const content::NotificationDetails& details) {
216   switch (type) {
217     case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
218       const user_manager::User& user =
219           *content::Details<user_manager::User>(details).ptr();
220       login_display_->OnUserImageChanged(user);
221       break;
222     }
223     default:
224       WebUILoginView::Observe(type, source, details);
225   }
226 }
227
228 ////////////////////////////////////////////////////////////////////////////////
229 // WebUIScreenLocker, LoginDisplay::Delegate implementation:
230
231 void WebUIScreenLocker::CancelPasswordChangedFlow()  {
232   NOTREACHED();
233 }
234
235 void WebUIScreenLocker::CreateAccount() {
236   NOTREACHED();
237 }
238
239 void WebUIScreenLocker::CompleteLogin(const UserContext& user_context) {
240   NOTREACHED();
241 }
242
243 base::string16 WebUIScreenLocker::GetConnectedNetworkName() {
244   return network_state_helper_->GetCurrentNetworkName();
245 }
246
247 bool WebUIScreenLocker::IsSigninInProgress() const {
248   // The way how screen locker is implemented right now there's no
249   // GAIA sign in in progress in any case.
250   return false;
251 }
252
253 void WebUIScreenLocker::Login(const UserContext& user_context,
254                               const SigninSpecifics& specifics) {
255   chromeos::ScreenLocker::default_screen_locker()->Authenticate(user_context);
256 }
257
258 void WebUIScreenLocker::MigrateUserData(const std::string& old_password) {
259   NOTREACHED();
260 }
261
262 void WebUIScreenLocker::OnSigninScreenReady() {
263 }
264
265 void WebUIScreenLocker::OnStartEnterpriseEnrollment() {
266   NOTREACHED();
267 }
268
269 void WebUIScreenLocker::OnStartKioskEnableScreen() {
270   NOTREACHED();
271 }
272
273 void WebUIScreenLocker::OnStartKioskAutolaunchScreen() {
274   NOTREACHED();
275 }
276
277 void WebUIScreenLocker::ShowWrongHWIDScreen() {
278   NOTREACHED();
279 }
280
281 void WebUIScreenLocker::ResetPublicSessionAutoLoginTimer() {
282 }
283
284 void WebUIScreenLocker::ResyncUserData() {
285   NOTREACHED();
286 }
287
288 void WebUIScreenLocker::SetDisplayEmail(const std::string& email) {
289   NOTREACHED();
290 }
291
292 void WebUIScreenLocker::Signout() {
293   chromeos::ScreenLocker::default_screen_locker()->Signout();
294 }
295
296 ////////////////////////////////////////////////////////////////////////////////
297 // LockWindow::Observer implementation:
298
299 void WebUIScreenLocker::OnLockWindowReady() {
300   VLOG(1) << "Lock window ready; WebUI is " << (webui_ready_ ? "too" : "not");
301   lock_ready_ = true;
302   if (webui_ready_)
303     ScreenLockReady();
304 }
305
306 ////////////////////////////////////////////////////////////////////////////////
307 // SessionLockStateObserver override.
308
309 #if !defined(USE_ATHENA)
310 void WebUIScreenLocker::OnLockStateEvent(
311     ash::LockStateObserver::EventType event) {
312   if (event == ash::LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED) {
313     // Release capture if any.
314     aura::client::GetCaptureClient(GetNativeWindow()->GetRootWindow())->
315         SetCapture(NULL);
316     GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateOnceFullyDisplayed");
317   }
318 }
319 #endif
320
321 ////////////////////////////////////////////////////////////////////////////////
322 // WidgetObserver override.
323
324 void WebUIScreenLocker::OnWidgetDestroying(views::Widget* widget) {
325   lock_window_->RemoveObserver(this);
326   lock_window_ = NULL;
327 }
328
329 ////////////////////////////////////////////////////////////////////////////////
330 // PowerManagerClient::Observer overrides.
331
332 void WebUIScreenLocker::LidEventReceived(bool open,
333                                          const base::TimeTicks& time) {
334   content::BrowserThread::PostTask(
335       content::BrowserThread::UI,
336       FROM_HERE,
337       base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
338 }
339
340 void WebUIScreenLocker::SuspendDone(const base::TimeDelta& sleep_duration) {
341   content::BrowserThread::PostTask(
342       content::BrowserThread::UI,
343       FROM_HERE,
344       base::Bind(&WebUIScreenLocker::FocusUserPod, weak_factory_.GetWeakPtr()));
345 }
346
347 void WebUIScreenLocker::RenderProcessGone(base::TerminationStatus status) {
348   if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID &&
349       status != base::TERMINATION_STATUS_NORMAL_TERMINATION) {
350     LOG(ERROR) << "Renderer crash on lock screen";
351     Signout();
352   }
353 }
354
355 ////////////////////////////////////////////////////////////////////////////////
356 // ash::KeyboardStateObserver overrides.
357
358 #if !defined(USE_ATHENA)
359 void WebUIScreenLocker::OnVirtualKeyboardStateChanged(bool activated) {
360   if (keyboard::KeyboardController::GetInstance()) {
361     if (activated) {
362       if (!is_observing_keyboard_) {
363         keyboard::KeyboardController::GetInstance()->AddObserver(this);
364         is_observing_keyboard_ = true;
365       }
366     } else {
367       keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
368       is_observing_keyboard_ = false;
369     }
370   }
371 }
372 #endif
373
374 ////////////////////////////////////////////////////////////////////////////////
375 // keyboard::KeyboardControllerObserver overrides.
376
377 void WebUIScreenLocker::OnKeyboardBoundsChanging(
378     const gfx::Rect& new_bounds) {
379   if (new_bounds.IsEmpty() && !keyboard_bounds_.IsEmpty()) {
380     // Keyboard has been hidden.
381     if (GetOobeUI()) {
382       GetOobeUI()->GetCoreOobeActor()->ShowControlBar(true);
383       if (login::LoginScrollIntoViewEnabled())
384         GetOobeUI()->GetCoreOobeActor()->SetKeyboardState(false, new_bounds);
385     }
386   } else if (!new_bounds.IsEmpty() && keyboard_bounds_.IsEmpty()) {
387     // Keyboard has been shown.
388     if (GetOobeUI()) {
389       GetOobeUI()->GetCoreOobeActor()->ShowControlBar(false);
390       if (login::LoginScrollIntoViewEnabled())
391         GetOobeUI()->GetCoreOobeActor()->SetKeyboardState(true, new_bounds);
392     }
393   }
394
395   keyboard_bounds_ = new_bounds;
396 }
397
398 }  // namespace chromeos