OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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/screen_locker.h" | 5 #include "chrome/browser/chromeos/login/screen_locker.h" |
6 | 6 |
7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
9 #include "base/singleton.h" | 9 #include "base/singleton.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
11 #include "chrome/browser/chromeos/cros/screen_lock_library.h" | 11 #include "chrome/browser/chromeos/cros/screen_lock_library.h" |
12 #include "chrome/browser/chromeos/login/authenticator.h" | 12 #include "chrome/browser/chromeos/login/authenticator.h" |
13 #include "chrome/browser/chromeos/login/background_view.h" | 13 #include "chrome/browser/chromeos/login/background_view.h" |
14 #include "chrome/browser/chromeos/login/login_utils.h" | 14 #include "chrome/browser/chromeos/login/login_utils.h" |
15 #include "chrome/browser/chromeos/login/screen_lock_view.h" | 15 #include "chrome/browser/chromeos/login/screen_lock_view.h" |
16 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
17 #include "views/screen.h" | 17 #include "views/screen.h" |
18 #include "views/widget/widget_gtk.h" | 18 #include "views/widget/widget_gtk.h" |
19 | 19 |
20 namespace { | 20 namespace { |
| 21 // The maxium times that the screen locker should try to grab input, |
| 22 // and its interval. It has to be able to grab all inputs in 30 seconds, |
| 23 // otherwise chromium process fails and the session is terminated. |
| 24 const int64 kRetryGrabIntervalMs = 1000; |
| 25 const int kGrabFailureLimit = 30; |
21 | 26 |
22 // Observer to start ScreenLocker when the screen lock | 27 // Observer to start ScreenLocker when the screen lock |
23 class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer, | 28 class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer, |
24 public NotificationObserver { | 29 public NotificationObserver { |
25 public: | 30 public: |
26 ScreenLockObserver() { | 31 ScreenLockObserver() { |
27 registrar_.Add(this, NotificationType::LOGIN_USER_CHANGED, | 32 registrar_.Add(this, NotificationType::LOGIN_USER_CHANGED, |
28 NotificationService::AllSources()); | 33 NotificationService::AllSources()); |
29 } | 34 } |
30 | 35 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 67 |
63 namespace chromeos { | 68 namespace chromeos { |
64 | 69 |
65 // static | 70 // static |
66 ScreenLocker* ScreenLocker::screen_locker_ = NULL; | 71 ScreenLocker* ScreenLocker::screen_locker_ = NULL; |
67 | 72 |
68 // A child widget that grabs both keyboard and pointer input. | 73 // A child widget that grabs both keyboard and pointer input. |
69 // TODO(oshima): catch grab-broke event and quit if it ever happenes. | 74 // TODO(oshima): catch grab-broke event and quit if it ever happenes. |
70 class GrabWidget : public views::WidgetGtk { | 75 class GrabWidget : public views::WidgetGtk { |
71 public: | 76 public: |
72 GrabWidget() : views::WidgetGtk(views::WidgetGtk::TYPE_CHILD) { | 77 GrabWidget() |
| 78 : views::WidgetGtk(views::WidgetGtk::TYPE_CHILD), |
| 79 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), |
| 80 grab_failure_count_(0), |
| 81 kbd_grab_status_(GDK_GRAB_INVALID_TIME), |
| 82 mouse_grab_status_(GDK_GRAB_INVALID_TIME) { |
73 } | 83 } |
74 | 84 |
75 virtual void Show() { | 85 virtual void Show() { |
76 views::WidgetGtk::Show(); | 86 views::WidgetGtk::Show(); |
77 GtkWidget* current_grab_window = gtk_grab_get_current(); | 87 GtkWidget* current_grab_window = gtk_grab_get_current(); |
78 if (current_grab_window) | 88 if (current_grab_window) |
79 gtk_grab_remove(current_grab_window); | 89 gtk_grab_remove(current_grab_window); |
80 | 90 |
81 DoGrab(); | 91 DoGrab(); |
82 GdkGrabStatus kbd_status = | 92 |
83 gdk_keyboard_grab(window_contents()->window, FALSE, | 93 // Now steal all inputs. |
84 GDK_CURRENT_TIME); | 94 TryGrabAllInputs(); |
85 CHECK_EQ(GDK_GRAB_SUCCESS, kbd_status) << "Failed to grab keyboard input"; | 95 } |
86 GdkGrabStatus ptr_status = | 96 |
| 97 // Try to grab all inputs. It initiates another try if it fails to |
| 98 // grab and the retry count is within a limit, or fails with CHECK. |
| 99 void TryGrabAllInputs(); |
| 100 |
| 101 private: |
| 102 ScopedRunnableMethodFactory<GrabWidget> task_factory_; |
| 103 |
| 104 // The number times the widget tried to grab all focus. |
| 105 int grab_failure_count_; |
| 106 // Status of keyboard and mouse grab. |
| 107 GdkGrabStatus kbd_grab_status_; |
| 108 GdkGrabStatus mouse_grab_status_; |
| 109 |
| 110 DISALLOW_COPY_AND_ASSIGN(GrabWidget); |
| 111 }; |
| 112 |
| 113 |
| 114 void GrabWidget::TryGrabAllInputs() { |
| 115 if (kbd_grab_status_ != GDK_GRAB_SUCCESS) |
| 116 kbd_grab_status_ = gdk_keyboard_grab(window_contents()->window, FALSE, |
| 117 GDK_CURRENT_TIME); |
| 118 if (mouse_grab_status_ != GDK_GRAB_SUCCESS) { |
| 119 mouse_grab_status_ = |
87 gdk_pointer_grab(window_contents()->window, | 120 gdk_pointer_grab(window_contents()->window, |
88 FALSE, | 121 FALSE, |
89 static_cast<GdkEventMask>( | 122 static_cast<GdkEventMask>( |
90 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | | 123 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | |
91 GDK_POINTER_MOTION_MASK), | 124 GDK_POINTER_MOTION_MASK), |
92 NULL, | 125 NULL, |
93 NULL, | 126 NULL, |
94 GDK_CURRENT_TIME); | 127 GDK_CURRENT_TIME); |
95 CHECK_EQ(GDK_GRAB_SUCCESS, ptr_status) << "Failed to grab pointer input"; | |
96 } | 128 } |
97 | 129 if ((kbd_grab_status_ != GDK_GRAB_SUCCESS || |
98 private: | 130 kbd_grab_status_ != GDK_GRAB_SUCCESS) && |
99 DISALLOW_COPY_AND_ASSIGN(GrabWidget); | 131 grab_failure_count_++ < kGrabFailureLimit) { |
100 }; | 132 DLOG(WARNING) << "Failed to grab inputs. Trying again in 1 second: kbd=" |
| 133 << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; |
| 134 MessageLoop::current()->PostDelayedTask( |
| 135 FROM_HERE, |
| 136 task_factory_.NewRunnableMethod(&GrabWidget::TryGrabAllInputs), |
| 137 kRetryGrabIntervalMs); |
| 138 } else { |
| 139 CHECK_EQ(GDK_GRAB_SUCCESS, kbd_grab_status_) |
| 140 << "Failed to grab keyboard input:" << kbd_grab_status_; |
| 141 CHECK_EQ(GDK_GRAB_SUCCESS, mouse_grab_status_) |
| 142 << "Failed to grab pointer input:" << mouse_grab_status_; |
| 143 } |
| 144 } |
101 | 145 |
102 } // namespace | 146 } // namespace |
103 | 147 |
104 namespace chromeos { | 148 namespace chromeos { |
105 | 149 |
106 ScreenLocker::ScreenLocker(const UserManager::User& user) | 150 ScreenLocker::ScreenLocker(const UserManager::User& user) |
107 : lock_window_(NULL), | 151 : lock_window_(NULL), |
108 lock_widget_(NULL), | 152 lock_widget_(NULL), |
109 screen_lock_view_(NULL), | 153 screen_lock_view_(NULL), |
110 user_(user) { | 154 user_(user) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 } | 219 } |
176 | 220 |
177 void ScreenLocker::EnableInput() { | 221 void ScreenLocker::EnableInput() { |
178 screen_lock_view_->SetEnabled(true); | 222 screen_lock_view_->SetEnabled(true); |
179 screen_lock_view_->ClearAndSetFocusToPassword(); | 223 screen_lock_view_->ClearAndSetFocusToPassword(); |
180 } | 224 } |
181 | 225 |
182 // static | 226 // static |
183 void ScreenLocker::Show() { | 227 void ScreenLocker::Show() { |
184 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); | 228 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
185 DCHECK(!screen_locker_); | 229 // TODO(oshima): Currently, PowerManager may send a lock screen event |
186 gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL)); | 230 // even if a screen is locked. Investigate & solve the issue and |
187 ScreenLocker* locker = | 231 // enable this again if it's possible. |
188 new ScreenLocker(UserManager::Get()->logged_in_user()); | 232 // DCHECK(!screen_locker_); |
189 locker->Init(bounds); | 233 if (!screen_locker_) { |
| 234 gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL)); |
| 235 ScreenLocker* locker = |
| 236 new ScreenLocker(UserManager::Get()->logged_in_user()); |
| 237 locker->Init(bounds); |
| 238 } |
190 // TODO(oshima): Wait for a message from WM to complete the process. | 239 // TODO(oshima): Wait for a message from WM to complete the process. |
191 if (CrosLibrary::Get()->EnsureLoaded()) | 240 if (CrosLibrary::Get()->EnsureLoaded()) |
192 CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted(); | 241 CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted(); |
193 } | 242 } |
194 | 243 |
195 // static | 244 // static |
196 void ScreenLocker::Hide() { | 245 void ScreenLocker::Hide() { |
197 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); | 246 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
198 DCHECK(screen_locker_); | 247 DCHECK(screen_locker_); |
199 gdk_keyboard_ungrab(GDK_CURRENT_TIME); | 248 gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
(...skipping 14 matching lines...) Expand all Loading... |
214 LOG(INFO) << "Screen is unlocked"; | 263 LOG(INFO) << "Screen is unlocked"; |
215 } | 264 } |
216 } | 265 } |
217 | 266 |
218 // static | 267 // static |
219 void ScreenLocker::InitClass() { | 268 void ScreenLocker::InitClass() { |
220 Singleton<ScreenLockObserver>::get(); | 269 Singleton<ScreenLockObserver>::get(); |
221 } | 270 } |
222 | 271 |
223 } // namespace chromeos | 272 } // namespace chromeos |
OLD | NEW |