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.
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "remoting/base/auto_thread_task_runner.h"
14 #include "remoting/base/constants.h"
15 #include "remoting/host/audio_capturer.h"
16 #include "remoting/host/client_session.h"
17 #include "remoting/host/desktop_environment.h"
18 #include "remoting/host/fake_desktop_capturer.h"
19 #include "remoting/host/fake_host_extension.h"
20 #include "remoting/host/fake_mouse_cursor_monitor.h"
21 #include "remoting/host/host_extension.h"
22 #include "remoting/host/host_extension_session.h"
23 #include "remoting/host/host_mock_objects.h"
24 #include "remoting/protocol/protocol_mock_objects.h"
25 #include "testing/gmock/include/gmock/gmock-matchers.h"
26 #include "testing/gmock_mutant.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
29 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
30 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
34 using protocol::MockConnectionToClient
;
35 using protocol::MockClientStub
;
36 using protocol::MockHostStub
;
37 using protocol::MockInputStub
;
38 using protocol::MockSession
;
39 using protocol::MockVideoStub
;
40 using protocol::SessionConfig
;
43 using testing::AnyNumber
;
44 using testing::AtMost
;
45 using testing::CreateFunctor
;
46 using testing::DeleteArg
;
48 using testing::Expectation
;
49 using testing::Invoke
;
50 using testing::Return
;
51 using testing::ReturnRef
;
52 using testing::Sequence
;
54 using testing::StrictMock
;
58 const char kDefaultTestCapability
[] = "default";
60 ACTION_P2(InjectClipboardEvent
, connection
, event
) {
61 connection
->clipboard_stub()->InjectClipboardEvent(event
);
64 ACTION_P2(InjectKeyEvent
, connection
, event
) {
65 connection
->input_stub()->InjectKeyEvent(event
);
68 ACTION_P2(InjectMouseEvent
, connection
, event
) {
69 connection
->input_stub()->InjectMouseEvent(event
);
72 ACTION_P2(LocalMouseMoved
, client_session
, event
) {
73 client_session
->OnLocalMouseMoved(
74 webrtc::DesktopVector(event
.x(), event
.y()));
77 ACTION_P2(SetGnubbyAuthHandlerForTesting
, client_session
, gnubby_auth_handler
) {
78 client_session
->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler
);
81 ACTION_P2(DeliverClientMessage
, client_session
, message
) {
82 client_session
->DeliverClientMessage(message
);
85 ACTION_P2(SetCapabilities
, client_session
, capabilities
) {
86 protocol::Capabilities capabilities_message
;
87 capabilities_message
.set_capabilities(capabilities
);
88 client_session
->SetCapabilities(capabilities_message
);
91 MATCHER_P2(EqualsUsbEvent
, usb_keycode
, pressed
, "") {
92 return arg
.usb_keycode() == (unsigned int)usb_keycode
&&
93 arg
.pressed() == pressed
;
96 MATCHER_P2(EqualsMouseEvent
, x
, y
, "") {
97 return arg
.x() == x
&& arg
.y() == y
;
100 MATCHER_P2(EqualsMouseButtonEvent
, button
, down
, "") {
101 return arg
.button() == button
&& arg
.button_down() == down
;
104 // Matches a |protocol::Capabilities| argument against a list of capabilities
105 // formatted as a space-separated string.
106 MATCHER_P(EqCapabilities
, expected_capabilities
, "") {
107 if (!arg
.has_capabilities())
110 std::vector
<std::string
> words_args
;
111 std::vector
<std::string
> words_expected
;
112 Tokenize(arg
.capabilities(), " ", &words_args
);
113 Tokenize(expected_capabilities
, " ", &words_expected
);
114 std::sort(words_args
.begin(), words_args
.end());
115 std::sort(words_expected
.begin(), words_expected
.end());
116 return words_args
== words_expected
;
121 class ClientSessionTest
: public testing::Test
{
123 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
125 virtual void SetUp() OVERRIDE
;
126 virtual void TearDown() OVERRIDE
;
128 // Creates the client session.
129 void CreateClientSession();
131 // Disconnects the client session.
132 void DisconnectClientSession();
134 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
135 void StopClientSession();
138 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
139 // DesktopEnvironmentFactory::Create().
140 DesktopEnvironment
* CreateDesktopEnvironment();
142 // Returns |input_injector_| created and initialized by SetUp(), to mock
143 // DesktopEnvironment::CreateInputInjector().
144 InputInjector
* CreateInputInjector();
146 // Creates a fake webrtc::DesktopCapturer, to mock
147 // DesktopEnvironment::CreateVideoCapturer().
148 webrtc::DesktopCapturer
* CreateVideoCapturer();
150 // Creates a MockMouseCursorMonitor, to mock
151 // DesktopEnvironment::CreateMouseCursorMonitor
152 webrtc::MouseCursorMonitor
* CreateMouseCursorMonitor();
154 // Notifies the client session that the client connection has been
155 // authenticated and channels have been connected. This effectively enables
156 // the input pipe line and starts video capturing.
157 void ConnectClientSession();
159 // Creates expectation that simulates client supporting same capabilities as
161 void SetMatchCapabilitiesExpectation();
163 // Creates expectations to send an extension message and to disconnect
165 void SetSendMessageAndDisconnectExpectation(const std::string
& message_type
);
167 // Message loop that will process all ClientSession tasks.
168 base::MessageLoop message_loop_
;
170 // AutoThreadTaskRunner on which |client_session_| will be run.
171 scoped_refptr
<AutoThreadTaskRunner
> task_runner_
;
173 // Used to run |message_loop_| after each test, until no objects remain that
175 base::RunLoop run_loop_
;
177 // HostExtensions to pass when creating the ClientSession. Caller retains
178 // ownership of the HostExtensions themselves.
179 std::vector
<HostExtension
*> extensions_
;
181 // ClientSession instance under test.
182 scoped_ptr
<ClientSession
> client_session_
;
184 // ClientSession::EventHandler mock for use in tests.
185 MockClientSessionEventHandler session_event_handler_
;
187 // Storage for values to be returned by the protocol::Session mock.
188 SessionConfig session_config_
;
189 const std::string client_jid_
;
191 // Stubs returned to |client_session_| components by |connection_|.
192 MockClientStub client_stub_
;
193 MockVideoStub video_stub_
;
195 // DesktopEnvironment owns |input_injector_|, but input injection tests need
196 // to express expectations on it.
197 scoped_ptr
<MockInputInjector
> input_injector_
;
199 // ClientSession owns |connection_| but tests need it to inject fake events.
200 MockConnectionToClient
* connection_
;
202 scoped_ptr
<MockDesktopEnvironmentFactory
> desktop_environment_factory_
;
205 void ClientSessionTest::SetUp() {
206 // Arrange to run |message_loop_| until no components depend on it.
207 task_runner_
= new AutoThreadTaskRunner(
208 message_loop_
.message_loop_proxy(), run_loop_
.QuitClosure());
210 desktop_environment_factory_
.reset(new MockDesktopEnvironmentFactory());
211 EXPECT_CALL(*desktop_environment_factory_
, CreatePtr())
213 .WillRepeatedly(Invoke(this,
214 &ClientSessionTest::CreateDesktopEnvironment
));
215 EXPECT_CALL(*desktop_environment_factory_
, SupportsAudioCapture())
217 .WillRepeatedly(Return(false));
219 input_injector_
.reset(new MockInputInjector());
221 session_config_
= SessionConfig::ForTest();
224 void ClientSessionTest::TearDown() {
225 // Clear out |task_runner_| reference so the loop can quit, and run it until
231 void ClientSessionTest::CreateClientSession() {
232 // Mock protocol::Session APIs called directly by ClientSession.
233 protocol::MockSession
* session
= new MockSession();
234 EXPECT_CALL(*session
, config()).WillRepeatedly(ReturnRef(session_config_
));
235 EXPECT_CALL(*session
, jid()).WillRepeatedly(ReturnRef(client_jid_
));
236 EXPECT_CALL(*session
, SetEventHandler(_
));
238 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
239 // HostStub is not touched by ClientSession, so we can safely pass NULL.
240 scoped_ptr
<MockConnectionToClient
> connection(
241 new MockConnectionToClient(session
, NULL
));
242 EXPECT_CALL(*connection
, session()).WillRepeatedly(Return(session
));
243 EXPECT_CALL(*connection
, client_stub())
244 .WillRepeatedly(Return(&client_stub_
));
245 EXPECT_CALL(*connection
, video_stub()).WillRepeatedly(Return(&video_stub_
));
246 EXPECT_CALL(*connection
, Disconnect());
247 connection_
= connection
.get();
249 client_session_
.reset(new ClientSession(
250 &session_event_handler_
,
251 task_runner_
, // Audio thread.
252 task_runner_
, // Input thread.
253 task_runner_
, // Capture thread.
254 task_runner_
, // Encode thread.
255 task_runner_
, // Network thread.
256 task_runner_
, // UI thread.
257 connection
.PassAs
<protocol::ConnectionToClient
>(),
258 desktop_environment_factory_
.get(),
264 void ClientSessionTest::DisconnectClientSession() {
265 client_session_
->DisconnectSession();
266 // MockSession won't trigger OnConnectionClosed, so fake it.
267 client_session_
->OnConnectionClosed(client_session_
->connection(),
271 void ClientSessionTest::StopClientSession() {
272 client_session_
.reset();
274 desktop_environment_factory_
.reset();
277 DesktopEnvironment
* ClientSessionTest::CreateDesktopEnvironment() {
278 MockDesktopEnvironment
* desktop_environment
= new MockDesktopEnvironment();
279 EXPECT_CALL(*desktop_environment
, CreateAudioCapturerPtr())
281 EXPECT_CALL(*desktop_environment
, CreateInputInjectorPtr())
282 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector
));
283 EXPECT_CALL(*desktop_environment
, CreateScreenControlsPtr())
285 EXPECT_CALL(*desktop_environment
, CreateVideoCapturerPtr())
286 .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer
));
287 EXPECT_CALL(*desktop_environment
, CreateMouseCursorMonitorPtr())
289 Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor
));
290 EXPECT_CALL(*desktop_environment
, GetCapabilities())
292 .WillOnce(Return(kDefaultTestCapability
));
293 EXPECT_CALL(*desktop_environment
, SetCapabilities(_
))
296 return desktop_environment
;
299 InputInjector
* ClientSessionTest::CreateInputInjector() {
300 EXPECT_TRUE(input_injector_
);
301 return input_injector_
.release();
304 webrtc::DesktopCapturer
* ClientSessionTest::CreateVideoCapturer() {
305 return new FakeDesktopCapturer();
308 webrtc::MouseCursorMonitor
* ClientSessionTest::CreateMouseCursorMonitor() {
309 return new FakeMouseCursorMonitor();
312 void ClientSessionTest::ConnectClientSession() {
313 client_session_
->OnConnectionAuthenticated(client_session_
->connection());
314 client_session_
->OnConnectionChannelsConnected(client_session_
->connection());
317 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
318 // Set the client to report the same capabilities as the host.
319 EXPECT_CALL(client_stub_
, SetCapabilities(_
))
321 .WillOnce(Invoke(client_session_
.get(), &ClientSession::SetCapabilities
));
324 void ClientSessionTest::SetSendMessageAndDisconnectExpectation(
325 const std::string
& message_type
) {
326 protocol::ExtensionMessage message
;
327 message
.set_type(message_type
);
328 message
.set_data("data");
330 Expectation authenticated
=
331 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
332 .WillOnce(Return(true));
333 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
334 .After(authenticated
)
336 DeliverClientMessage(client_session_
.get(), message
),
337 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
338 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
341 MATCHER_P2(EqualsClipboardEvent
, m
, d
, "") {
342 return (strcmp(arg
.mime_type().c_str(), m
) == 0 &&
343 memcmp(arg
.data().data(), d
, arg
.data().size()) == 0);
346 TEST_F(ClientSessionTest
, ClipboardStubFilter
) {
347 CreateClientSession();
349 protocol::ClipboardEvent clipboard_event1
;
350 clipboard_event1
.set_mime_type(kMimeTypeTextUtf8
);
351 clipboard_event1
.set_data("a");
353 protocol::ClipboardEvent clipboard_event2
;
354 clipboard_event2
.set_mime_type(kMimeTypeTextUtf8
);
355 clipboard_event2
.set_data("b");
357 protocol::ClipboardEvent clipboard_event3
;
358 clipboard_event3
.set_mime_type(kMimeTypeTextUtf8
);
359 clipboard_event3
.set_data("c");
361 Expectation authenticated
=
362 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
363 .WillOnce(Return(true));
364 EXPECT_CALL(*input_injector_
, StartPtr(_
))
365 .After(authenticated
);
366 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
367 .After(authenticated
);
369 // Wait for the first video packet to be captured to make sure that
370 // the injected input will go though. Otherwise mouse events will be blocked
371 // by the mouse clamping filter.
373 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
375 .After(authenticated
)
377 // This event should get through to the clipboard stub.
378 InjectClipboardEvent(connection_
, clipboard_event2
),
379 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
380 // This event should not get through to the clipboard stub,
381 // because the client has disconnected.
382 InjectClipboardEvent(connection_
, clipboard_event3
),
383 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
384 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
385 kMimeTypeTextUtf8
, "b")))
387 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
390 // This event should not get through to the clipboard stub,
391 // because the client isn't authenticated yet.
392 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event1
);
394 ConnectClientSession();
397 TEST_F(ClientSessionTest
, InputStubFilter
) {
398 CreateClientSession();
400 protocol::KeyEvent key_event1
;
401 key_event1
.set_pressed(true);
402 key_event1
.set_usb_keycode(1);
404 protocol::KeyEvent key_event2_down
;
405 key_event2_down
.set_pressed(true);
406 key_event2_down
.set_usb_keycode(2);
408 protocol::KeyEvent key_event2_up
;
409 key_event2_up
.set_pressed(false);
410 key_event2_up
.set_usb_keycode(2);
412 protocol::KeyEvent key_event3
;
413 key_event3
.set_pressed(true);
414 key_event3
.set_usb_keycode(3);
416 protocol::MouseEvent mouse_event1
;
417 mouse_event1
.set_x(100);
418 mouse_event1
.set_y(101);
420 protocol::MouseEvent mouse_event2
;
421 mouse_event2
.set_x(200);
422 mouse_event2
.set_y(201);
424 protocol::MouseEvent mouse_event3
;
425 mouse_event3
.set_x(300);
426 mouse_event3
.set_y(301);
428 Expectation authenticated
=
429 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
430 .WillOnce(Return(true));
431 EXPECT_CALL(*input_injector_
, StartPtr(_
))
432 .After(authenticated
);
433 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
434 .After(authenticated
);
436 // Wait for the first video packet to be captured to make sure that
437 // the injected input will go though. Otherwise mouse events will be blocked
438 // by the mouse clamping filter.
440 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
442 .After(authenticated
)
444 // These events should get through to the input stub.
445 InjectKeyEvent(connection_
, key_event2_down
),
446 InjectKeyEvent(connection_
, key_event2_up
),
447 InjectMouseEvent(connection_
, mouse_event2
),
448 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
449 // These events should not get through to the input stub,
450 // because the client has disconnected.
451 InjectKeyEvent(connection_
, key_event3
),
452 InjectMouseEvent(connection_
, mouse_event3
),
453 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
454 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, true)))
456 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, false)))
458 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(200, 201)))
460 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
463 // These events should not get through to the input stub,
464 // because the client isn't authenticated yet.
465 connection_
->input_stub()->InjectKeyEvent(key_event1
);
466 connection_
->input_stub()->InjectMouseEvent(mouse_event1
);
468 ConnectClientSession();
471 TEST_F(ClientSessionTest
, LocalInputTest
) {
472 CreateClientSession();
474 protocol::MouseEvent mouse_event1
;
475 mouse_event1
.set_x(100);
476 mouse_event1
.set_y(101);
477 protocol::MouseEvent mouse_event2
;
478 mouse_event2
.set_x(200);
479 mouse_event2
.set_y(201);
480 protocol::MouseEvent mouse_event3
;
481 mouse_event3
.set_x(300);
482 mouse_event3
.set_y(301);
484 Expectation authenticated
=
485 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
486 .WillOnce(Return(true));
487 EXPECT_CALL(*input_injector_
, StartPtr(_
))
488 .After(authenticated
);
489 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
490 .After(authenticated
);
492 // Wait for the first video packet to be captured to make sure that
493 // the injected input will go though. Otherwise mouse events will be blocked
494 // by the mouse clamping filter.
496 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
498 .After(authenticated
)
500 // This event should get through to the input stub.
501 InjectMouseEvent(connection_
, mouse_event1
),
503 // The OS echoes the injected event back.
504 LocalMouseMoved(client_session_
.get(), mouse_event1
),
505 #endif // !defined(OS_WIN)
506 // This one should get throught as well.
507 InjectMouseEvent(connection_
, mouse_event2
),
508 // Now this is a genuine local event.
509 LocalMouseMoved(client_session_
.get(), mouse_event1
),
510 // This one should be blocked because of the previous local input
512 InjectMouseEvent(connection_
, mouse_event3
),
513 // TODO(jamiewalch): Verify that remote inputs are re-enabled
514 // eventually (via dependency injection, not sleep!)
515 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
516 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
517 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(100, 101)))
519 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(200, 201)))
521 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
524 ConnectClientSession();
527 TEST_F(ClientSessionTest
, RestoreEventState
) {
528 CreateClientSession();
530 protocol::KeyEvent key1
;
531 key1
.set_pressed(true);
532 key1
.set_usb_keycode(1);
534 protocol::KeyEvent key2
;
535 key2
.set_pressed(true);
536 key2
.set_usb_keycode(2);
538 protocol::MouseEvent mousedown
;
539 mousedown
.set_button(protocol::MouseEvent::BUTTON_LEFT
);
540 mousedown
.set_button_down(true);
542 Expectation authenticated
=
543 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
544 .WillOnce(Return(true));
545 EXPECT_CALL(*input_injector_
, StartPtr(_
))
546 .After(authenticated
);
547 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
548 .After(authenticated
);
550 // Wait for the first video packet to be captured to make sure that
551 // the injected input will go though. Otherwise mouse events will be blocked
552 // by the mouse clamping filter.
554 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
556 .After(authenticated
)
558 InjectKeyEvent(connection_
, key1
),
559 InjectKeyEvent(connection_
, key2
),
560 InjectMouseEvent(connection_
, mousedown
),
561 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
562 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
563 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, true)))
565 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, true)))
567 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
568 protocol::MouseEvent::BUTTON_LEFT
, true)))
570 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, false)))
572 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, false)))
574 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
575 protocol::MouseEvent::BUTTON_LEFT
, false)))
577 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
580 ConnectClientSession();
583 TEST_F(ClientSessionTest
, ClampMouseEvents
) {
584 CreateClientSession();
586 Expectation authenticated
=
587 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
588 .WillOnce(Return(true));
589 EXPECT_CALL(*input_injector_
, StartPtr(_
))
590 .After(authenticated
);
591 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
592 .After(authenticated
);
593 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
594 .After(authenticated
);
596 Expectation connected
= authenticated
;
598 int input_x
[3] = { -999, 100, 999 };
599 int expected_x
[3] = { 0, 100, FakeDesktopCapturer::kWidth
- 1 };
600 int input_y
[3] = { -999, 50, 999 };
601 int expected_y
[3] = { 0, 50, FakeDesktopCapturer::kHeight
- 1 };
603 protocol::MouseEvent expected_event
;
604 for (int j
= 0; j
< 3; j
++) {
605 for (int i
= 0; i
< 3; i
++) {
606 protocol::MouseEvent injected_event
;
607 injected_event
.set_x(input_x
[i
]);
608 injected_event
.set_y(input_y
[j
]);
610 if (i
== 0 && j
== 0) {
611 // Inject the 1st event once a video packet has been received.
613 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
615 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
617 // Every next event is injected once the previous event has been
620 EXPECT_CALL(*input_injector_
,
621 InjectMouseEvent(EqualsMouseEvent(expected_event
.x(),
622 expected_event
.y())))
624 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
627 expected_event
.set_x(expected_x
[i
]);
628 expected_event
.set_y(expected_y
[j
]);
632 // Shutdown the connection once the last event has been received.
633 EXPECT_CALL(*input_injector_
,
634 InjectMouseEvent(EqualsMouseEvent(expected_event
.x(),
635 expected_event
.y())))
638 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
639 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
641 ConnectClientSession();
644 TEST_F(ClientSessionTest
, NoGnubbyAuth
) {
645 CreateClientSession();
647 protocol::ExtensionMessage message
;
648 message
.set_type("gnubby-auth");
649 message
.set_data("test");
651 Expectation authenticated
=
652 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
653 .WillOnce(Return(true));
654 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
655 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
656 .After(authenticated
)
658 DeliverClientMessage(client_session_
.get(), message
),
659 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
660 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
661 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
663 ConnectClientSession();
666 TEST_F(ClientSessionTest
, EnableGnubbyAuth
) {
667 CreateClientSession();
669 // Lifetime controlled by object under test.
670 MockGnubbyAuthHandler
* gnubby_auth_handler
= new MockGnubbyAuthHandler();
672 protocol::ExtensionMessage message
;
673 message
.set_type("gnubby-auth");
674 message
.set_data("test");
676 Expectation authenticated
=
677 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
678 .WillOnce(Return(true));
679 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
680 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
681 .After(authenticated
)
683 SetGnubbyAuthHandlerForTesting(client_session_
.get(),
684 gnubby_auth_handler
),
685 DeliverClientMessage(client_session_
.get(), message
),
686 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
687 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
688 EXPECT_CALL(*gnubby_auth_handler
, DeliverClientMessage(_
));
689 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
691 ConnectClientSession();
694 // Verifies that the client's video pipeline can be reset mid-session.
695 TEST_F(ClientSessionTest
, ResetVideoPipeline
) {
696 CreateClientSession();
698 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
699 .WillOnce(Return(true));
701 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
703 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
704 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
706 ConnectClientSession();
708 client_session_
->ResetVideoPipeline();
711 // Verifies that clients can have extensions registered, resulting in the
712 // correct capabilities being reported, and messages delivered correctly.
713 // The extension system is tested more extensively in the
714 // HostExtensionSessionManager unit-tests.
715 TEST_F(ClientSessionTest
, Extensions
) {
716 // Configure fake extensions for testing.
717 FakeExtension
extension1("ext1", "cap1");
718 extensions_
.push_back(&extension1
);
719 FakeExtension
extension2("ext2", "");
720 extensions_
.push_back(&extension2
);
721 FakeExtension
extension3("ext3", "cap3");
722 extensions_
.push_back(&extension3
);
724 // Set the second extension to request to modify the video pipeline.
725 extension2
.set_steal_video_capturer(true);
727 CreateClientSession();
729 Expectation authenticated
=
730 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
731 .WillOnce(Return(true));
733 // Verify that the ClientSession reports the correct capabilities, and mimic
734 // the client reporting an overlapping set of capabilities.
735 EXPECT_CALL(client_stub_
,
736 SetCapabilities(EqCapabilities("cap1 cap3 default")))
737 .After(authenticated
)
738 .WillOnce(SetCapabilities(client_session_
.get(), "cap1 cap4 default"));
740 // Verify that the correct extension messages are delivered, and dropped.
741 protocol::ExtensionMessage message1
;
742 message1
.set_type("ext1");
743 message1
.set_data("data");
744 protocol::ExtensionMessage message3
;
745 message3
.set_type("ext3");
746 message3
.set_data("data");
747 protocol::ExtensionMessage message4
;
748 message4
.set_type("ext4");
749 message4
.set_data("data");
750 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
752 DeliverClientMessage(client_session_
.get(), message1
),
753 DeliverClientMessage(client_session_
.get(), message3
),
754 DeliverClientMessage(client_session_
.get(), message4
),
755 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
756 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
758 // Simulate the ClientSession connect and extension negotiation.
759 ConnectClientSession();
760 base::RunLoop().RunUntilIdle();
762 // ext1 was instantiated and sent a message, and did not wrap anything.
763 EXPECT_TRUE(extension1
.was_instantiated());
764 EXPECT_TRUE(extension1
.has_handled_message());
765 EXPECT_FALSE(extension1
.has_wrapped_video_encoder());
767 // ext2 was instantiated but not sent a message, and wrapped video encoder.
768 EXPECT_TRUE(extension2
.was_instantiated());
769 EXPECT_FALSE(extension2
.has_handled_message());
770 EXPECT_TRUE(extension2
.has_wrapped_video_encoder());
772 // ext3 was sent a message but not instantiated.
773 EXPECT_FALSE(extension3
.was_instantiated());
776 // Verifies that an extension can "steal" the video capture, in which case no
777 // VideoScheduler is instantiated.
778 TEST_F(ClientSessionTest
, StealVideoCapturer
) {
779 FakeExtension
extension("ext1", "cap1");
780 extensions_
.push_back(&extension
);
782 CreateClientSession();
784 SetMatchCapabilitiesExpectation();
786 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
787 .WillOnce(Return(true));
789 ConnectClientSession();
791 base::RunLoop().RunUntilIdle();
793 extension
.set_steal_video_capturer(true);
794 client_session_
->ResetVideoPipeline();
796 base::RunLoop().RunUntilIdle();
798 // Verify that video control messages received while there is no video
799 // scheduler active won't crash things.
800 protocol::VideoControl video_control
;
801 video_control
.set_enable(false);
802 video_control
.set_lossless_encode(true);
803 video_control
.set_lossless_color(true);
804 client_session_
->ControlVideo(video_control
);
806 // TODO(wez): Find a way to verify that the ClientSession never captures any
807 // frames in this case.
809 DisconnectClientSession();
812 // ext1 was instantiated and wrapped the video capturer.
813 EXPECT_TRUE(extension
.was_instantiated());
814 EXPECT_TRUE(extension
.has_wrapped_video_capturer());
817 } // namespace remoting