screen_locker_browsertest.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/message_loop.h" 7#include "base/scoped_ptr.h" 8#include "chrome/browser/automation/ui_controls.h" 9#include "chrome/browser/browser.h" 10#include "chrome/browser/browser_window.h" 11#include "chrome/browser/chrome_thread.h" 12#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" 13#include "chrome/browser/chromeos/cros/mock_input_method_library.h" 14#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h" 15#include "chrome/browser/chromeos/login/mock_authenticator.h" 16#include "chrome/browser/chromeos/login/screen_locker.h" 17#include "chrome/browser/chromeos/login/screen_locker_tester.h" 18#include "chrome/browser/chromeos/login/user_manager.h" 19#include "chrome/browser/views/browser_dialogs.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/notification_service.h" 22#include "chrome/common/notification_type.h" 23#include "chrome/test/ui_test_utils.h" 24#include "testing/gmock/include/gmock/gmock.h" 25#include "testing/gtest/include/gtest/gtest.h" 26#include "views/controls/textfield/textfield.h" 27#include "views/window/window_gtk.h" 28 29namespace { 30 31// An object that wait for lock state and fullscreen state. 32class Waiter : public NotificationObserver { 33 public: 34 explicit Waiter(Browser* browser) 35 : browser_(browser) { 36 registrar_.Add(this, 37 NotificationType::SCREEN_LOCK_STATE_CHANGED, 38 NotificationService::AllSources()); 39 handler_id_ = g_signal_connect( 40 G_OBJECT(browser_->window()->GetNativeHandle()), 41 "window-state-event", 42 G_CALLBACK(OnWindowStateEventThunk), 43 this); 44 } 45 46 ~Waiter() { 47 g_signal_handler_disconnect( 48 G_OBJECT(browser_->window()->GetNativeHandle()), 49 handler_id_); 50 } 51 52 virtual void Observe(NotificationType type, 53 const NotificationSource& source, 54 const NotificationDetails& details) { 55 DCHECK(type == NotificationType::SCREEN_LOCK_STATE_CHANGED); 56 MessageLoop::current()->Quit(); 57 } 58 59 // Wait until the two conditions are met. 60 void Wait(bool locker_state, bool fullscreen) { 61 scoped_ptr<chromeos::test::ScreenLockerTester> 62 tester(chromeos::ScreenLocker::GetTester()); 63 while (tester->IsLocked() != locker_state || 64 browser_->window()->IsFullscreen() != fullscreen) { 65 ui_test_utils::RunMessageLoop(); 66 } 67 // Make sure all pending tasks are executed. 68 ui_test_utils::RunAllPendingInMessageLoop(); 69 } 70 71 CHROMEGTK_CALLBACK_1(Waiter, gboolean, OnWindowStateEvent, 72 GdkEventWindowState*); 73 74 private: 75 Browser* browser_; 76 gulong handler_id_; 77 NotificationRegistrar registrar_; 78 79 DISALLOW_COPY_AND_ASSIGN(Waiter); 80}; 81 82gboolean Waiter::OnWindowStateEvent(GtkWidget* widget, 83 GdkEventWindowState* event) { 84 MessageLoop::current()->Quit(); 85 return false; 86} 87 88} // namespace 89 90namespace chromeos { 91 92class ScreenLockerTest : public CrosInProcessBrowserTest { 93 public: 94 ScreenLockerTest() : mock_screen_lock_library_(NULL), 95 mock_input_method_library_(NULL) { 96 } 97 98 protected: 99 MockScreenLockLibrary *mock_screen_lock_library_; 100 MockInputMethodLibrary *mock_input_method_library_; 101 102 // Test the no password mode with different unlock scheme given by 103 // |unlock| function. 104 void TestNoPassword(void (unlock)(views::Widget*)) { 105 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested()) 106 .Times(1) 107 .RetiresOnSaturation(); 108 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted()) 109 .Times(1) 110 .RetiresOnSaturation(); 111 UserManager::Get()->OffTheRecordUserLoggedIn(); 112 ScreenLocker::Show(); 113 scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); 114 tester->EmulateWindowManagerReady(); 115 ui_test_utils::WaitForNotification( 116 NotificationType::SCREEN_LOCK_STATE_CHANGED); 117 EXPECT_TRUE(tester->IsLocked()); 118 tester->InjectMockAuthenticator("", ""); 119 120 unlock(tester->GetWidget()); 121 122 ui_test_utils::RunAllPendingInMessageLoop(); 123 EXPECT_TRUE(tester->IsLocked()); 124 125 // Emulate LockScreen request from PowerManager (via SessionManager). 126 ScreenLocker::Hide(); 127 ui_test_utils::RunAllPendingInMessageLoop(); 128 EXPECT_FALSE(tester->IsLocked()); 129 } 130 131 private: 132 virtual void SetUpInProcessBrowserTestFixture() { 133 cros_mock_->InitStatusAreaMocks(); 134 cros_mock_->InitMockScreenLockLibrary(); 135 mock_screen_lock_library_ = cros_mock_->mock_screen_lock_library(); 136 mock_input_method_library_ = cros_mock_->mock_input_method_library(); 137 EXPECT_CALL(*mock_screen_lock_library_, AddObserver(testing::_)) 138 .Times(1) 139 .RetiresOnSaturation(); 140 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockCompleted()) 141 .Times(1) 142 .RetiresOnSaturation(); 143 // Expectations for the status are on the screen lock window. 144 cros_mock_->SetStatusAreaMocksExpectations(); 145 // Expectations for the status area on the browser window. 146 cros_mock_->SetStatusAreaMocksExpectations(); 147 } 148 149 virtual void SetUpCommandLine(CommandLine* command_line) { 150 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); 151 command_line->AppendSwitch(switches::kNoFirstRun); 152 } 153 154 DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest); 155}; 156 157IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) { 158 EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods()) 159 .Times(1) 160 .WillRepeatedly((testing::Return(0))) 161 .RetiresOnSaturation(); 162 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested()) 163 .Times(1) 164 .RetiresOnSaturation(); 165 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted()) 166 .Times(1) 167 .RetiresOnSaturation(); 168 UserManager::Get()->UserLoggedIn("user"); 169 ScreenLocker::Show(); 170 scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); 171 tester->EmulateWindowManagerReady(); 172 ui_test_utils::WaitForNotification( 173 NotificationType::SCREEN_LOCK_STATE_CHANGED); 174 175 // Test to make sure that the widget is actually appearing and is of 176 // reasonable size, preventing a regression of 177 // http://code.google.com/p/chromium-os/issues/detail?id=5987 178 gfx::Rect lock_bounds; 179 tester->GetChildWidget()->GetBounds(&lock_bounds, true); 180 EXPECT_GT(lock_bounds.width(), 10); 181 EXPECT_GT(lock_bounds.height(), 10); 182 183 tester->InjectMockAuthenticator("user", "pass"); 184 EXPECT_TRUE(tester->IsLocked()); 185 tester->EnterPassword("fail"); 186 ui_test_utils::RunAllPendingInMessageLoop(); 187 EXPECT_TRUE(tester->IsLocked()); 188 tester->EnterPassword("pass"); 189 ui_test_utils::RunAllPendingInMessageLoop(); 190 // Successful authentication simply send a unlock request to PowerManager. 191 EXPECT_TRUE(tester->IsLocked()); 192 193 // Emulate LockScreen request from PowerManager (via SessionManager). 194 // TODO(oshima): Find out better way to handle this in mock. 195 ScreenLocker::Hide(); 196 ui_test_utils::RunAllPendingInMessageLoop(); 197 EXPECT_FALSE(tester->IsLocked()); 198} 199 200IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) { 201 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested()) 202 .Times(1) 203 .RetiresOnSaturation(); 204 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted()) 205 .Times(1) 206 .RetiresOnSaturation(); 207 scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); 208 { 209 Waiter waiter(browser()); 210 browser()->ToggleFullscreenMode(); 211 waiter.Wait(false /* not locked */, true /* full screen */); 212 EXPECT_TRUE(browser()->window()->IsFullscreen()); 213 EXPECT_FALSE(tester->IsLocked()); 214 } 215 { 216 Waiter waiter(browser()); 217 UserManager::Get()->UserLoggedIn("user"); 218 ScreenLocker::Show(); 219 tester->EmulateWindowManagerReady(); 220 waiter.Wait(true /* locked */, false /* full screen */); 221 EXPECT_FALSE(browser()->window()->IsFullscreen()); 222 EXPECT_TRUE(tester->IsLocked()); 223 } 224 tester->InjectMockAuthenticator("user", "pass"); 225 tester->EnterPassword("pass"); 226 ui_test_utils::RunAllPendingInMessageLoop(); 227 ScreenLocker::Hide(); 228 ui_test_utils::RunAllPendingInMessageLoop(); 229 EXPECT_FALSE(tester->IsLocked()); 230} 231 232void MouseMove(views::Widget* widget) { 233 ui_controls::SendMouseMove(10, 10); 234} 235 236IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseMove) { 237 TestNoPassword(MouseMove); 238} 239 240void MouseClick(views::Widget* widget) { 241 ui_controls::SendMouseClick(ui_controls::RIGHT); 242} 243 244IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseClick) { 245 TestNoPassword(MouseClick); 246} 247 248void KeyPress(views::Widget* widget) { 249 ui_controls::SendKeyPress(GTK_WINDOW(widget->GetNativeView()), 250 app::VKEY_SPACE, false, false, false, false); 251} 252 253IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithKeyPress) { 254 TestNoPassword(KeyPress); 255} 256 257IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestShowTwice) { 258 EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted()) 259 .Times(2) 260 .RetiresOnSaturation(); 261 262 UserManager::Get()->UserLoggedIn("user"); 263 ScreenLocker::Show(); 264 scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); 265 tester->EmulateWindowManagerReady(); 266 ui_test_utils::WaitForNotification( 267 NotificationType::SCREEN_LOCK_STATE_CHANGED); 268 EXPECT_TRUE(tester->IsLocked()); 269 270 // Calling Show again simply send LockCompleted signal. 271 ScreenLocker::Show(); 272 EXPECT_TRUE(tester->IsLocked()); 273 274 // Close the locker to match expectations. 275 ScreenLocker::Hide(); 276 ui_test_utils::RunAllPendingInMessageLoop(); 277 EXPECT_FALSE(tester->IsLocked()); 278} 279 280} // namespace chromeos 281