OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/login/webui_screen_locker.h" | 5 #include "chrome/browser/chromeos/login/lock_window_gtk.h" |
| 6 |
| 7 #include <X11/extensions/XTest.h> |
| 8 #include <X11/keysym.h> |
| 9 #include <gdk/gdkkeysyms.h> |
| 10 #include <gdk/gdkx.h> |
| 11 |
| 12 // Evil hack to undo X11 evil #define. |
| 13 #undef None |
| 14 #undef Status |
6 | 15 |
7 #include "base/command_line.h" | 16 #include "base/command_line.h" |
8 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
9 #include "base/values.h" | 18 #include "base/values.h" |
10 #include "chrome/browser/chromeos/cros/cros_library.h" | 19 #include "chrome/browser/chromeos/cros/cros_library.h" |
11 #include "chrome/browser/chromeos/cros/network_library.h" | 20 #include "chrome/browser/chromeos/cros/network_library.h" |
12 #include "chrome/browser/chromeos/legacy_window_manager/wm_ipc.h" | 21 #include "chrome/browser/chromeos/legacy_window_manager/wm_ipc.h" |
13 #include "chrome/browser/chromeos/login/helper.h" | 22 #include "chrome/browser/chromeos/login/helper.h" |
14 #include "chrome/browser/chromeos/login/screen_locker.h" | 23 #include "chrome/browser/chromeos/login/screen_locker.h" |
15 #include "chrome/browser/chromeos/login/user_manager.h" | 24 #include "chrome/browser/chromeos/login/user_manager.h" |
16 #include "chrome/browser/chromeos/login/webui_login_display.h" | 25 #include "chrome/browser/chromeos/login/webui_login_display.h" |
17 #include "chrome/browser/ui/views/dom_view.h" | 26 #include "chrome/browser/ui/views/dom_view.h" |
18 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" | 27 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" |
19 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
20 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
21 #include "content/browser/renderer_host/render_widget_host_view.h" | 30 #include "content/browser/renderer_host/render_widget_host_view.h" |
22 #include "content/public/browser/notification_service.h" | 31 #include "content/public/browser/notification_service.h" |
23 #include "content/public/browser/notification_types.h" | 32 #include "content/public/browser/notification_types.h" |
24 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
25 #include "ui/base/x/x11_util.h" | 34 #include "ui/base/x/x11_util.h" |
26 #include "ui/gfx/screen.h" | 35 #include "ui/gfx/screen.h" |
27 #include "ui/views/widget/native_widget_gtk.h" | 36 #include "ui/views/widget/native_widget_gtk.h" |
28 | 37 #include "ui/views/widget/widget.h" |
29 // These conflict with some of the Chrome headers, so must be included last. | |
30 #include <X11/extensions/XTest.h> | |
31 #include <X11/keysym.h> | |
32 #include <gdk/gdkkeysyms.h> | |
33 #include <gdk/gdkx.h> | |
34 | 38 |
35 namespace { | 39 namespace { |
36 | 40 |
37 // URL which corresponds to the login WebUI. | |
38 const char kLoginURL[] = "chrome://oobe/login"; | |
39 | |
40 // The maximum duration for which locker should try to grab the keyboard and | 41 // The maximum duration for which locker should try to grab the keyboard and |
41 // mouse and its interval for regrabbing on failure. | 42 // mouse and its interval for regrabbing on failure. |
42 const int kMaxGrabFailureSec = 30; | 43 const int kMaxGrabFailureSec = 30; |
43 const int64 kRetryGrabIntervalMs = 500; | 44 const int64 kRetryGrabIntervalMs = 500; |
44 | 45 |
45 // Maximum number of times we'll try to grab the keyboard and mouse before | 46 // Maximum number of times we'll try to grab the keyboard and mouse before |
46 // giving up. If we hit the limit, Chrome exits and the session is terminated. | 47 // giving up. If we hit the limit, Chrome exits and the session is terminated. |
47 const int kMaxGrabFailures = kMaxGrabFailureSec * 1000 / kRetryGrabIntervalMs; | 48 const int kMaxGrabFailures = kMaxGrabFailureSec * 1000 / kRetryGrabIntervalMs; |
48 | 49 |
49 // A ScreenLock window that covers entire screen to keep the keyboard | |
50 // focus/events inside the grab widget. | |
51 class LockWindow : public views::NativeWidgetGtk { | |
52 public: | |
53 explicit LockWindow(chromeos::WebUIScreenLocker* webui_screen_locker) | |
54 : views::NativeWidgetGtk(new views::Widget), | |
55 toplevel_focus_widget_(NULL), | |
56 webui_screen_locker_(webui_screen_locker) { | |
57 EnableDoubleBuffer(true); | |
58 } | |
59 | |
60 virtual gboolean OnButtonPress(GtkWidget* widget, | |
61 GdkEventButton* event) OVERRIDE { | |
62 // Never propagate mouse events to parent. | |
63 return true; | |
64 } | |
65 | |
66 virtual void OnDestroy(GtkWidget* object) OVERRIDE { | |
67 VLOG(1) << "OnDestroy: LockWindow destroyed"; | |
68 views::NativeWidgetGtk::OnDestroy(object); | |
69 } | |
70 | |
71 virtual void ClearNativeFocus() OVERRIDE { | |
72 DCHECK(toplevel_focus_widget_); | |
73 gtk_widget_grab_focus(toplevel_focus_widget_); | |
74 } | |
75 | |
76 virtual void HandleGtkGrabBroke() OVERRIDE { | |
77 webui_screen_locker_->HandleGtkGrabBroke(); | |
78 } | |
79 | |
80 // Sets the widget to move the focus to when clearning the native | |
81 // widget's focus. | |
82 void set_toplevel_focus_widget(GtkWidget* widget) { | |
83 gtk_widget_set_can_focus(widget, TRUE); | |
84 toplevel_focus_widget_ = widget; | |
85 } | |
86 | |
87 private: | |
88 // The widget we set focus to when clearning the focus on native | |
89 // widget. Gdk input is grabbed in WebUIScreenLocker, and resetting the focus | |
90 // by using gtk_window_set_focus seems to confuse gtk and doesn't let focus | |
91 // move to native widget under this. | |
92 GtkWidget* toplevel_focus_widget_; | |
93 | |
94 // The WebUI screen locker. | |
95 chromeos::WebUIScreenLocker* webui_screen_locker_; | |
96 | |
97 DISALLOW_COPY_AND_ASSIGN(LockWindow); | |
98 }; | |
99 | |
100 // Define separate methods for each error code so that stack trace | 50 // Define separate methods for each error code so that stack trace |
101 // will tell which error the grab failed with. | 51 // will tell which error the grab failed with. |
102 void FailedWithGrabAlreadyGrabbed() { | 52 void FailedWithGrabAlreadyGrabbed() { |
103 LOG(FATAL) << "Grab already grabbed"; | 53 LOG(FATAL) << "Grab already grabbed"; |
104 } | 54 } |
105 void FailedWithGrabInvalidTime() { | 55 void FailedWithGrabInvalidTime() { |
106 LOG(FATAL) << "Grab invalid time"; | 56 LOG(FATAL) << "Grab invalid time"; |
107 } | 57 } |
108 void FailedWithGrabNotViewable() { | 58 void FailedWithGrabNotViewable() { |
109 LOG(FATAL) << "Grab not viewable"; | 59 LOG(FATAL) << "Grab not viewable"; |
110 } | 60 } |
111 void FailedWithGrabFrozen() { | 61 void FailedWithGrabFrozen() { |
112 LOG(FATAL) << "Grab frozen"; | 62 LOG(FATAL) << "Grab frozen"; |
113 } | 63 } |
114 void FailedWithUnknownError() { | 64 void FailedWithUnknownError() { |
115 LOG(FATAL) << "Grab uknown"; | 65 LOG(FATAL) << "Grab uknown"; |
116 } | 66 } |
117 | 67 |
118 } // namespace | 68 } // namespace |
119 | 69 |
120 namespace chromeos { | 70 namespace chromeos { |
121 | 71 |
| 72 LockWindow* LockWindow::Create() { |
| 73 return new LockWindowGtk(); |
| 74 } |
| 75 |
122 //////////////////////////////////////////////////////////////////////////////// | 76 //////////////////////////////////////////////////////////////////////////////// |
123 // WebUIScreenLocker implementation. | 77 // LockWindowGtk implementation. |
124 | 78 |
125 WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker) | 79 void LockWindowGtk::Grab(DOMView* dom_view) { |
126 : ScreenLockerDelegate(screen_locker), | 80 // Grab on the RenderWidgetHostView hosting the WebUI login screen. |
| 81 grab_widget_ = dom_view->dom_contents()->tab_contents()-> |
| 82 GetRenderWidgetHostView()->GetNativeView(); |
| 83 ClearGtkGrab(); |
| 84 |
| 85 // Call this after lock_window_->Show(); otherwise the 1st invocation |
| 86 // of gdk_xxx_grab() will always fail. |
| 87 TryGrabAllInputs(); |
| 88 |
| 89 // Add the window to its own group so that its grab won't be stolen if |
| 90 // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. |
| 91 // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this |
| 92 // after calling ClearGtkGrab(), as want to be in the default window group |
| 93 // then so we can break any existing GTK grabs. |
| 94 GtkWindowGroup* window_group = gtk_window_group_new(); |
| 95 gtk_window_group_add_window(window_group, |
| 96 GTK_WINDOW(lock_window_->GetNativeView())); |
| 97 g_object_unref(window_group); |
| 98 } |
| 99 |
| 100 views::Widget* LockWindowGtk::GetWidget() { |
| 101 return views::NativeWidgetGtk::GetWidget(); |
| 102 } |
| 103 |
| 104 gboolean LockWindowGtk::OnButtonPress(GtkWidget* widget, |
| 105 GdkEventButton* event) { |
| 106 // Never propagate mouse events to parent. |
| 107 return true; |
| 108 } |
| 109 |
| 110 void LockWindowGtk::OnDestroy(GtkWidget* object) { |
| 111 VLOG(1) << "OnDestroy: LockWindow destroyed"; |
| 112 views::NativeWidgetGtk::OnDestroy(object); |
| 113 } |
| 114 |
| 115 void LockWindowGtk::ClearNativeFocus() { |
| 116 gtk_widget_grab_focus(window_contents()); |
| 117 } |
| 118 |
| 119 //////////////////////////////////////////////////////////////////////////////// |
| 120 // LockWindowGtk private: |
| 121 |
| 122 LockWindowGtk::LockWindowGtk() |
| 123 : views::NativeWidgetGtk(new views::Widget), |
| 124 lock_window_(NULL), |
| 125 grab_widget_(NULL), |
127 drawn_(false), | 126 drawn_(false), |
128 input_grabbed_(false), | 127 input_grabbed_(false), |
129 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 128 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
130 grab_failure_count_(0), | 129 grab_failure_count_(0), |
131 kbd_grab_status_(GDK_GRAB_INVALID_TIME), | 130 kbd_grab_status_(GDK_GRAB_INVALID_TIME), |
132 mouse_grab_status_(GDK_GRAB_INVALID_TIME) { | 131 mouse_grab_status_(GDK_GRAB_INVALID_TIME) { |
| 132 Init(); |
133 } | 133 } |
134 | 134 |
135 void WebUIScreenLocker::LockScreen(bool unlock_on_input) { | 135 LockWindowGtk::~LockWindowGtk() { |
| 136 } |
| 137 |
| 138 void LockWindowGtk::Init() { |
136 static const GdkColor kGdkBlack = {0, 0, 0, 0}; | 139 static const GdkColor kGdkBlack = {0, 0, 0, 0}; |
| 140 EnableDoubleBuffer(true); |
137 | 141 |
138 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(NULL)); | 142 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(NULL)); |
139 | 143 |
140 LockWindow* lock_window = new LockWindow(this); | 144 lock_window_ = GetWidget(); |
141 lock_window_ = lock_window->GetWidget(); | |
142 views::Widget::InitParams params( | 145 views::Widget::InitParams params( |
143 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); | 146 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
144 params.bounds = bounds; | 147 params.bounds = bounds; |
145 params.native_widget = lock_window; | 148 params.native_widget = this; |
146 lock_window_->Init(params); | 149 lock_window_->Init(params); |
147 gtk_widget_modify_bg( | 150 gtk_widget_modify_bg( |
148 lock_window_->GetNativeView(), GTK_STATE_NORMAL, &kGdkBlack); | 151 lock_window_->GetNativeView(), GTK_STATE_NORMAL, &kGdkBlack); |
149 | 152 |
150 g_signal_connect(lock_window_->GetNativeView(), "client-event", | 153 g_signal_connect(lock_window_->GetNativeView(), "client-event", |
151 G_CALLBACK(OnClientEventThunk), this); | 154 G_CALLBACK(OnClientEventThunk), this); |
152 | 155 |
153 // TODO(flackr): Obscure the screen with black / a screensaver if | |
154 // unlock_on_input. | |
155 DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); | 156 DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); |
156 WmIpc::instance()->SetWindowType( | 157 WmIpc::instance()->SetWindowType( |
157 lock_window_->GetNativeView(), | 158 lock_window_->GetNativeView(), |
158 WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, | 159 WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, |
159 NULL); | 160 NULL); |
160 | |
161 WebUILoginView::Init(lock_window_); | |
162 lock_window_->SetContentsView(this); | |
163 lock_window_->Show(); | |
164 OnWindowCreated(); | |
165 LoadURL(GURL(kLoginURL)); | |
166 // User list consisting of a single logged-in user. | |
167 UserList users(1, &chromeos::UserManager::Get()->logged_in_user()); | |
168 login_display_.reset(new WebUILoginDisplay(this)); | |
169 login_display_->set_background_bounds(bounds); | |
170 login_display_->set_parent_window( | |
171 GTK_WINDOW(lock_window_->GetNativeView())); | |
172 login_display_->Init(users, false, false); | |
173 | |
174 static_cast<OobeUI*>(GetWebUI())->ShowSigninScreen(login_display_.get()); | |
175 | |
176 registrar_.Add(this, | |
177 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, | |
178 content::NotificationService::AllSources()); | |
179 | |
180 ClearGtkGrab(); | |
181 | |
182 // Call this after lock_window_->Show(); otherwise the 1st invocation | |
183 // of gdk_xxx_grab() will always fail. | |
184 TryGrabAllInputs(); | |
185 | |
186 // Add the window to its own group so that its grab won't be stolen if | |
187 // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. | |
188 // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this | |
189 // after calling ClearGtkGrab(), as want to be in the default window group | |
190 // then so we can break any existing GTK grabs. | |
191 GtkWindowGroup* window_group = gtk_window_group_new(); | |
192 gtk_window_group_add_window(window_group, | |
193 GTK_WINDOW(lock_window_->GetNativeView())); | |
194 g_object_unref(window_group); | |
195 | |
196 lock_window->set_toplevel_focus_widget(lock_window->window_contents()); | |
197 } | 161 } |
198 | 162 |
199 void WebUIScreenLocker::OnGrabInputs() { | 163 void LockWindowGtk::OnGrabInputs() { |
200 DVLOG(1) << "OnGrabInputs"; | 164 DVLOG(1) << "OnGrabInputs"; |
201 input_grabbed_ = true; | 165 input_grabbed_ = true; |
202 if (drawn_) | 166 if (drawn_ && observer_) |
203 ScreenLockReady(); | 167 observer_->OnLockWindowReady(); |
204 } | 168 } |
205 | 169 |
206 void WebUIScreenLocker::OnWindowManagerReady() { | 170 void LockWindowGtk::OnWindowManagerReady() { |
207 DVLOG(1) << "OnClientEvent: drawn for lock"; | 171 DVLOG(1) << "OnClientEvent: drawn for lock"; |
208 drawn_ = true; | 172 drawn_ = true; |
209 if (input_grabbed_) | 173 if (input_grabbed_ && observer_) |
210 ScreenLockReady(); | 174 observer_->OnLockWindowReady(); |
211 } | 175 } |
212 | 176 |
213 void WebUIScreenLocker::ScreenLockReady() { | 177 void LockWindowGtk::ClearGtkGrab() { |
214 ScreenLockerDelegate::ScreenLockReady(); | |
215 SetInputEnabled(true); | |
216 } | |
217 | |
218 void WebUIScreenLocker::ClearGtkGrab() { | |
219 GtkWidget* current_grab_window; | 178 GtkWidget* current_grab_window; |
220 // Grab gtk input first so that the menu holding gtk grab will | 179 // Grab gtk input first so that the menu holding gtk grab will |
221 // close itself. | 180 // close itself. |
222 gtk_grab_add(webui_login_->native_view()); | 181 gtk_grab_add(grab_widget_); |
223 | 182 |
224 // Make sure there is no gtk grab widget so that gtk simply propagates | 183 // Make sure there is no gtk grab widget so that gtk simply propagates |
225 // an event. GTK maintains grab widgets in a linked-list, so we need to | 184 // an event. GTK maintains grab widgets in a linked-list, so we need to |
226 // remove until it's empty. | 185 // remove until it's empty. |
227 while ((current_grab_window = gtk_grab_get_current()) != NULL) | 186 while ((current_grab_window = gtk_grab_get_current()) != NULL) |
228 gtk_grab_remove(current_grab_window); | 187 gtk_grab_remove(current_grab_window); |
229 } | 188 } |
230 | 189 |
231 void WebUIScreenLocker::TryGrabAllInputs() { | 190 void LockWindowGtk::TryGrabAllInputs() { |
232 // Grab on the RenderWidgetHostView hosting the WebUI login screen. | |
233 GdkWindow* grab_widget = webui_login_->dom_contents()->tab_contents()-> | |
234 GetRenderWidgetHostView()->GetNativeView()->window; | |
235 // Grab x server so that we can atomically grab and take | 191 // Grab x server so that we can atomically grab and take |
236 // action when grab fails. | 192 // action when grab fails. |
237 gdk_x11_grab_server(); | 193 gdk_x11_grab_server(); |
238 gtk_grab_add(webui_login_->native_view()); | 194 gtk_grab_add(grab_widget_); |
239 if (kbd_grab_status_ != GDK_GRAB_SUCCESS) | 195 if (kbd_grab_status_ != GDK_GRAB_SUCCESS) |
240 kbd_grab_status_ = gdk_keyboard_grab(grab_widget, FALSE, GDK_CURRENT_TIME); | 196 kbd_grab_status_ = gdk_keyboard_grab(grab_widget_->window, |
| 197 FALSE, |
| 198 GDK_CURRENT_TIME); |
241 if (mouse_grab_status_ != GDK_GRAB_SUCCESS) { | 199 if (mouse_grab_status_ != GDK_GRAB_SUCCESS) { |
242 mouse_grab_status_ = | 200 mouse_grab_status_ = |
243 gdk_pointer_grab(grab_widget, | 201 gdk_pointer_grab(grab_widget_->window, |
244 FALSE, | 202 FALSE, |
245 static_cast<GdkEventMask>( | 203 static_cast<GdkEventMask>( |
246 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | | 204 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | |
247 GDK_POINTER_MOTION_MASK), | 205 GDK_POINTER_MOTION_MASK), |
248 NULL, | 206 NULL, |
249 NULL, | 207 NULL, |
250 GDK_CURRENT_TIME); | 208 GDK_CURRENT_TIME); |
251 } | 209 } |
252 if ((kbd_grab_status_ != GDK_GRAB_SUCCESS || | 210 if ((kbd_grab_status_ != GDK_GRAB_SUCCESS || |
253 mouse_grab_status_ != GDK_GRAB_SUCCESS) && | 211 mouse_grab_status_ != GDK_GRAB_SUCCESS) && |
254 grab_failure_count_++ < kMaxGrabFailures) { | 212 grab_failure_count_++ < kMaxGrabFailures) { |
255 LOG(WARNING) << "Failed to grab inputs. Trying again in " | 213 LOG(WARNING) << "Failed to grab inputs. Trying again in " |
256 << kRetryGrabIntervalMs << " ms: kbd=" | 214 << kRetryGrabIntervalMs << " ms: kbd=" |
257 << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; | 215 << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; |
258 TryUngrabOtherClients(); | 216 TryUngrabOtherClients(); |
259 gdk_x11_ungrab_server(); | 217 gdk_x11_ungrab_server(); |
260 MessageLoop::current()->PostDelayedTask( | 218 MessageLoop::current()->PostDelayedTask( |
261 FROM_HERE, | 219 FROM_HERE, |
262 base::Bind(&WebUIScreenLocker::TryGrabAllInputs, | 220 base::Bind(&LockWindowGtk::TryGrabAllInputs, |
263 weak_factory_.GetWeakPtr()), | 221 weak_factory_.GetWeakPtr()), |
264 kRetryGrabIntervalMs); | 222 kRetryGrabIntervalMs); |
265 } else { | 223 } else { |
266 gdk_x11_ungrab_server(); | 224 gdk_x11_ungrab_server(); |
267 GdkGrabStatus status = kbd_grab_status_; | 225 GdkGrabStatus status = kbd_grab_status_; |
268 if (status == GDK_GRAB_SUCCESS) { | 226 if (status == GDK_GRAB_SUCCESS) { |
269 status = mouse_grab_status_; | 227 status = mouse_grab_status_; |
270 } | 228 } |
271 switch (status) { | 229 switch (status) { |
272 case GDK_GRAB_SUCCESS: | 230 case GDK_GRAB_SUCCESS: |
(...skipping 12 matching lines...) Expand all Loading... |
285 break; | 243 break; |
286 default: | 244 default: |
287 FailedWithUnknownError(); | 245 FailedWithUnknownError(); |
288 break; | 246 break; |
289 } | 247 } |
290 DVLOG(1) << "Grab Success"; | 248 DVLOG(1) << "Grab Success"; |
291 OnGrabInputs(); | 249 OnGrabInputs(); |
292 } | 250 } |
293 } | 251 } |
294 | 252 |
295 void WebUIScreenLocker::TryUngrabOtherClients() { | 253 void LockWindowGtk::TryUngrabOtherClients() { |
296 #if !defined(NDEBUG) | 254 #if !defined(NDEBUG) |
297 { | 255 { |
298 int event_base, error_base; | 256 int event_base, error_base; |
299 int major, minor; | 257 int major, minor; |
300 // Make sure we have XTest extension. | 258 // Make sure we have XTest extension. |
301 DCHECK(XTestQueryExtension(ui::GetXDisplay(), | 259 DCHECK(XTestQueryExtension(ui::GetXDisplay(), |
302 &event_base, &error_base, | 260 &event_base, &error_base, |
303 &major, &minor)); | 261 &major, &minor)); |
304 } | 262 } |
305 #endif | 263 #endif |
306 | 264 |
307 // The following code is an attempt to grab inputs by closing | 265 // The following code is an attempt to grab inputs by closing |
308 // supposedly opened menu. This happens when a plugin has a menu | 266 // supposedly opened menu. This happens when a plugin has a menu |
309 // opened. | 267 // opened. |
310 if (mouse_grab_status_ == GDK_GRAB_ALREADY_GRABBED || | 268 if (mouse_grab_status_ == GDK_GRAB_ALREADY_GRABBED || |
311 mouse_grab_status_ == GDK_GRAB_FROZEN) { | 269 mouse_grab_status_ == GDK_GRAB_FROZEN) { |
312 // Successfully grabbed the keyboard, but pointer is still | 270 // Successfully grabbed the keyboard, but pointer is still |
313 // grabbed by other client. Another attempt to close supposedly | 271 // grabbed by other client. Another attempt to close supposedly |
314 // opened menu by emulating keypress at the left top corner. | 272 // opened menu by emulating keypress at the left top corner. |
315 Display* display = ui::GetXDisplay(); | 273 Display* display = ui::GetXDisplay(); |
316 Window root, child; | 274 Window root, child; |
317 int root_x, root_y, win_x, winy; | 275 int root_x, root_y, win_x, winy; |
318 unsigned int mask; | 276 unsigned int mask; |
319 XQueryPointer(display, | 277 XQueryPointer(display, |
320 ui::GetX11WindowFromGtkWidget( | 278 ui::GetX11WindowFromGtkWidget( |
321 static_cast<LockWindow*>(lock_window_->native_widget())-> | |
322 window_contents()), | 279 window_contents()), |
323 &root, &child, &root_x, &root_y, | 280 &root, &child, &root_x, &root_y, |
324 &win_x, &winy, &mask); | 281 &win_x, &winy, &mask); |
325 XTestFakeMotionEvent(display, -1, -10000, -10000, CurrentTime); | 282 XTestFakeMotionEvent(display, -1, -10000, -10000, CurrentTime); |
326 XTestFakeButtonEvent(display, 1, True, CurrentTime); | 283 XTestFakeButtonEvent(display, 1, True, CurrentTime); |
327 XTestFakeButtonEvent(display, 1, False, CurrentTime); | 284 XTestFakeButtonEvent(display, 1, False, CurrentTime); |
328 // Move the pointer back. | 285 // Move the pointer back. |
329 XTestFakeMotionEvent(display, -1, root_x, root_y, CurrentTime); | 286 XTestFakeMotionEvent(display, -1, root_x, root_y, CurrentTime); |
330 XFlush(display); | 287 XFlush(display); |
331 } else if (kbd_grab_status_ == GDK_GRAB_ALREADY_GRABBED || | 288 } else if (kbd_grab_status_ == GDK_GRAB_ALREADY_GRABBED || |
332 kbd_grab_status_ == GDK_GRAB_FROZEN) { | 289 kbd_grab_status_ == GDK_GRAB_FROZEN) { |
333 // Successfully grabbed the pointer, but keyboard is still grabbed | 290 // Successfully grabbed the pointer, but keyboard is still grabbed |
334 // by other client. Another attempt to close supposedly opened | 291 // by other client. Another attempt to close supposedly opened |
335 // menu by emulating escape key. Such situation must be very | 292 // menu by emulating escape key. Such situation must be very |
336 // rare, but handling this just in case | 293 // rare, but handling this just in case |
337 Display* display = ui::GetXDisplay(); | 294 Display* display = ui::GetXDisplay(); |
338 KeyCode escape = XKeysymToKeycode(display, XK_Escape); | 295 KeyCode escape = XKeysymToKeycode(display, XK_Escape); |
339 XTestFakeKeyEvent(display, escape, True, CurrentTime); | 296 XTestFakeKeyEvent(display, escape, True, CurrentTime); |
340 XTestFakeKeyEvent(display, escape, False, CurrentTime); | 297 XTestFakeKeyEvent(display, escape, False, CurrentTime); |
341 XFlush(display); | 298 XFlush(display); |
342 } | 299 } |
343 } | 300 } |
344 | 301 |
345 void WebUIScreenLocker::HandleGtkGrabBroke() { | 302 void LockWindowGtk::HandleGtkGrabBroke() { |
346 // Input should never be stolen from ScreenLocker once it's | 303 // Input should never be stolen from ScreenLocker once it's |
347 // grabbed. If this happens, it's a bug and has to be fixed. We | 304 // grabbed. If this happens, it's a bug and has to be fixed. We |
348 // let chrome crash to get a crash report and dump, and | 305 // let chrome crash to get a crash report and dump, and |
349 // SessionManager will terminate the session to logout. | 306 // SessionManager will terminate the session to logout. |
350 CHECK_NE(GDK_GRAB_SUCCESS, kbd_grab_status_); | 307 CHECK_NE(GDK_GRAB_SUCCESS, kbd_grab_status_); |
351 CHECK_NE(GDK_GRAB_SUCCESS, mouse_grab_status_); | 308 CHECK_NE(GDK_GRAB_SUCCESS, mouse_grab_status_); |
352 } | 309 } |
353 | 310 |
354 void WebUIScreenLocker::OnAuthenticate() { | 311 void LockWindowGtk::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { |
355 } | |
356 | |
357 void WebUIScreenLocker::SetInputEnabled(bool enabled) { | |
358 login_display_->SetUIEnabled(enabled); | |
359 SetStatusAreaEnabled(enabled); | |
360 } | |
361 | |
362 void WebUIScreenLocker::SetSignoutEnabled(bool enabled) { | |
363 // TODO(flackr): Implement (crbug.com/105267). | |
364 NOTIMPLEMENTED(); | |
365 } | |
366 | |
367 void WebUIScreenLocker::ShowErrorMessage(const string16& message, | |
368 bool sign_out_only) { | |
369 // TODO(flackr): Use login_display_ to show error message (requires either | |
370 // adding a method to display error strings or strictly passing error ids: | |
371 // crbug.com/105267). | |
372 base::FundamentalValue login_attempts_value(0); | |
373 base::StringValue error_message(message); | |
374 base::StringValue help_link(""); | |
375 base::FundamentalValue help_id(0); | |
376 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.showSignInError", | |
377 login_attempts_value, | |
378 error_message, | |
379 help_link, | |
380 help_id); | |
381 } | |
382 | |
383 void WebUIScreenLocker::ShowCaptchaAndErrorMessage(const GURL& captcha_url, | |
384 const string16& message) { | |
385 ShowErrorMessage(message, true); | |
386 } | |
387 | |
388 void WebUIScreenLocker::ClearErrors() { | |
389 GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.clearErrors"); | |
390 } | |
391 | |
392 WebUIScreenLocker::~WebUIScreenLocker() { | |
393 DCHECK(lock_window_); | |
394 lock_window_->Close(); | |
395 } | |
396 | |
397 void WebUIScreenLocker::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { | |
398 WmIpc::Message msg; | 312 WmIpc::Message msg; |
399 WmIpc::instance()->DecodeMessage(*event, &msg); | 313 WmIpc::instance()->DecodeMessage(*event, &msg); |
400 if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK) | 314 if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK) |
401 OnWindowManagerReady(); | 315 OnWindowManagerReady(); |
402 } | 316 } |
403 | 317 |
404 //////////////////////////////////////////////////////////////////////////////// | |
405 // WebUIScreenLocker, content::NotificationObserver implementation: | |
406 | |
407 void WebUIScreenLocker::Observe( | |
408 int type, | |
409 const content::NotificationSource& source, | |
410 const content::NotificationDetails& details) { | |
411 if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) | |
412 return; | |
413 | |
414 const User& user = *content::Details<User>(details).ptr(); | |
415 login_display_->OnUserImageChanged(user); | |
416 } | |
417 | |
418 //////////////////////////////////////////////////////////////////////////////// | |
419 // WebUIScreenLocker, LoginDisplay::Delegate implementation: | |
420 | |
421 void WebUIScreenLocker::CreateAccount() { | |
422 NOTREACHED(); | |
423 } | |
424 | |
425 string16 WebUIScreenLocker::GetConnectedNetworkName() { | |
426 return GetCurrentNetworkName(CrosLibrary::Get()->GetNetworkLibrary()); | |
427 } | |
428 | |
429 void WebUIScreenLocker::FixCaptivePortal() { | |
430 NOTREACHED(); | |
431 } | |
432 | |
433 void WebUIScreenLocker::CompleteLogin(const std::string& username, | |
434 const std::string& password) { | |
435 NOTREACHED(); | |
436 } | |
437 | |
438 void WebUIScreenLocker::Login(const std::string& username, | |
439 const std::string& password) { | |
440 DCHECK(username == chromeos::UserManager::Get()->logged_in_user().email()); | |
441 | |
442 chromeos::ScreenLocker::default_screen_locker()->Authenticate( | |
443 ASCIIToUTF16(password)); | |
444 } | |
445 | |
446 void WebUIScreenLocker::LoginAsGuest() { | |
447 NOTREACHED(); | |
448 } | |
449 | |
450 void WebUIScreenLocker::OnUserSelected(const std::string& username) { | |
451 } | |
452 | |
453 void WebUIScreenLocker::OnStartEnterpriseEnrollment() { | |
454 NOTREACHED(); | |
455 } | |
456 | |
457 } // namespace chromeos | 318 } // namespace chromeos |
OLD | NEW |