172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/screen_locker.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <X11/extensions/XTest.h> 8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <X11/keysym.h> 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <gdk/gdkkeysyms.h> 10201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <gdk/gdkx.h> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 13201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Evil hack to undo X11 evil #define. See crosbug.com/ 14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#undef Status 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/metrics/histogram.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/timer.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/cros/input_method_library.h" 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/chromeos/cros/login_library.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/cros/screen_lock_library.h" 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/chromeos/input_method/input_method_util.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/language_preferences.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/authenticator.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/background_view.h" 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/chromeos/login/login_performer.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/login_utils.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/message_bubble.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/login/screen_lock_view.h" 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/chromeos/login/shutdown_button.h" 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/chromeos/system_key_event_listener.h" 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/chromeos/view_ids.h" 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/chromeos/wm_ipc.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h" 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h" 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h" 41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/sync/profile_sync_service.h" 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h" 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h" 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h" 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "googleurl/src/gurl.h" 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "third_party/cros/chromeos_wm_ipc_enums.h" 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/x/x11_util.h" 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/screen.h" 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_gtk.h" 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// The maximum duration for which locker should try to grab the keyboard and 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// mouse and its interval for regrabbing on failure. 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kMaxGrabFailureSec = 30; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int64 kRetryGrabIntervalMs = 500; 654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Maximum number of times we'll try to grab the keyboard and mouse before 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// giving up. If we hit the limit, Chrome exits and the session is terminated. 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int kMaxGrabFailures = kMaxGrabFailureSec * 1000 / kRetryGrabIntervalMs; 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// A idle time to show the screen saver in seconds. 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kScreenSaverIdleTimeout = 15; 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Observer to start ScreenLocker when the screen lock 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public NotificationObserver { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScreenLockObserver() { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::LOGIN_USER_CHANGED, 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NotificationObserver overrides: 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Observe(NotificationType type, 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::LOGIN_USER_CHANGED) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register Screen Lock after login screen to make sure 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't show the screen lock on top of the login screen by accident. 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chromeos::CrosLibrary::Get()->EnsureLoaded()) 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::CrosLibrary::Get()->GetScreenLockLibrary()->AddObserver(this); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void LockScreen(chromeos::ScreenLockLibrary* obj) { 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "In: ScreenLockObserver::LockScreen"; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetupInputMethodsForScreenLocker(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ScreenLocker::Show(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void UnlockScreen(chromeos::ScreenLockLibrary* obj) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RestoreInputMethods(); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ScreenLocker::Hide(); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void UnlockScreenFailed(chromeos::ScreenLockLibrary* obj) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ScreenLocker::UnlockScreenFailed(); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Temporarily deactivates all input methods (e.g. Chinese, Japanese, Arabic) 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since they are not necessary to input a login password. Users are still 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // able to use/switch active keyboard layouts (e.g. US qwerty, US dvorak, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // French). 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetupInputMethodsForScreenLocker() { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chromeos::CrosLibrary::Get()->EnsureLoaded() && 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The LockScreen function is also called when the OS is suspended, and 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in that case |saved_active_input_method_list_| might be non-empty. 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_active_input_method_list_.empty()) { 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chromeos::InputMethodLibrary* library = 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen saved_previous_input_method_id_ = library->previous_input_method().id; 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen saved_current_input_method_id_ = library->current_input_method().id; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<chromeos::InputMethodDescriptors> active_input_method_list( 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->GetActiveInputMethods()); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string hardware_keyboard_id = 12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chromeos::input_method::GetHardwareInputMethodId(); 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We'll add the hardware keyboard if it's not included in 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // |active_input_method_list| so that the user can always use the hardware 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // keyboard on the screen locker. 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool should_add_hardware_keyboard = true; 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ImeConfigValue value; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value.type = chromeos::ImeConfigValue::kValueTypeStringList; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < active_input_method_list->size(); ++i) { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& input_method_id = active_input_method_list->at(i).id; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_active_input_method_list_.push_back(input_method_id); 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Skip if it's not a keyboard layout. 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!chromeos::input_method::IsKeyboardLayout(input_method_id)) 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value.string_list_value.push_back(input_method_id); 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (input_method_id == hardware_keyboard_id) { 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick should_add_hardware_keyboard = false; 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (should_add_hardware_keyboard) { 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen value.string_list_value.push_back(hardware_keyboard_id); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // We don't want to shut down the IME, even if the hardware layout is the 151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // only IME left. 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->SetEnableAutoImeShutdown(false); 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->SetImeConfig( 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chromeos::language_prefs::kGeneralSectionName, 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chromeos::language_prefs::kPreloadEnginesConfigName, 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick value); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void RestoreInputMethods() { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chromeos::CrosLibrary::Get()->EnsureLoaded() && 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !saved_active_input_method_list_.empty()) { 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chromeos::InputMethodLibrary* library = 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ImeConfigValue value; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value.type = chromeos::ImeConfigValue::kValueTypeStringList; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value.string_list_value = saved_active_input_method_list_; 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->SetEnableAutoImeShutdown(true); 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->SetImeConfig( 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chromeos::language_prefs::kGeneralSectionName, 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chromeos::language_prefs::kPreloadEnginesConfigName, 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick value); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send previous input method id first so Ctrl+space would work fine. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!saved_previous_input_method_id_.empty()) 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->ChangeInputMethod(saved_previous_input_method_id_); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!saved_current_input_method_id_.empty()) 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen library->ChangeInputMethod(saved_current_input_method_id_); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_previous_input_method_id_.clear(); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_current_input_method_id_.clear(); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_active_input_method_list_.clear(); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string saved_previous_input_method_id_; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string saved_current_input_method_id_; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> saved_active_input_method_list_; 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ScreenLockObserver); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<ScreenLockObserver> g_screen_lock_observer( 19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::LINKER_INITIALIZED); 19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// A ScreenLock window that covers entire screen to keep the keyboard 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// focus/events inside the grab widget. 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass LockWindow : public views::WidgetGtk { 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LockWindow() 2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW), 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toplevel_focus_widget_(NULL) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EnableDoubleBuffer(true); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GTK propagates key events from parents to children. 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure LockWindow will never handle key events. 20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual gboolean OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't handle key event in the lock window. 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void OnDestroy(GtkWidget* object) { 215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "OnDestroy: LockWindow destroyed"; 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick views::WidgetGtk::OnDestroy(object); 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void ClearNativeFocus() { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(toplevel_focus_widget_); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_grab_focus(toplevel_focus_widget_); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets the widget to move the focus to when clearning the native 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // widget's focus. 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_toplevel_focus_widget(GtkWidget* widget) { 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toplevel_focus_widget_ = widget; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The widget we set focus to when clearning the focus on native 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // widget. In screen locker, gdk input is grabbed in GrabWidget, 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and resetting the focus by using gtk_window_set_focus seems to 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // confuse gtk and doesn't let focus move to native widget under 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GrabWidget. 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* toplevel_focus_widget_; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(LockWindow); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// GrabWidget's root view to layout the ScreenLockView at the center 243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// and the Shutdown button at the right bottom. 24421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass GrabWidgetRootView 24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : public views::View, 24621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public chromeos::ScreenLocker::ScreenLockViewContainer { 247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch explicit GrabWidgetRootView(chromeos::ScreenLockView* screen_lock_view) 249513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : screen_lock_view_(screen_lock_view), 250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch shutdown_button_(new chromeos::ShutdownButton()) { 251513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch shutdown_button_->Init(); 252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AddChildView(screen_lock_view_); 253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AddChildView(shutdown_button_); 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // views::View implementation. 257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void Layout() { 258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gfx::Size size = screen_lock_view_->GetPreferredSize(); 259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch screen_lock_view_->SetBounds(0, 0, size.width(), size.height()); 260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch shutdown_button_->LayoutIn(this); 261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // ScreenLocker::ScreenLockViewContainer implementation: 26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void SetScreenLockView(views::View* screen_lock_view) { 26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (screen_lock_view_) { 26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen RemoveChildView(screen_lock_view_); 26721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 26821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_ = screen_lock_view; 26921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (screen_lock_view_) { 27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen AddChildViewAt(screen_lock_view_, 0); 27121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 27221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Layout(); 27321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 27421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch views::View* screen_lock_view_; 277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch chromeos::ShutdownButton* shutdown_button_; 279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(GrabWidgetRootView); 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A child widget that grabs both keyboard and pointer input. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass GrabWidget : public views::WidgetGtk { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit GrabWidget(chromeos::ScreenLocker* screen_locker) 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : views::WidgetGtk(views::WidgetGtk::TYPE_CHILD), 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_locker_(screen_locker), 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch grab_failure_count_(0), 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kbd_grab_status_(GDK_GRAB_INVALID_TIME), 29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mouse_grab_status_(GDK_GRAB_INVALID_TIME), 29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen signout_link_(NULL), 29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen shutdown_(NULL) { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Show() { 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::WidgetGtk::Show(); 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen signout_link_ = 30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen screen_locker_->GetViewByID(VIEW_ID_SCREEN_LOCKER_SIGNOUT_LINK); 30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen shutdown_ = screen_locker_->GetViewByID(VIEW_ID_SCREEN_LOCKER_SHUTDOWN); 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // These can be null in guest mode. 3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch void ClearGtkGrab() { 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* current_grab_window; 307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Grab gtk input first so that the menu holding gtk grab will 308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // close itself. 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_grab_add(window_contents()); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 311201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Make sure there is no gtk grab widget so that gtk simply propagates 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an event. This is necessary to allow message bubble and password 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // field, button to process events simultaneously. GTK 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // maintains grab widgets in a linked-list, so we need to remove 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // until it's empty. 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while ((current_grab_window = gtk_grab_get_current()) != NULL) 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_grab_remove(current_grab_window); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual gboolean OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::KeyEvent key_event(reinterpret_cast<GdkEvent*>(event)); 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This is a hack to workaround the issue crosbug.com/10655 due to 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the limitation that a focus manager cannot handle views in 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TYPE_CHILD WidgetGtk correctly. 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (signout_link_ && 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event->type == GDK_KEY_PRESS && 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (event->keyval == GDK_Tab || 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event->keyval == GDK_ISO_Left_Tab || 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event->keyval == GDK_KP_Tab)) { 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(shutdown_); 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool reverse = event->state & GDK_SHIFT_MASK; 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (reverse && signout_link_->HasFocus()) { 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen shutdown_->RequestFocus(); 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!reverse && shutdown_->HasFocus()) { 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen signout_link_->RequestFocus(); 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return views::WidgetGtk::OnKeyEvent(widget, event); 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WidgetGtk::OnButtonPress(widget, event); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Never propagate event to parent. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to grab all inputs. It initiates another try if it fails to 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // grab and the retry count is within a limit, or fails with CHECK. 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void TryGrabAllInputs(); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 354201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // This method tries to steal pointer/keyboard grab from other 355201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // client by sending events that will hopefully close menus or windows 356201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // that have the grab. 357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch void TryUngrabOtherClients(); 358201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void HandleGtkGrabBroke() { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Input should never be stolen from ScreenLocker once it's 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // grabbed. If this happens, it's a bug and has to be fixed. We 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // let chrome crash to get a crash report and dump, and 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SessionManager will terminate the session to logout. 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_NE(GDK_GRAB_SUCCESS, kbd_grab_status_); 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_NE(GDK_GRAB_SUCCESS, mouse_grab_status_); 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Define separate methods for each error code so that stack trace 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will tell which error the grab failed with. 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void FailedWithGrabAlreadyGrabbed() { 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(FATAL) << "Grab already grabbed"; 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void FailedWithGrabInvalidTime() { 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(FATAL) << "Grab invalid time"; 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void FailedWithGrabNotViewable() { 378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(FATAL) << "Grab not viewable"; 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void FailedWithGrabFrozen() { 381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(FATAL) << "Grab frozen"; 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void FailedWithUnknownError() { 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(FATAL) << "Grab uknown"; 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ScreenLocker* screen_locker_; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedRunnableMethodFactory<GrabWidget> task_factory_; 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number times the widget tried to grab all focus. 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int grab_failure_count_; 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Status of keyboard and mouse grab. 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkGrabStatus kbd_grab_status_; 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkGrabStatus mouse_grab_status_; 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::View* signout_link_; 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::View* shutdown_; 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(GrabWidget); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GrabWidget::TryGrabAllInputs() { 403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Grab x server so that we can atomically grab and take 404201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // action when grab fails. 405201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch gdk_x11_grab_server(); 4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (kbd_grab_status_ != GDK_GRAB_SUCCESS) { 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kbd_grab_status_ = gdk_keyboard_grab(window_contents()->window, FALSE, 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_CURRENT_TIME); 4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mouse_grab_status_ != GDK_GRAB_SUCCESS) { 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mouse_grab_status_ = 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_pointer_grab(window_contents()->window, 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FALSE, 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<GdkEventMask>( 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_POINTER_MOTION_MASK), 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_CURRENT_TIME); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((kbd_grab_status_ != GDK_GRAB_SUCCESS || 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mouse_grab_status_ != GDK_GRAB_SUCCESS) && 4234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch grab_failure_count_++ < kMaxGrabFailures) { 4244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(WARNING) << "Failed to grab inputs. Trying again in " 4254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << kRetryGrabIntervalMs << " ms: kbd=" 4264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; 427201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TryUngrabOtherClients(); 428201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch gdk_x11_ungrab_server(); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask( 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch task_factory_.NewRunnableMethod(&GrabWidget::TryGrabAllInputs), 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kRetryGrabIntervalMs); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch gdk_x11_ungrab_server(); 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GdkGrabStatus status = kbd_grab_status_; 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (status == GDK_GRAB_SUCCESS) { 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen status = mouse_grab_status_; 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (status) { 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case GDK_GRAB_SUCCESS: 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case GDK_GRAB_ALREADY_GRABBED: 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FailedWithGrabAlreadyGrabbed(); 444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case GDK_GRAB_INVALID_TIME: 446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FailedWithGrabInvalidTime(); 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case GDK_GRAB_NOT_VIEWABLE: 449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FailedWithGrabNotViewable(); 450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case GDK_GRAB_FROZEN: 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FailedWithGrabFrozen(); 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FailedWithUnknownError(); 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "Grab Success"; 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_locker_->OnGrabInputs(); 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 463201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid GrabWidget::TryUngrabOtherClients() { 464201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if !defined(NDEBUG) 465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch { 466201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int event_base, error_base; 467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int major, minor; 468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Make sure we have XTest extension. 46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(XTestQueryExtension(ui::GetXDisplay(), 470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &event_base, &error_base, 471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &major, &minor)); 472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif 474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The following code is an attempt to grab inputs by closing 476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // supposedly opened menu. This happens when a plugin has a menu 477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // opened. 478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (mouse_grab_status_ == GDK_GRAB_ALREADY_GRABBED || 479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch mouse_grab_status_ == GDK_GRAB_FROZEN) { 480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Successfully grabbed the keyboard, but pointer is still 481201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // grabbed by other client. Another attempt to close supposedly 482201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // opened menu by emulating keypress at the left top corner. 48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Display* display = ui::GetXDisplay(); 484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch Window root, child; 485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int root_x, root_y, win_x, winy; 486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch unsigned int mask; 487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XQueryPointer(display, 48872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::GetX11WindowFromGtkWidget(window_contents()), 489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &root, &child, &root_x, &root_y, 490201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &win_x, &winy, &mask); 491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeMotionEvent(display, -1, -10000, -10000, CurrentTime); 492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeButtonEvent(display, 1, True, CurrentTime); 493201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeButtonEvent(display, 1, False, CurrentTime); 494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Move the pointer back. 495201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeMotionEvent(display, -1, root_x, root_y, CurrentTime); 496201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XFlush(display); 497201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else if (kbd_grab_status_ == GDK_GRAB_ALREADY_GRABBED || 498201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch kbd_grab_status_ == GDK_GRAB_FROZEN) { 499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Successfully grabbed the pointer, but keyboard is still grabbed 500201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // by other client. Another attempt to close supposedly opened 501201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // menu by emulating escape key. Such situation must be very 502201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // rare, but handling this just in case 50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Display* display = ui::GetXDisplay(); 504201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch KeyCode escape = XKeysymToKeycode(display, XK_Escape); 505201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeKeyEvent(display, escape, True, CurrentTime); 506201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XTestFakeKeyEvent(display, escape, False, CurrentTime); 507201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch XFlush(display); 508201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 509201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 510201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BackgroundView for ScreenLocker, which layouts a lock widget in 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// addition to other background components. 51321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass ScreenLockerBackgroundView 51421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : public chromeos::BackgroundView, 51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public chromeos::ScreenLocker::ScreenLockViewContainer { 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 517513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ScreenLockerBackgroundView(views::WidgetGtk* lock_widget, 518513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch views::View* screen_lock_view) 519513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : lock_widget_(lock_widget), 520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch screen_lock_view_(screen_lock_view) { 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual ScreenMode GetScreenMode() const { 52472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kScreenLockerMode; 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Layout() { 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::BackgroundView::Layout(); 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect screen = bounds(); 530513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (screen_lock_view_) { 531513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gfx::Size size = screen_lock_view_->GetPreferredSize(); 532513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gfx::Point origin((screen.width() - size.width()) / 2, 533513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (screen.height() - size.height()) / 2); 534513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch gfx::Size widget_size(screen.size()); 535513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch widget_size.Enlarge(-origin.x(), -origin.y()); 536513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch lock_widget_->SetBounds(gfx::Rect(origin, widget_size)); 537513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 538513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // No password entry. Move the lock widget to off screen. 539513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch lock_widget_->SetBounds(gfx::Rect(-100, -100, 1, 1)); 540513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // ScreenLocker::ScreenLockViewContainer implementation: 54421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void SetScreenLockView(views::View* screen_lock_view) { 54521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_ = screen_lock_view; 54621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Layout(); 54721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 54821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::WidgetGtk* lock_widget_; 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 552513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch views::View* screen_lock_view_; 553513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ScreenLockerBackgroundView); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochScreenLocker* ScreenLocker::screen_locker_ = NULL; 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A event observer that forwards gtk events from one window to another. 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// See screen_locker.h for more details. 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MouseEventRelay : public MessageLoopForUI::Observer { 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 5683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MouseEventRelay(GdkWindow* src, GdkWindow* dest) 5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : src_(src), 5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dest_(dest), 5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick initialized_(false) { 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(src_); 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(dest_); 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void WillProcessEvent(GdkEvent* event) {} 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void DidProcessEvent(GdkEvent* event) { 5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (event->any.window != src_) 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!initialized_) { 5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gint src_x, src_y, dest_x, dest_y, width, height, depth; 5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gdk_window_get_geometry(dest_, &dest_x, &dest_y, &width, &height, &depth); 5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // wait to compute offset until the info bubble widget's location 5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // is available. 5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dest_x < 0 || dest_y < 0) 5873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gdk_window_get_geometry(src_, &src_x, &src_y, &width, &height, &depth); 5893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset_.SetPoint(dest_x - src_x, dest_y - src_y); 5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick initialized_ = true; 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->type == GDK_BUTTON_PRESS || 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->type == GDK_BUTTON_RELEASE) { 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEvent* copy = gdk_event_copy(event); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copy->button.window = dest_; 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_ref(copy->button.window); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copy->button.x -= offset_.x(); 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copy->button.y -= offset_.y(); 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_event_put(copy); 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_event_free(copy); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (event->type == GDK_MOTION_NOTIFY) { 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEvent* copy = gdk_event_copy(event); 6043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick copy->motion.window = dest_; 6053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_object_ref(copy->motion.window); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copy->motion.x -= offset_.x(); 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copy->motion.y -= offset_.y(); 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_event_put(copy); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_event_free(copy); 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkWindow* src_; 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkWindow* dest_; 6173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool initialized_; 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Offset from src_'s origin to dest_'s origin. 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point offset_; 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(MouseEventRelay); 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A event observer used to unlock the screen upon user's action 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// without asking password. Used in BWSI and auto login mode. 6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(oshima): consolidate InputEventObserver and LockerInputEventObserver. 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass InputEventObserver : public MessageLoopForUI::Observer { 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit InputEventObserver(ScreenLocker* screen_locker) 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : screen_locker_(screen_locker), 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch activated_(false) { 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void WillProcessEvent(GdkEvent* event) { 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((event->type == GDK_KEY_PRESS || 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->type == GDK_BUTTON_PRESS || 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->type == GDK_MOTION_NOTIFY) && 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !activated_) { 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch activated_ = true; 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string not_used_string; 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GaiaAuthConsumer::ClientLoginResult not_used; 643513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch screen_locker_->OnLoginSuccess(not_used_string, 644513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch not_used_string, 645513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch not_used, 646513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch false); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void DidProcessEvent(GdkEvent* event) { 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chromeos::ScreenLocker* screen_locker_; 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool activated_; 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(InputEventObserver); 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// A event observer used to show the screen locker upon 6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// user action: mouse or keyboard interactions. 6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(oshima): this has to be disabled while authenticating. 6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass LockerInputEventObserver : public MessageLoopForUI::Observer { 6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick explicit LockerInputEventObserver(ScreenLocker* screen_locker) 6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : screen_locker_(screen_locker), 6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ALLOW_THIS_IN_INITIALIZER_LIST( 6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick timer_(base::TimeDelta::FromSeconds(kScreenSaverIdleTimeout), this, 6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &LockerInputEventObserver::StartScreenSaver)) { 6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void WillProcessEvent(GdkEvent* event) { 6743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if ((event->type == GDK_KEY_PRESS || 6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick event->type == GDK_BUTTON_PRESS || 6763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick event->type == GDK_MOTION_NOTIFY)) { 6773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick timer_.Reset(); 6783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_locker_->StopScreenSaver(); 6793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void DidProcessEvent(GdkEvent* event) { 6833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 6863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void StartScreenSaver() { 6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_locker_->StartScreenSaver(); 6883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chromeos::ScreenLocker* screen_locker_; 6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::DelayTimer<LockerInputEventObserver> timer_; 6923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(LockerInputEventObserver); 6943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick////////////////////////////////////////////////////////////////////////////// 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScreenLocker, public: 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochScreenLocker::ScreenLocker(const UserManager::User& user) 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : lock_window_(NULL), 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_widget_(NULL), 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_(NULL), 70321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_(NULL), 70421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen grab_container_(NULL), 70521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen background_container_(NULL), 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_(user), 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_info_(NULL), 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drawn_(false), 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch input_grabbed_(false), 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(oshima): support auto login mode (this is not implemented yet) 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://crosbug.com/1881 712731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick unlock_on_input_(user_.email().empty()), 713513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch locked_(false), 714513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch start_time_(base::Time::Now()) { 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!screen_locker_); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_locker_ = this; 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::Init() { 720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const GdkColor kGdkBlack = {0, 0, 0, 0}; 721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point left_top(1, 1); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect init_bounds(views::Screen::GetMonitorAreaNearestPoint(left_top)); 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LockWindow* lock_window = new LockWindow(); 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window_ = lock_window; 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window_->Init(NULL, init_bounds); 730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_widget_modify_bg( 731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen lock_window_->GetNativeView(), GTK_STATE_NORMAL, &kGdkBlack); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(lock_window_->GetNativeView(), "client-event", 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnClientEventThunk), this); 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GTK does not like zero width/height. 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!unlock_on_input_) { 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_ = new ScreenLockView(this); 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->Init(); 740731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick screen_lock_view_->SetEnabled(false); 74121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->StartThrobber(); 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch input_event_observer_.reset(new InputEventObserver(this)); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI::current()->AddObserver(input_event_observer_.get()); 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Hang on to a cast version of the grab widget so we can call its 7484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TryGrabAllInputs() method later. (Nobody else needs to use it, so moving 7494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // its declaration to the header instead of keeping it in an anonymous 7504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // namespace feels a bit ugly.) 7514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GrabWidget* cast_lock_widget = new GrabWidget(this); 7524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch lock_widget_ = cast_lock_widget; 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_widget_->MakeTransparent(); 754731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick lock_widget_->InitWithWidget(lock_window_, gfx::Rect()); 755513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (screen_lock_view_) { 75621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen GrabWidgetRootView* root_view = new GrabWidgetRootView(screen_lock_view_); 75721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen grab_container_ = root_view; 75821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen lock_widget_->SetContentsView(root_view); 759513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_widget_->Show(); 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Configuring the background url. 7633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string url_string = 7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switches::kScreenSaverUrl); 76621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScreenLockerBackgroundView* screen_lock_background_view_ = 76721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new ScreenLockerBackgroundView(lock_widget_, screen_lock_view_); 76821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen background_container_ = screen_lock_background_view_; 76921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen background_view_ = screen_lock_background_view_; 7703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_view_->Init(GURL(url_string)); 771731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (background_view_->ScreenSaverEnabled()) 772731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick StartScreenSaver(); 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView())); 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WmIpc::instance()->SetWindowType( 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window_->GetNativeView(), 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WM_IPC_WINDOW_CHROME_SCREEN_LOCKER, 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL); 7793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_window_->SetContentsView(background_view_); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window_->Show(); 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch cast_lock_widget->ClearGtkGrab(); 784201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 785201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Call this after lock_window_->Show(); otherwise the 1st invocation 786201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // of gdk_xxx_grab() will always fail. 7874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cast_lock_widget->TryGrabAllInputs(); 7884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 7894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Add the window to its own group so that its grab won't be stolen if 7904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. 7914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this 792201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // after calling ClearGtkGrab(), as want to be in the default window group 7934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // then so we can break any existing GTK grabs. 7944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GtkWindowGroup* window_group = gtk_window_group_new(); 7954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch gtk_window_group_add_window(window_group, 7964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GTK_WINDOW(lock_window_->GetNativeView())); 7974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch g_object_unref(window_group); 7984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window->set_toplevel_focus_widget(lock_widget_->window_contents()); 800513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 801513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Create the SystemKeyEventListener so it can listen for system keyboard 802513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // messages regardless of focus while screen locked. 80321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SystemKeyEventListener::GetInstance(); 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ScreenLocker::OnLoginFailure(const LoginFailure& error) { 807731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "OnLoginFailure"; 808513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UserMetrics::RecordAction(UserMetricsAction("ScreenLocker_OnLoginFailure")); 809513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (authentication_start_time_.is_null()) { 810513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "authentication_start_time_ is not set"; 811513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 812513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::TimeDelta delta = base::Time::Now() - authentication_start_time_; 813513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Authentication failure time: " << delta.InSecondsF(); 814513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationFailureTime", delta); 815513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 816513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EnableInput(); 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't enable signout button here as we're showing 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MessageBubble. 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen string16 msg = l10n_util::GetStringUTF16(IDS_LOGIN_ERROR_AUTHENTICATING); 8223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string error_text = error.GetErrorString(); 8233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!error_text.empty()) 8243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen msg += ASCIIToUTF16("\n") + ASCIIToUTF16(error_text); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InputMethodLibrary* input_method_library = 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrosLibrary::Get()->GetInputMethodLibrary(); 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (input_method_library->GetNumActiveInputMethods() > 1) 8293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen msg += ASCIIToUTF16("\n") + 8303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen l10n_util::GetStringUTF16(IDS_LOGIN_ERROR_KEYBOARD_SWITCH_HINT); 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ShowErrorBubble(UTF16ToWide(msg), BubbleBorder::BOTTOM_LEFT); 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 835731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ScreenLocker::OnLoginSuccess( 836731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& username, 837513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& password, 838731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GaiaAuthConsumer::ClientLoginResult& unused, 839731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool pending_requests) { 840731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "OnLoginSuccess: Sending Unlock request."; 841513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (authentication_start_time_.is_null()) { 842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!username.empty()) 843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "authentication_start_time_ is not set"; 844513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 845513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::TimeDelta delta = base::Time::Now() - authentication_start_time_; 846513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Authentication success time: " << delta.InSecondsF(); 847513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationSuccessTime", delta); 848513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 849513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 850201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch Profile* profile = ProfileManager::GetDefaultProfile(); 851201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (profile) { 852201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ProfileSyncService* service = profile->GetProfileSyncService(username); 853201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (service && !service->HasSyncSetupCompleted()) { 854201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If sync has failed somehow, try setting the sync passphrase here. 85572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen service->SetPassphrase(password, false, true); 856201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 857201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 858201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CrosLibrary::Get()->EnsureLoaded()) 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenUnlockRequested(); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ScreenLocker::BubbleClosing(Bubble* bubble, bool closed_by_escape) { 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_info_ = NULL; 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->SetSignoutEnabled(true); 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mouse_event_relay_.get()) { 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI::current()->RemoveObserver(mouse_event_relay_.get()); 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mouse_event_relay_.reset(); 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ScreenLocker::OnCaptchaEntered(const std::string& captcha) { 87321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Captcha dialog is only shown when LoginPerformer instance exists, 87421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // i.e. blocking UI after password change is in place. 87521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(LoginPerformer::default_performer()); 87621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LoginPerformer::default_performer()->set_captcha(captcha); 87721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 87821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // ScreenLockView ownership is passed to grab_container_. 87921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Need to save return value here so that compile 88021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // doesn't fail with "unused result" warning. 88121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen views::View* view = secondary_view_.release(); 88221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen view = NULL; 88321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_->SetVisible(false); 88421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen grab_container_->SetScreenLockView(screen_lock_view_); 88521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen background_container_->SetScreenLockView(screen_lock_view_); 88621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->SetVisible(true); 88721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->ClearAndSetFocusToPassword(); 88821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 88921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Take CaptchaView ownership now that it's removed from grab_container_. 89021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen secondary_view_.reset(captcha_view_); 89121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ShowErrorMessage(postponed_error_message_, false); 89221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen postponed_error_message_.clear(); 89321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 89421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::Authenticate(const string16& password) { 896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (password.empty()) 897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 899513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch authentication_start_time_ = base::Time::Now(); 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->SetEnabled(false); 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->SetSignoutEnabled(false); 90221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->StartThrobber(); 90321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 90421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If LoginPerformer instance exists, 90521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // initial online login phase is still active. 90621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (LoginPerformer::default_performer()) { 90721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DVLOG(1) << "Delegating authentication to LoginPerformer."; 90821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LoginPerformer::default_performer()->Login(user_.email(), 90921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen UTF16ToUTF8(password)); 91021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 91121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BrowserThread::PostTask( 91221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BrowserThread::UI, FROM_HERE, 91321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen NewRunnableMethod(authenticator_.get(), 91421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &Authenticator::AuthenticateToUnlock, 91521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen user_.email(), 91621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen UTF16ToUTF8(password))); 91721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::ClearErrors() { 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error_info_) { 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_info_->Close(); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_info_ = NULL; 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::EnableInput() { 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_lock_view_) { 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->SetEnabled(true); 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_lock_view_->ClearAndSetFocusToPassword(); 93121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->StopThrobber(); 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::Signout() { 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!error_info_) { 937513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UserMetrics::RecordAction(UserMetricsAction("ScreenLocker_Signout")); 9383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen WmIpc::instance()->NotifyAboutSignout(); 9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CrosLibrary::Get()->EnsureLoaded()) { 9403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CrosLibrary::Get()->GetLoginLibrary()->StopSession(""); 9413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't hide yet the locker because the chrome screen may become visible 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // briefly. 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ScreenLocker::ShowCaptchaAndErrorMessage(const GURL& captcha_url, 94921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::wstring& message) { 95021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen postponed_error_message_ = message; 95121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (captcha_view_) { 95221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_->SetCaptchaURL(captcha_url); 95321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 95421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_ = new CaptchaView(captcha_url, true); 95521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_->Init(); 95621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_->set_delegate(this); 95721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 95821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CaptchaView ownership is passed to grab_container_. 95921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen views::View* view = secondary_view_.release(); 96021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen view = NULL; 96121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->SetVisible(false); 96221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen grab_container_->SetScreenLockView(captcha_view_); 96321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen background_container_->SetScreenLockView(captcha_view_); 96421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen captcha_view_->SetVisible(true); 96521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Take ScreenLockView ownership now that it's removed from grab_container_. 96621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen secondary_view_.reset(screen_lock_view_); 96721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 96821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 96921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ScreenLocker::ShowErrorMessage(const std::wstring& message, 97021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool sign_out_only) { 97121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (sign_out_only) { 97221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->SetEnabled(false); 97321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 97421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen EnableInput(); 97521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 97621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen screen_lock_view_->SetSignoutEnabled(sign_out_only); 97721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Make sure that active Sign Out button is not hidden behind the bubble. 97821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ShowErrorBubble(message, sign_out_only ? 97921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BubbleBorder::BOTTOM_RIGHT : BubbleBorder::BOTTOM_LEFT); 98021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 98121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::OnGrabInputs() { 983731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "OnGrabInputs"; 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch input_grabbed_ = true; 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drawn_) 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScreenLockReady(); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenviews::View* ScreenLocker::GetViewByID(int id) { 99072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return lock_widget_->GetRootView()->GetViewByID(id); 99172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 99272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::Show() { 995731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "In ScreenLocker::Show"; 996513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UserMetrics::RecordAction(UserMetricsAction("ScreenLocker_Show")); 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Exit fullscreen. 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = BrowserList::GetLastActive(); 10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // browser can be NULL if we receive a lock request before the first browser 10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // window is shown. 10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (browser && browser->window()->IsFullscreen()) { 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->ToggleFullscreenMode(); 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!screen_locker_) { 1008731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Show: Locking screen"; 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScreenLocker* locker = 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new ScreenLocker(UserManager::Get()->logged_in_user()); 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch locker->Init(); 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // PowerManager re-sends lock screen signal if it doesn't 10143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // receive the response within timeout. Just send complete 10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // signal. 1016731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Show: locker already exists. Just sending completion event."; 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CrosLibrary::Get()->EnsureLoaded()) 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted(); 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::Hide() { 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(screen_locker_); 1026731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Hide: Deleting ScreenLocker: " << screen_locker_; 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI::current()->DeleteSoon(FROM_HERE, screen_locker_); 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::UnlockScreenFailed() { 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_locker_) { 10343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Power manager decided no to unlock the screen even if a user 10353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // typed in password, for example, when a user closed the lid 10363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // immediately after typing in the password. 1037731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "UnlockScreenFailed: re-enabling screen locker."; 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_locker_->EnableInput(); 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This can happen when a user requested unlock, but PowerManager 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // rejected because the computer is closed, then PowerManager unlocked 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because it's open again and the above failure message arrives. 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This'd be extremely rare, but may still happen. 1044731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "UnlockScreenFailed: screen is already unlocked."; 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::InitClass() { 105021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_screen_lock_observer.Get(); 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScreenLocker, private: 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochScreenLocker::~ScreenLocker() { 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearErrors(); 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (input_event_observer_.get()) 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI::current()->RemoveObserver(input_event_observer_.get()); 10613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (locker_input_event_observer_.get()) { 10623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_widget_->GetFocusManager()->UnregisterAccelerator( 106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this); 10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MessageLoopForUI::current()->RemoveObserver( 10653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick locker_input_event_observer_.get()); 10663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_keyboard_ungrab(GDK_CURRENT_TIME); 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_pointer_ungrab(GDK_CURRENT_TIME); 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(lock_window_); 1072731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "~ScreenLocker(): Closing ScreenLocker window."; 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lock_window_->Close(); 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // lock_widget_ will be deleted by gtk's destroy signal. 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_locker_ = NULL; 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool state = false; 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::SCREEN_LOCK_STATE_CHANGED, 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<ScreenLocker>(this), 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<bool>(&state)); 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CrosLibrary::Get()->EnsureLoaded()) 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenUnlockCompleted(); 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::SetAuthenticator(Authenticator* authenticator) { 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch authenticator_ = authenticator; 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::ScreenLockReady() { 1090731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "ScreenLockReady: sending completed signal to power manager."; 1091731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick locked_ = true; 1092513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::TimeDelta delta = base::Time::Now() - start_time_; 1093513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Screen lock time: " << delta.InSecondsF(); 1094513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UMA_HISTOGRAM_TIMES("ScreenLocker.ScreenLockTime", delta); 1095513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 10963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (background_view_->ScreenSaverEnabled()) { 10973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick lock_widget_->GetFocusManager()->RegisterAccelerator( 109872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this); 10993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick locker_input_event_observer_.reset(new LockerInputEventObserver(this)); 11003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MessageLoopForUI::current()->AddObserver( 11013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick locker_input_event_observer_.get()); 11023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Don't enable the password field until we grab all inputs. 11043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableInput(); 11053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool state = true; 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::SCREEN_LOCK_STATE_CHANGED, 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<ScreenLocker>(this), 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<bool>(&state)); 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CrosLibrary::Get()->EnsureLoaded()) 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted(); 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::OnClientEvent(GtkWidget* widge, GdkEventClient* event) { 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WmIpc::Message msg; 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WmIpc::instance()->DecodeMessage(*event, &msg); 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_SCREEN_REDRAWN_FOR_LOCK) { 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnWindowManagerReady(); 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ScreenLocker::OnWindowManagerReady() { 1125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "OnClientEvent: drawn for lock"; 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drawn_ = true; 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (input_grabbed_) 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScreenLockReady(); 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ScreenLocker::ShowErrorBubble(const std::wstring& message, 113221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BubbleBorder::ArrowLocation arrow_location) { 113321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (error_info_) 113421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_info_->Close(); 113521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 113621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen gfx::Rect rect = screen_lock_view_->GetPasswordBoundsRelativeTo( 113721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen lock_widget_->GetRootView()); 1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gfx::Rect lock_widget_bounds = lock_widget_->GetClientAreaScreenBounds(); 113921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rect.Offset(lock_widget_bounds.x(), lock_widget_bounds.y()); 114021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_info_ = MessageBubble::ShowNoGrab( 114121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen lock_window_, 114221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rect, 114321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen arrow_location, 114421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING), 114521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen message, 114621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::wstring(), // TODO(nkostylev): Add help link. 114721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this); 114821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 114921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (mouse_event_relay_.get()) 115021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen MessageLoopForUI::current()->RemoveObserver(mouse_event_relay_.get()); 115121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen mouse_event_relay_.reset( 115221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new MouseEventRelay(lock_widget_->GetNativeView()->window, 115321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_info_->GetNativeView()->window)); 115421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen MessageLoopForUI::current()->AddObserver(mouse_event_relay_.get()); 115521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 115621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ScreenLocker::StopScreenSaver() { 11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (background_view_->IsScreenSaverVisible()) { 1159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "StopScreenSaver"; 11603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_view_->HideScreenSaver(); 11613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (screen_lock_view_) { 11623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_lock_view_->SetVisible(true); 11633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_lock_view_->RequestFocus(); 11643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableInput(); 11663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 11683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 11693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ScreenLocker::StartScreenSaver() { 11703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!background_view_->IsScreenSaverVisible()) { 1171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "StartScreenSaver"; 1172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UserMetrics::RecordAction( 1173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UserMetricsAction("ScreenLocker_StartScreenSaver")); 11743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_view_->ShowScreenSaver(); 11753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (screen_lock_view_) { 11763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_lock_view_->SetEnabled(false); 11773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick screen_lock_view_->SetVisible(false); 11783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ClearErrors(); 11803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 11823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 11833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool ScreenLocker::AcceleratorPressed(const views::Accelerator& accelerator) { 11843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!background_view_->IsScreenSaverVisible()) { 11853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick StartScreenSaver(); 11863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 11873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 11893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 11903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chromeos 1192