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 "remoting/protocol/test_event_matchers.h"
26 #include "testing/gmock/include/gmock/gmock-matchers.h"
27 #include "testing/gmock_mutant.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
30 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
31 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
35 using protocol::MockClientStub
;
36 using protocol::MockConnectionToClient
;
37 using protocol::MockHostStub
;
38 using protocol::MockInputStub
;
39 using protocol::MockSession
;
40 using protocol::MockVideoStub
;
41 using protocol::SessionConfig
;
42 using protocol::test::EqualsClipboardEvent
;
43 using protocol::test::EqualsMouseButtonEvent
;
44 using protocol::test::EqualsMouseMoveEvent
;
45 using protocol::test::EqualsKeyEvent
;
48 using testing::AnyNumber
;
49 using testing::AtMost
;
50 using testing::AtLeast
;
51 using testing::CreateFunctor
;
52 using testing::DeleteArg
;
54 using testing::Expectation
;
55 using testing::Invoke
;
56 using testing::Return
;
57 using testing::ReturnRef
;
58 using testing::Sequence
;
60 using testing::StrictMock
;
64 const char kDefaultTestCapability
[] = "default";
66 ACTION_P2(InjectClipboardEvent
, connection
, event
) {
67 connection
->clipboard_stub()->InjectClipboardEvent(event
);
70 ACTION_P2(InjectKeyEvent
, connection
, event
) {
71 connection
->input_stub()->InjectKeyEvent(event
);
74 ACTION_P2(InjectMouseEvent
, connection
, event
) {
75 connection
->input_stub()->InjectMouseEvent(event
);
78 ACTION_P2(LocalMouseMoved
, client_session
, event
) {
79 client_session
->OnLocalMouseMoved(
80 webrtc::DesktopVector(event
.x(), event
.y()));
83 ACTION_P2(SetGnubbyAuthHandlerForTesting
, client_session
, gnubby_auth_handler
) {
84 client_session
->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler
);
87 ACTION_P2(DeliverClientMessage
, client_session
, message
) {
88 client_session
->DeliverClientMessage(message
);
91 ACTION_P2(SetCapabilities
, client_session
, capabilities
) {
92 protocol::Capabilities capabilities_message
;
93 capabilities_message
.set_capabilities(capabilities
);
94 client_session
->SetCapabilities(capabilities_message
);
97 // Matches a |protocol::Capabilities| argument against a list of capabilities
98 // formatted as a space-separated string.
99 MATCHER_P(EqCapabilities
, expected_capabilities
, "") {
100 if (!arg
.has_capabilities())
103 std::vector
<std::string
> words_args
;
104 std::vector
<std::string
> words_expected
;
105 Tokenize(arg
.capabilities(), " ", &words_args
);
106 Tokenize(expected_capabilities
, " ", &words_expected
);
107 std::sort(words_args
.begin(), words_args
.end());
108 std::sort(words_expected
.begin(), words_expected
.end());
109 return words_args
== words_expected
;
114 class ClientSessionTest
: public testing::Test
{
116 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
118 void SetUp() override
;
119 void TearDown() override
;
121 // Creates the client session.
122 void CreateClientSession();
124 // Disconnects the client session.
125 void DisconnectClientSession();
127 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
128 void StopClientSession();
131 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
132 // DesktopEnvironmentFactory::Create().
133 DesktopEnvironment
* CreateDesktopEnvironment();
135 // Returns |input_injector_| created and initialized by SetUp(), to mock
136 // DesktopEnvironment::CreateInputInjector().
137 InputInjector
* CreateInputInjector();
139 // Creates a fake webrtc::DesktopCapturer, to mock
140 // DesktopEnvironment::CreateVideoCapturer().
141 webrtc::DesktopCapturer
* CreateVideoCapturer();
143 // Creates a MockMouseCursorMonitor, to mock
144 // DesktopEnvironment::CreateMouseCursorMonitor
145 webrtc::MouseCursorMonitor
* CreateMouseCursorMonitor();
147 // Notifies the client session that the client connection has been
148 // authenticated and channels have been connected. This effectively enables
149 // the input pipe line and starts video capturing.
150 void ConnectClientSession();
152 // Creates expectation that simulates client supporting same capabilities as
154 void SetMatchCapabilitiesExpectation();
156 // Creates expectations to send an extension message and to disconnect
158 void SetSendMessageAndDisconnectExpectation(const std::string
& message_type
);
160 // Message loop that will process all ClientSession tasks.
161 base::MessageLoop message_loop_
;
163 // AutoThreadTaskRunner on which |client_session_| will be run.
164 scoped_refptr
<AutoThreadTaskRunner
> task_runner_
;
166 // Used to run |message_loop_| after each test, until no objects remain that
168 base::RunLoop run_loop_
;
170 // HostExtensions to pass when creating the ClientSession. Caller retains
171 // ownership of the HostExtensions themselves.
172 std::vector
<HostExtension
*> extensions_
;
174 // ClientSession instance under test.
175 scoped_ptr
<ClientSession
> client_session_
;
177 // ClientSession::EventHandler mock for use in tests.
178 MockClientSessionEventHandler session_event_handler_
;
180 // Storage for values to be returned by the protocol::Session mock.
181 scoped_ptr
<SessionConfig
> session_config_
;
182 const std::string client_jid_
;
184 // Stubs returned to |client_session_| components by |connection_|.
185 MockClientStub client_stub_
;
186 MockVideoStub video_stub_
;
188 // DesktopEnvironment owns |input_injector_|, but input injection tests need
189 // to express expectations on it.
190 scoped_ptr
<MockInputInjector
> input_injector_
;
192 // ClientSession owns |connection_| but tests need it to inject fake events.
193 MockConnectionToClient
* connection_
;
195 scoped_ptr
<MockDesktopEnvironmentFactory
> desktop_environment_factory_
;
198 void ClientSessionTest::SetUp() {
199 // Arrange to run |message_loop_| until no components depend on it.
200 task_runner_
= new AutoThreadTaskRunner(
201 message_loop_
.task_runner(), run_loop_
.QuitClosure());
203 desktop_environment_factory_
.reset(new MockDesktopEnvironmentFactory());
204 EXPECT_CALL(*desktop_environment_factory_
, CreatePtr())
206 .WillRepeatedly(Invoke(this,
207 &ClientSessionTest::CreateDesktopEnvironment
));
208 EXPECT_CALL(*desktop_environment_factory_
, SupportsAudioCapture())
210 .WillRepeatedly(Return(false));
212 input_injector_
.reset(new MockInputInjector());
214 session_config_
= SessionConfig::ForTest();
217 void ClientSessionTest::TearDown() {
218 // Clear out |task_runner_| reference so the loop can quit, and run it until
220 task_runner_
= nullptr;
224 void ClientSessionTest::CreateClientSession() {
225 // Mock protocol::Session APIs called directly by ClientSession.
226 protocol::MockSession
* session
= new MockSession();
227 EXPECT_CALL(*session
, config()).WillRepeatedly(ReturnRef(*session_config_
));
228 EXPECT_CALL(*session
, jid()).WillRepeatedly(ReturnRef(client_jid_
));
229 EXPECT_CALL(*session
, SetEventHandler(_
));
231 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
232 // HostStub is not touched by ClientSession, so we can safely pass nullptr.
233 scoped_ptr
<MockConnectionToClient
> connection(
234 new MockConnectionToClient(session
, nullptr));
235 EXPECT_CALL(*connection
, session()).WillRepeatedly(Return(session
));
236 EXPECT_CALL(*connection
, client_stub())
237 .WillRepeatedly(Return(&client_stub_
));
238 EXPECT_CALL(*connection
, video_stub()).WillRepeatedly(Return(&video_stub_
));
239 EXPECT_CALL(*connection
, Disconnect());
240 connection_
= connection
.get();
242 client_session_
.reset(new ClientSession(
243 &session_event_handler_
,
244 task_runner_
, // Audio thread.
245 task_runner_
, // Input thread.
246 task_runner_
, // Capture thread.
247 task_runner_
, // Encode thread.
248 task_runner_
, // Network thread.
249 task_runner_
, // UI thread.
251 desktop_environment_factory_
.get(),
257 void ClientSessionTest::DisconnectClientSession() {
258 client_session_
->DisconnectSession();
259 // MockSession won't trigger OnConnectionClosed, so fake it.
260 client_session_
->OnConnectionClosed(client_session_
->connection(),
264 void ClientSessionTest::StopClientSession() {
265 client_session_
.reset();
267 desktop_environment_factory_
.reset();
270 DesktopEnvironment
* ClientSessionTest::CreateDesktopEnvironment() {
271 MockDesktopEnvironment
* desktop_environment
= new MockDesktopEnvironment();
272 EXPECT_CALL(*desktop_environment
, CreateAudioCapturerPtr())
274 EXPECT_CALL(*desktop_environment
, CreateInputInjectorPtr())
275 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector
));
276 EXPECT_CALL(*desktop_environment
, CreateScreenControlsPtr())
278 EXPECT_CALL(*desktop_environment
, CreateVideoCapturerPtr())
279 .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer
));
280 EXPECT_CALL(*desktop_environment
, CreateMouseCursorMonitorPtr())
282 Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor
));
283 EXPECT_CALL(*desktop_environment
, GetCapabilities())
285 .WillOnce(Return(kDefaultTestCapability
));
286 EXPECT_CALL(*desktop_environment
, SetCapabilities(_
))
289 return desktop_environment
;
292 InputInjector
* ClientSessionTest::CreateInputInjector() {
293 EXPECT_TRUE(input_injector_
);
294 return input_injector_
.release();
297 webrtc::DesktopCapturer
* ClientSessionTest::CreateVideoCapturer() {
298 return new FakeDesktopCapturer();
301 webrtc::MouseCursorMonitor
* ClientSessionTest::CreateMouseCursorMonitor() {
302 return new FakeMouseCursorMonitor();
305 void ClientSessionTest::ConnectClientSession() {
306 // Stubs should be set only after connection is authenticated.
307 EXPECT_FALSE(connection_
->clipboard_stub());
308 EXPECT_FALSE(connection_
->input_stub());
310 client_session_
->OnConnectionAuthenticated(client_session_
->connection());
312 EXPECT_TRUE(connection_
->clipboard_stub());
313 EXPECT_TRUE(connection_
->input_stub());
315 client_session_
->OnConnectionChannelsConnected(client_session_
->connection());
318 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
319 // Set the client to report the same capabilities as the host.
320 EXPECT_CALL(client_stub_
, SetCapabilities(_
))
322 .WillOnce(Invoke(client_session_
.get(), &ClientSession::SetCapabilities
));
325 void ClientSessionTest::SetSendMessageAndDisconnectExpectation(
326 const std::string
& message_type
) {
327 protocol::ExtensionMessage message
;
328 message
.set_type(message_type
);
329 message
.set_data("data");
331 Expectation authenticated
=
332 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
333 .WillOnce(Return(true));
334 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
335 .After(authenticated
)
337 DeliverClientMessage(client_session_
.get(), message
),
338 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
339 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
342 TEST_F(ClientSessionTest
, ClipboardStubFilter
) {
343 CreateClientSession();
345 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
346 .WillOnce(Return(true));
347 EXPECT_CALL(*input_injector_
, StartPtr(_
));
348 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
));
350 // Wait for the first video packet to be captured to make sure that
351 // the injected input will go though. Otherwise mouse events will be blocked
352 // by the mouse clamping filter.
353 base::RunLoop run_loop
;
354 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
356 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
359 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
360 kMimeTypeTextUtf8
, "a")));
361 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, true)));
362 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, false)));
363 EXPECT_CALL(*input_injector_
,
364 InjectMouseEvent(EqualsMouseMoveEvent(100, 101)));
366 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
367 kMimeTypeTextUtf8
, "c")));
368 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(3, true)));
369 EXPECT_CALL(*input_injector_
,
370 InjectMouseEvent(EqualsMouseMoveEvent(300, 301)));
371 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(3, false)));
374 ConnectClientSession();
376 // Wait for the first frame.
379 // Inject test events that are expected to be injected.
380 protocol::ClipboardEvent clipboard_event
;
381 clipboard_event
.set_mime_type(kMimeTypeTextUtf8
);
382 clipboard_event
.set_data("a");
383 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
385 protocol::KeyEvent key_event
;
386 key_event
.set_pressed(true);
387 key_event
.set_usb_keycode(1);
388 connection_
->input_stub()->InjectKeyEvent(key_event
);
390 protocol::MouseEvent mouse_event
;
391 mouse_event
.set_x(100);
392 mouse_event
.set_y(101);
393 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
395 base::RunLoop().RunUntilIdle();
398 client_session_
->SetDisableInputs(true);
400 // These event shouldn't get though to the input injector.
401 clipboard_event
.set_data("b");
402 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
404 key_event
.set_pressed(true);
405 key_event
.set_usb_keycode(2);
406 connection_
->input_stub()->InjectKeyEvent(key_event
);
407 key_event
.set_pressed(false);
408 key_event
.set_usb_keycode(2);
409 connection_
->input_stub()->InjectKeyEvent(key_event
);
411 mouse_event
.set_x(200);
412 mouse_event
.set_y(201);
413 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
415 base::RunLoop().RunUntilIdle();
417 // Enable input again.
418 client_session_
->SetDisableInputs(false);
420 clipboard_event
.set_data("c");
421 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
422 base::RunLoop().RunUntilIdle();
424 key_event
.set_pressed(true);
425 key_event
.set_usb_keycode(3);
426 connection_
->input_stub()->InjectKeyEvent(key_event
);
428 mouse_event
.set_x(300);
429 mouse_event
.set_y(301);
430 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
432 client_session_
->DisconnectSession();
433 client_session_
->OnConnectionClosed(connection_
, protocol::OK
);
434 client_session_
.reset();
437 TEST_F(ClientSessionTest
, LocalInputTest
) {
438 CreateClientSession();
440 protocol::MouseEvent mouse_event1
;
441 mouse_event1
.set_x(100);
442 mouse_event1
.set_y(101);
443 protocol::MouseEvent mouse_event2
;
444 mouse_event2
.set_x(200);
445 mouse_event2
.set_y(201);
446 protocol::MouseEvent mouse_event3
;
447 mouse_event3
.set_x(300);
448 mouse_event3
.set_y(301);
450 Expectation authenticated
=
451 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
452 .WillOnce(Return(true));
453 EXPECT_CALL(*input_injector_
, StartPtr(_
))
454 .After(authenticated
);
455 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
456 .After(authenticated
);
458 // Wait for the first video packet to be captured to make sure that
459 // the injected input will go though. Otherwise mouse events will be blocked
460 // by the mouse clamping filter.
462 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
464 .After(authenticated
)
466 // This event should get through to the input stub.
467 InjectMouseEvent(connection_
, mouse_event1
),
469 // The OS echoes the injected event back.
470 LocalMouseMoved(client_session_
.get(), mouse_event1
),
471 #endif // !defined(OS_WIN)
472 // This one should get throught as well.
473 InjectMouseEvent(connection_
, mouse_event2
),
474 // Now this is a genuine local event.
475 LocalMouseMoved(client_session_
.get(), mouse_event1
),
476 // This one should be blocked because of the previous local input
478 InjectMouseEvent(connection_
, mouse_event3
),
479 // TODO(jamiewalch): Verify that remote inputs are re-enabled
480 // eventually (via dependency injection, not sleep!)
481 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
482 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
483 EXPECT_CALL(*input_injector_
,
484 InjectMouseEvent(EqualsMouseMoveEvent(100, 101))).InSequence(s
);
485 EXPECT_CALL(*input_injector_
,
486 InjectMouseEvent(EqualsMouseMoveEvent(200, 201))).InSequence(s
);
487 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).InSequence(s
);
489 ConnectClientSession();
492 TEST_F(ClientSessionTest
, RestoreEventState
) {
493 CreateClientSession();
495 protocol::KeyEvent key1
;
496 key1
.set_pressed(true);
497 key1
.set_usb_keycode(1);
499 protocol::KeyEvent key2
;
500 key2
.set_pressed(true);
501 key2
.set_usb_keycode(2);
503 protocol::MouseEvent mousedown
;
504 mousedown
.set_button(protocol::MouseEvent::BUTTON_LEFT
);
505 mousedown
.set_button_down(true);
507 Expectation authenticated
=
508 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
509 .WillOnce(Return(true));
510 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
511 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
512 .After(authenticated
);
514 // Wait for the first video packet to be captured to make sure that
515 // the injected input will go though. Otherwise mouse events will be blocked
516 // by the mouse clamping filter.
518 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
520 .After(authenticated
)
522 InjectKeyEvent(connection_
, key1
), InjectKeyEvent(connection_
, key2
),
523 InjectMouseEvent(connection_
, mousedown
),
524 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
525 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
526 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, true)))
528 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(2, true)))
530 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
531 protocol::MouseEvent::BUTTON_LEFT
, true)))
533 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, false)))
535 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(2, false)))
537 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
538 protocol::MouseEvent::BUTTON_LEFT
, false)))
540 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).InSequence(s
);
542 ConnectClientSession();
545 TEST_F(ClientSessionTest
, ClampMouseEvents
) {
546 CreateClientSession();
548 Expectation authenticated
=
549 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
550 .WillOnce(Return(true));
551 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
552 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
553 .After(authenticated
);
554 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).After(authenticated
);
556 Expectation connected
= authenticated
;
558 int input_x
[3] = { -999, 100, 999 };
559 int expected_x
[3] = { 0, 100, FakeDesktopCapturer::kWidth
- 1 };
560 int input_y
[3] = { -999, 50, 999 };
561 int expected_y
[3] = { 0, 50, FakeDesktopCapturer::kHeight
- 1 };
563 protocol::MouseEvent expected_event
;
564 for (int j
= 0; j
< 3; j
++) {
565 for (int i
= 0; i
< 3; i
++) {
566 protocol::MouseEvent injected_event
;
567 injected_event
.set_x(input_x
[i
]);
568 injected_event
.set_y(input_y
[j
]);
570 if (i
== 0 && j
== 0) {
571 // Inject the 1st event once a video packet has been received.
573 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
575 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
577 // Every next event is injected once the previous event has been
580 EXPECT_CALL(*input_injector_
,
581 InjectMouseEvent(EqualsMouseMoveEvent(
582 expected_event
.x(), expected_event
.y())))
584 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
587 expected_event
.set_x(expected_x
[i
]);
588 expected_event
.set_y(expected_y
[j
]);
592 // Shutdown the connection once the last event has been received.
593 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseMoveEvent(
594 expected_event
.x(), expected_event
.y())))
597 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
598 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
600 ConnectClientSession();
603 TEST_F(ClientSessionTest
, NoGnubbyAuth
) {
604 CreateClientSession();
606 protocol::ExtensionMessage message
;
607 message
.set_type("gnubby-auth");
608 message
.set_data("test");
610 Expectation authenticated
=
611 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
612 .WillOnce(Return(true));
613 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
614 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
615 .After(authenticated
)
617 DeliverClientMessage(client_session_
.get(), message
),
618 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
619 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
620 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
622 ConnectClientSession();
625 TEST_F(ClientSessionTest
, EnableGnubbyAuth
) {
626 CreateClientSession();
628 // Lifetime controlled by object under test.
629 MockGnubbyAuthHandler
* gnubby_auth_handler
= new MockGnubbyAuthHandler();
631 protocol::ExtensionMessage message
;
632 message
.set_type("gnubby-auth");
633 message
.set_data("test");
635 Expectation authenticated
=
636 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
637 .WillOnce(Return(true));
638 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
639 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
640 .After(authenticated
)
642 SetGnubbyAuthHandlerForTesting(client_session_
.get(),
643 gnubby_auth_handler
),
644 DeliverClientMessage(client_session_
.get(), message
),
645 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
646 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
647 EXPECT_CALL(*gnubby_auth_handler
, DeliverClientMessage(_
));
648 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
650 ConnectClientSession();
653 // Verifies that the client's video pipeline can be reset mid-session.
654 TEST_F(ClientSessionTest
, ResetVideoPipeline
) {
655 CreateClientSession();
657 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
658 .WillOnce(Return(true));
660 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
662 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
663 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
665 ConnectClientSession();
667 client_session_
->ResetVideoPipeline();
670 // Verifies that clients can have extensions registered, resulting in the
671 // correct capabilities being reported, and messages delivered correctly.
672 // The extension system is tested more extensively in the
673 // HostExtensionSessionManager unit-tests.
674 TEST_F(ClientSessionTest
, Extensions
) {
675 // Configure fake extensions for testing.
676 FakeExtension
extension1("ext1", "cap1");
677 extensions_
.push_back(&extension1
);
678 FakeExtension
extension2("ext2", "");
679 extensions_
.push_back(&extension2
);
680 FakeExtension
extension3("ext3", "cap3");
681 extensions_
.push_back(&extension3
);
683 // Set the second extension to request to modify the video pipeline.
684 extension2
.set_steal_video_capturer(true);
686 CreateClientSession();
688 Expectation authenticated
=
689 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
690 .WillOnce(Return(true));
692 // Verify that the ClientSession reports the correct capabilities, and mimic
693 // the client reporting an overlapping set of capabilities.
694 EXPECT_CALL(client_stub_
,
695 SetCapabilities(EqCapabilities("cap1 cap3 default")))
696 .After(authenticated
)
697 .WillOnce(SetCapabilities(client_session_
.get(), "cap1 cap4 default"));
699 // Verify that the correct extension messages are delivered, and dropped.
700 protocol::ExtensionMessage message1
;
701 message1
.set_type("ext1");
702 message1
.set_data("data");
703 protocol::ExtensionMessage message3
;
704 message3
.set_type("ext3");
705 message3
.set_data("data");
706 protocol::ExtensionMessage message4
;
707 message4
.set_type("ext4");
708 message4
.set_data("data");
709 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
711 DeliverClientMessage(client_session_
.get(), message1
),
712 DeliverClientMessage(client_session_
.get(), message3
),
713 DeliverClientMessage(client_session_
.get(), message4
),
714 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
715 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
717 // Simulate the ClientSession connect and extension negotiation.
718 ConnectClientSession();
719 base::RunLoop().RunUntilIdle();
721 // ext1 was instantiated and sent a message, and did not wrap anything.
722 EXPECT_TRUE(extension1
.was_instantiated());
723 EXPECT_TRUE(extension1
.has_handled_message());
724 EXPECT_FALSE(extension1
.has_wrapped_video_encoder());
726 // ext2 was instantiated but not sent a message, and wrapped video encoder.
727 EXPECT_TRUE(extension2
.was_instantiated());
728 EXPECT_FALSE(extension2
.has_handled_message());
729 EXPECT_TRUE(extension2
.has_wrapped_video_encoder());
731 // ext3 was sent a message but not instantiated.
732 EXPECT_FALSE(extension3
.was_instantiated());
735 // Verifies that an extension can "steal" the video capture, in which case no
736 // VideoFramePump is instantiated.
737 TEST_F(ClientSessionTest
, StealVideoCapturer
) {
738 FakeExtension
extension("ext1", "cap1");
739 extensions_
.push_back(&extension
);
741 CreateClientSession();
743 SetMatchCapabilitiesExpectation();
745 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
746 .WillOnce(Return(true));
748 ConnectClientSession();
750 base::RunLoop().RunUntilIdle();
752 extension
.set_steal_video_capturer(true);
753 client_session_
->ResetVideoPipeline();
755 base::RunLoop().RunUntilIdle();
757 // Verify that video control messages received while there is no video
758 // scheduler active won't crash things.
759 protocol::VideoControl video_control
;
760 video_control
.set_enable(false);
761 video_control
.set_lossless_encode(true);
762 video_control
.set_lossless_color(true);
763 client_session_
->ControlVideo(video_control
);
765 // TODO(wez): Find a way to verify that the ClientSession never captures any
766 // frames in this case.
768 DisconnectClientSession();
771 // ext1 was instantiated and wrapped the video capturer.
772 EXPECT_TRUE(extension
.was_instantiated());
773 EXPECT_TRUE(extension
.has_wrapped_video_capturer());
776 } // namespace remoting