Disable overview on alt-tab by default and update test expectation to match.
[chromium-blink-merge.git] / remoting / host / client_session_unittest.cc
blob13207da8735db7263a86638198c5b33c719f0116
1 // Copyright (c) 2012 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.
5 #include "base/message_loop/message_loop.h"
6 #include "remoting/base/auto_thread_task_runner.h"
7 #include "remoting/base/constants.h"
8 #include "remoting/host/audio_capturer.h"
9 #include "remoting/host/client_session.h"
10 #include "remoting/host/desktop_environment.h"
11 #include "remoting/host/host_mock_objects.h"
12 #include "remoting/host/screen_capturer_fake.h"
13 #include "remoting/protocol/protocol_mock_objects.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
16 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
18 namespace remoting {
20 using protocol::MockConnectionToClient;
21 using protocol::MockClientStub;
22 using protocol::MockHostStub;
23 using protocol::MockInputStub;
24 using protocol::MockSession;
25 using protocol::MockVideoStub;
26 using protocol::SessionConfig;
28 using testing::_;
29 using testing::AnyNumber;
30 using testing::AtMost;
31 using testing::DeleteArg;
32 using testing::DoAll;
33 using testing::Expectation;
34 using testing::Return;
35 using testing::ReturnRef;
36 using testing::Sequence;
38 namespace {
40 ACTION_P2(InjectClipboardEvent, connection, event) {
41 connection->clipboard_stub()->InjectClipboardEvent(event);
44 ACTION_P2(InjectKeyEvent, connection, event) {
45 connection->input_stub()->InjectKeyEvent(event);
48 ACTION_P2(InjectMouseEvent, connection, event) {
49 connection->input_stub()->InjectMouseEvent(event);
52 ACTION_P2(LocalMouseMoved, client_session, event) {
53 client_session->OnLocalMouseMoved(SkIPoint::Make(event.x(), event.y()));
56 } // namespace
58 class ClientSessionTest : public testing::Test {
59 public:
60 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
62 virtual void SetUp() OVERRIDE;
63 virtual void TearDown() OVERRIDE;
65 // Disconnects the client session.
66 void DisconnectClientSession();
68 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
69 void StopClientSession();
71 protected:
72 // Creates a DesktopEnvironment with a fake webrtc::ScreenCapturer, to mock
73 // DesktopEnvironmentFactory::Create().
74 DesktopEnvironment* CreateDesktopEnvironment();
76 // Returns |input_injector_| created and initialized by SetUp(), to mock
77 // DesktopEnvironment::CreateInputInjector().
78 InputInjector* CreateInputInjector();
80 // Creates a fake webrtc::ScreenCapturer, to mock
81 // DesktopEnvironment::CreateVideoCapturer().
82 webrtc::ScreenCapturer* CreateVideoCapturer();
84 // Notifies the client session that the client connection has been
85 // authenticated and channels have been connected. This effectively enables
86 // the input pipe line and starts video capturing.
87 void ConnectClientSession();
89 // Invoked when the last reference to the AutoThreadTaskRunner has been
90 // released and quits the message loop to finish the test.
91 void QuitMainMessageLoop();
93 // Message loop passed to |client_session_| to perform all functions on.
94 base::MessageLoop message_loop_;
96 // ClientSession instance under test.
97 scoped_ptr<ClientSession> client_session_;
99 // ClientSession::EventHandler mock for use in tests.
100 MockClientSessionEventHandler session_event_handler_;
102 // Storage for values to be returned by the protocol::Session mock.
103 SessionConfig session_config_;
104 const std::string client_jid_;
106 // Stubs returned to |client_session_| components by |connection_|.
107 MockClientStub client_stub_;
108 MockVideoStub video_stub_;
110 // DesktopEnvironment owns |input_injector_|, but input injection tests need
111 // to express expectations on it.
112 scoped_ptr<MockInputInjector> input_injector_;
114 // ClientSession owns |connection_| but tests need it to inject fake events.
115 MockConnectionToClient* connection_;
117 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_;
120 void ClientSessionTest::SetUp() {
121 // Arrange to run |message_loop_| until no components depend on it.
122 scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
123 message_loop_.message_loop_proxy(),
124 base::Bind(&ClientSessionTest::QuitMainMessageLoop,
125 base::Unretained(this)));
127 desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
128 EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
129 .Times(AnyNumber())
130 .WillRepeatedly(Invoke(this,
131 &ClientSessionTest::CreateDesktopEnvironment));
132 EXPECT_CALL(*desktop_environment_factory_, SupportsAudioCapture())
133 .Times(AnyNumber())
134 .WillRepeatedly(Return(false));
136 input_injector_.reset(new MockInputInjector());
138 session_config_ = SessionConfig::ForTest();
140 // Mock protocol::Session APIs called directly by ClientSession.
141 protocol::MockSession* session = new MockSession();
142 EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_));
143 EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_));
144 EXPECT_CALL(*session, SetEventHandler(_));
146 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
147 // HostStub is not touched by ClientSession, so we can safely pass NULL.
148 scoped_ptr<MockConnectionToClient> connection(
149 new MockConnectionToClient(session, NULL));
150 EXPECT_CALL(*connection, session()).WillRepeatedly(Return(session));
151 EXPECT_CALL(*connection, client_stub())
152 .WillRepeatedly(Return(&client_stub_));
153 EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_));
154 EXPECT_CALL(*connection, Disconnect());
155 connection_ = connection.get();
157 client_session_.reset(new ClientSession(
158 &session_event_handler_,
159 ui_task_runner, // Audio thread.
160 ui_task_runner, // Input thread.
161 ui_task_runner, // Capture thread.
162 ui_task_runner, // Encode thread.
163 ui_task_runner, // Network thread.
164 ui_task_runner, // UI thread.
165 connection.PassAs<protocol::ConnectionToClient>(),
166 desktop_environment_factory_.get(),
167 base::TimeDelta(),
168 NULL));
171 void ClientSessionTest::TearDown() {
172 // Verify that the client session has been stopped.
173 EXPECT_TRUE(!client_session_);
176 void ClientSessionTest::DisconnectClientSession() {
177 client_session_->DisconnectSession();
178 // MockSession won't trigger OnConnectionClosed, so fake it.
179 client_session_->OnConnectionClosed(client_session_->connection(),
180 protocol::OK);
183 void ClientSessionTest::StopClientSession() {
184 client_session_.reset();
186 desktop_environment_factory_.reset();
189 DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
190 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
191 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
192 .Times(0);
193 EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
194 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector));
195 EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
196 .Times(AtMost(1));
197 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
198 .WillOnce(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
199 EXPECT_CALL(*desktop_environment, GetCapabilities())
200 .Times(AtMost(1));
201 EXPECT_CALL(*desktop_environment, SetCapabilities(_))
202 .Times(AtMost(1));
204 return desktop_environment;
207 InputInjector* ClientSessionTest::CreateInputInjector() {
208 EXPECT_TRUE(input_injector_);
209 return input_injector_.release();
212 webrtc::ScreenCapturer* ClientSessionTest::CreateVideoCapturer() {
213 return new ScreenCapturerFake();
216 void ClientSessionTest::ConnectClientSession() {
217 client_session_->OnConnectionAuthenticated(client_session_->connection());
218 client_session_->OnConnectionChannelsConnected(client_session_->connection());
221 void ClientSessionTest::QuitMainMessageLoop() {
222 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
225 MATCHER_P2(EqualsClipboardEvent, m, d, "") {
226 return (strcmp(arg.mime_type().c_str(), m) == 0 &&
227 memcmp(arg.data().data(), d, arg.data().size()) == 0);
230 TEST_F(ClientSessionTest, ClipboardStubFilter) {
231 protocol::ClipboardEvent clipboard_event1;
232 clipboard_event1.set_mime_type(kMimeTypeTextUtf8);
233 clipboard_event1.set_data("a");
235 protocol::ClipboardEvent clipboard_event2;
236 clipboard_event2.set_mime_type(kMimeTypeTextUtf8);
237 clipboard_event2.set_data("b");
239 protocol::ClipboardEvent clipboard_event3;
240 clipboard_event3.set_mime_type(kMimeTypeTextUtf8);
241 clipboard_event3.set_data("c");
243 Expectation authenticated =
244 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
245 .WillOnce(Return(true));
246 EXPECT_CALL(*input_injector_, StartPtr(_))
247 .After(authenticated);
248 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
249 .After(authenticated);
251 // Wait for the first video packet to be captured to make sure that
252 // the injected input will go though. Otherwise mouse events will be blocked
253 // by the mouse clamping filter.
254 Sequence s;
255 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
256 .InSequence(s)
257 .After(authenticated)
258 .WillOnce(DoAll(
259 // This event should get through to the clipboard stub.
260 InjectClipboardEvent(connection_, clipboard_event2),
261 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
262 // This event should not get through to the clipboard stub,
263 // because the client has disconnected.
264 InjectClipboardEvent(connection_, clipboard_event3),
265 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
266 EXPECT_CALL(*input_injector_, InjectClipboardEvent(EqualsClipboardEvent(
267 kMimeTypeTextUtf8, "b")))
268 .InSequence(s);
269 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
270 .InSequence(s);
272 // This event should not get through to the clipboard stub,
273 // because the client isn't authenticated yet.
274 connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event1);
276 ConnectClientSession();
277 message_loop_.Run();
280 namespace {
282 MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") {
283 return arg.usb_keycode() == (unsigned int)usb_keycode &&
284 arg.pressed() == pressed;
287 MATCHER_P2(EqualsMouseEvent, x, y, "") {
288 return arg.x() == x && arg.y() == y;
291 MATCHER_P2(EqualsMouseButtonEvent, button, down, "") {
292 return arg.button() == button && arg.button_down() == down;
297 TEST_F(ClientSessionTest, InputStubFilter) {
298 protocol::KeyEvent key_event1;
299 key_event1.set_pressed(true);
300 key_event1.set_usb_keycode(1);
302 protocol::KeyEvent key_event2_down;
303 key_event2_down.set_pressed(true);
304 key_event2_down.set_usb_keycode(2);
306 protocol::KeyEvent key_event2_up;
307 key_event2_up.set_pressed(false);
308 key_event2_up.set_usb_keycode(2);
310 protocol::KeyEvent key_event3;
311 key_event3.set_pressed(true);
312 key_event3.set_usb_keycode(3);
314 protocol::MouseEvent mouse_event1;
315 mouse_event1.set_x(100);
316 mouse_event1.set_y(101);
318 protocol::MouseEvent mouse_event2;
319 mouse_event2.set_x(200);
320 mouse_event2.set_y(201);
322 protocol::MouseEvent mouse_event3;
323 mouse_event3.set_x(300);
324 mouse_event3.set_y(301);
326 Expectation authenticated =
327 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
328 .WillOnce(Return(true));
329 EXPECT_CALL(*input_injector_, StartPtr(_))
330 .After(authenticated);
331 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
332 .After(authenticated);
334 // Wait for the first video packet to be captured to make sure that
335 // the injected input will go though. Otherwise mouse events will be blocked
336 // by the mouse clamping filter.
337 Sequence s;
338 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
339 .InSequence(s)
340 .After(authenticated)
341 .WillOnce(DoAll(
342 // These events should get through to the input stub.
343 InjectKeyEvent(connection_, key_event2_down),
344 InjectKeyEvent(connection_, key_event2_up),
345 InjectMouseEvent(connection_, mouse_event2),
346 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
347 // These events should not get through to the input stub,
348 // because the client has disconnected.
349 InjectKeyEvent(connection_, key_event3),
350 InjectMouseEvent(connection_, mouse_event3),
351 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
352 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
353 .InSequence(s);
354 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
355 .InSequence(s);
356 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
357 .InSequence(s);
358 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
359 .InSequence(s);
361 // These events should not get through to the input stub,
362 // because the client isn't authenticated yet.
363 connection_->input_stub()->InjectKeyEvent(key_event1);
364 connection_->input_stub()->InjectMouseEvent(mouse_event1);
366 ConnectClientSession();
367 message_loop_.Run();
370 TEST_F(ClientSessionTest, LocalInputTest) {
371 protocol::MouseEvent mouse_event1;
372 mouse_event1.set_x(100);
373 mouse_event1.set_y(101);
374 protocol::MouseEvent mouse_event2;
375 mouse_event2.set_x(200);
376 mouse_event2.set_y(201);
377 protocol::MouseEvent mouse_event3;
378 mouse_event3.set_x(300);
379 mouse_event3.set_y(301);
381 Expectation authenticated =
382 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
383 .WillOnce(Return(true));
384 EXPECT_CALL(*input_injector_, StartPtr(_))
385 .After(authenticated);
386 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
387 .After(authenticated);
389 // Wait for the first video packet to be captured to make sure that
390 // the injected input will go though. Otherwise mouse events will be blocked
391 // by the mouse clamping filter.
392 Sequence s;
393 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
394 .InSequence(s)
395 .After(authenticated)
396 .WillOnce(DoAll(
397 // This event should get through to the input stub.
398 InjectMouseEvent(connection_, mouse_event1),
399 #if !defined(OS_WIN)
400 // The OS echoes the injected event back.
401 LocalMouseMoved(client_session_.get(), mouse_event1),
402 #endif // !defined(OS_WIN)
403 // This one should get throught as well.
404 InjectMouseEvent(connection_, mouse_event2),
405 // Now this is a genuine local event.
406 LocalMouseMoved(client_session_.get(), mouse_event1),
407 // This one should be blocked because of the previous local input
408 // event.
409 InjectMouseEvent(connection_, mouse_event3),
410 // TODO(jamiewalch): Verify that remote inputs are re-enabled
411 // eventually (via dependency injection, not sleep!)
412 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
413 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
414 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(100, 101)))
415 .InSequence(s);
416 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
417 .InSequence(s);
418 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
419 .InSequence(s);
421 ConnectClientSession();
422 message_loop_.Run();
425 TEST_F(ClientSessionTest, RestoreEventState) {
426 protocol::KeyEvent key1;
427 key1.set_pressed(true);
428 key1.set_usb_keycode(1);
430 protocol::KeyEvent key2;
431 key2.set_pressed(true);
432 key2.set_usb_keycode(2);
434 protocol::MouseEvent mousedown;
435 mousedown.set_button(protocol::MouseEvent::BUTTON_LEFT);
436 mousedown.set_button_down(true);
438 Expectation authenticated =
439 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
440 .WillOnce(Return(true));
441 EXPECT_CALL(*input_injector_, StartPtr(_))
442 .After(authenticated);
443 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
444 .After(authenticated);
446 // Wait for the first video packet to be captured to make sure that
447 // the injected input will go though. Otherwise mouse events will be blocked
448 // by the mouse clamping filter.
449 Sequence s;
450 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
451 .InSequence(s)
452 .After(authenticated)
453 .WillOnce(DoAll(
454 InjectKeyEvent(connection_, key1),
455 InjectKeyEvent(connection_, key2),
456 InjectMouseEvent(connection_, mousedown),
457 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
458 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
459 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, true)))
460 .InSequence(s);
461 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
462 .InSequence(s);
463 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
464 protocol::MouseEvent::BUTTON_LEFT, true)))
465 .InSequence(s);
466 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, false)))
467 .InSequence(s);
468 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
469 .InSequence(s);
470 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
471 protocol::MouseEvent::BUTTON_LEFT, false)))
472 .InSequence(s);
473 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
474 .InSequence(s);
476 ConnectClientSession();
477 message_loop_.Run();
480 TEST_F(ClientSessionTest, ClampMouseEvents) {
481 Expectation authenticated =
482 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
483 .WillOnce(Return(true));
484 EXPECT_CALL(*input_injector_, StartPtr(_))
485 .After(authenticated);
486 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
487 .After(authenticated);
488 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
489 .After(authenticated);
491 Expectation connected = authenticated;
493 int input_x[3] = { -999, 100, 999 };
494 int expected_x[3] = { 0, 100, ScreenCapturerFake::kWidth - 1 };
495 int input_y[3] = { -999, 50, 999 };
496 int expected_y[3] = { 0, 50, ScreenCapturerFake::kHeight - 1 };
498 protocol::MouseEvent expected_event;
499 for (int j = 0; j < 3; j++) {
500 for (int i = 0; i < 3; i++) {
501 protocol::MouseEvent injected_event;
502 injected_event.set_x(input_x[i]);
503 injected_event.set_y(input_y[j]);
505 if (i == 0 && j == 0) {
506 // Inject the 1st event once a video packet has been received.
507 connected =
508 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
509 .After(connected)
510 .WillOnce(InjectMouseEvent(connection_, injected_event));
511 } else {
512 // Every next event is injected once the previous event has been
513 // received.
514 connected =
515 EXPECT_CALL(*input_injector_,
516 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
517 expected_event.y())))
518 .After(connected)
519 .WillOnce(InjectMouseEvent(connection_, injected_event));
522 expected_event.set_x(expected_x[i]);
523 expected_event.set_y(expected_y[j]);
527 // Shutdown the connection once the last event has been received.
528 EXPECT_CALL(*input_injector_,
529 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
530 expected_event.y())))
531 .After(connected)
532 .WillOnce(DoAll(
533 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
534 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
536 ConnectClientSession();
537 message_loop_.Run();
540 } // namespace remoting