| 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 |