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