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_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "remoting/base/auto_thread_task_runner.h"
15 #include "remoting/base/constants.h"
16 #include "remoting/host/audio_capturer.h"
17 #include "remoting/host/client_session.h"
18 #include "remoting/host/desktop_environment.h"
19 #include "remoting/host/fake_desktop_capturer.h"
20 #include "remoting/host/fake_host_extension.h"
21 #include "remoting/host/fake_mouse_cursor_monitor.h"
22 #include "remoting/host/host_extension.h"
23 #include "remoting/host/host_extension_session.h"
24 #include "remoting/host/host_mock_objects.h"
25 #include "remoting/protocol/protocol_mock_objects.h"
26 #include "remoting/protocol/test_event_matchers.h"
27 #include "testing/gmock/include/gmock/gmock-matchers.h"
28 #include "testing/gmock_mutant.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
31 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
32 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
36 using protocol::MockClientStub
;
37 using protocol::MockConnectionToClient
;
38 using protocol::MockHostStub
;
39 using protocol::MockInputStub
;
40 using protocol::MockSession
;
41 using protocol::MockVideoStub
;
42 using protocol::SessionConfig
;
43 using protocol::test::EqualsClipboardEvent
;
44 using protocol::test::EqualsMouseButtonEvent
;
45 using protocol::test::EqualsMouseMoveEvent
;
46 using protocol::test::EqualsKeyEvent
;
49 using testing::AnyNumber
;
50 using testing::AtMost
;
51 using testing::AtLeast
;
52 using testing::CreateFunctor
;
53 using testing::DeleteArg
;
55 using testing::Expectation
;
56 using testing::Invoke
;
57 using testing::Return
;
58 using testing::ReturnRef
;
59 using testing::Sequence
;
61 using testing::StrictMock
;
65 const char kDefaultTestCapability
[] = "default";
67 ACTION_P2(InjectClipboardEvent
, connection
, event
) {
68 connection
->clipboard_stub()->InjectClipboardEvent(event
);
71 ACTION_P2(InjectKeyEvent
, connection
, event
) {
72 connection
->input_stub()->InjectKeyEvent(event
);
75 ACTION_P2(InjectMouseEvent
, connection
, event
) {
76 connection
->input_stub()->InjectMouseEvent(event
);
79 ACTION_P2(LocalMouseMoved
, client_session
, event
) {
80 client_session
->OnLocalMouseMoved(
81 webrtc::DesktopVector(event
.x(), event
.y()));
84 ACTION_P2(SetGnubbyAuthHandlerForTesting
, client_session
, gnubby_auth_handler
) {
85 client_session
->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler
);
88 ACTION_P2(DeliverClientMessage
, client_session
, message
) {
89 client_session
->DeliverClientMessage(message
);
92 ACTION_P2(SetCapabilities
, client_session
, capabilities
) {
93 protocol::Capabilities capabilities_message
;
94 capabilities_message
.set_capabilities(capabilities
);
95 client_session
->SetCapabilities(capabilities_message
);
98 // Matches a |protocol::Capabilities| argument against a list of capabilities
99 // formatted as a space-separated string.
100 MATCHER_P(EqCapabilities
, expected_capabilities
, "") {
101 if (!arg
.has_capabilities())
104 std::vector
<std::string
> words_args
= base::SplitString(
105 arg
.capabilities(), " ", base::KEEP_WHITESPACE
,
106 base::SPLIT_WANT_NONEMPTY
);
107 std::vector
<std::string
> words_expected
= base::SplitString(
108 expected_capabilities
, " ", base::KEEP_WHITESPACE
,
109 base::SPLIT_WANT_NONEMPTY
);
110 std::sort(words_args
.begin(), words_args
.end());
111 std::sort(words_expected
.begin(), words_expected
.end());
112 return words_args
== words_expected
;
117 class ClientSessionTest
: public testing::Test
{
119 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
121 void SetUp() override
;
122 void TearDown() override
;
124 // Creates the client session.
125 void CreateClientSession();
127 // Disconnects the client session.
128 void DisconnectClientSession();
130 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
131 void StopClientSession();
134 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
135 // DesktopEnvironmentFactory::Create().
136 DesktopEnvironment
* CreateDesktopEnvironment();
138 // Returns |input_injector_| created and initialized by SetUp(), to mock
139 // DesktopEnvironment::CreateInputInjector().
140 InputInjector
* CreateInputInjector();
142 // Creates a fake webrtc::DesktopCapturer, to mock
143 // DesktopEnvironment::CreateVideoCapturer().
144 webrtc::DesktopCapturer
* CreateVideoCapturer();
146 // Creates a MockMouseCursorMonitor, to mock
147 // DesktopEnvironment::CreateMouseCursorMonitor
148 webrtc::MouseCursorMonitor
* CreateMouseCursorMonitor();
150 // Notifies the client session that the client connection has been
151 // authenticated and channels have been connected. This effectively enables
152 // the input pipe line and starts video capturing.
153 void ConnectClientSession();
155 // Creates expectation that simulates client supporting same capabilities as
157 void SetMatchCapabilitiesExpectation();
159 // Creates expectations to send an extension message and to disconnect
161 void SetSendMessageAndDisconnectExpectation(const std::string
& message_type
);
163 // Message loop that will process all ClientSession tasks.
164 base::MessageLoop message_loop_
;
166 // AutoThreadTaskRunner on which |client_session_| will be run.
167 scoped_refptr
<AutoThreadTaskRunner
> task_runner_
;
169 // Used to run |message_loop_| after each test, until no objects remain that
171 base::RunLoop run_loop_
;
173 // HostExtensions to pass when creating the ClientSession. Caller retains
174 // ownership of the HostExtensions themselves.
175 std::vector
<HostExtension
*> extensions_
;
177 // ClientSession instance under test.
178 scoped_ptr
<ClientSession
> client_session_
;
180 // ClientSession::EventHandler mock for use in tests.
181 MockClientSessionEventHandler session_event_handler_
;
183 // Storage for values to be returned by the protocol::Session mock.
184 scoped_ptr
<SessionConfig
> session_config_
;
185 const std::string client_jid_
;
187 // Stubs returned to |client_session_| components by |connection_|.
188 MockClientStub client_stub_
;
189 MockVideoStub video_stub_
;
191 // DesktopEnvironment owns |input_injector_|, but input injection tests need
192 // to express expectations on it.
193 scoped_ptr
<MockInputInjector
> input_injector_
;
195 // ClientSession owns |connection_| but tests need it to inject fake events.
196 MockConnectionToClient
* connection_
;
198 scoped_ptr
<MockDesktopEnvironmentFactory
> desktop_environment_factory_
;
201 void ClientSessionTest::SetUp() {
202 // Arrange to run |message_loop_| until no components depend on it.
203 task_runner_
= new AutoThreadTaskRunner(
204 message_loop_
.task_runner(), run_loop_
.QuitClosure());
206 desktop_environment_factory_
.reset(new MockDesktopEnvironmentFactory());
207 EXPECT_CALL(*desktop_environment_factory_
, CreatePtr())
209 .WillRepeatedly(Invoke(this,
210 &ClientSessionTest::CreateDesktopEnvironment
));
211 EXPECT_CALL(*desktop_environment_factory_
, SupportsAudioCapture())
213 .WillRepeatedly(Return(false));
215 input_injector_
.reset(new MockInputInjector());
217 session_config_
= SessionConfig::ForTest();
220 void ClientSessionTest::TearDown() {
221 // Clear out |task_runner_| reference so the loop can quit, and run it until
223 task_runner_
= nullptr;
227 void ClientSessionTest::CreateClientSession() {
228 // Mock protocol::Session APIs called directly by ClientSession.
229 protocol::MockSession
* session
= new MockSession();
230 EXPECT_CALL(*session
, config()).WillRepeatedly(ReturnRef(*session_config_
));
231 EXPECT_CALL(*session
, jid()).WillRepeatedly(ReturnRef(client_jid_
));
232 EXPECT_CALL(*session
, SetEventHandler(_
));
234 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
235 // HostStub is not touched by ClientSession, so we can safely pass nullptr.
236 scoped_ptr
<MockConnectionToClient
> connection(
237 new MockConnectionToClient(session
, nullptr));
238 EXPECT_CALL(*connection
, session()).WillRepeatedly(Return(session
));
239 EXPECT_CALL(*connection
, client_stub())
240 .WillRepeatedly(Return(&client_stub_
));
241 EXPECT_CALL(*connection
, video_stub()).WillRepeatedly(Return(&video_stub_
));
242 EXPECT_CALL(*connection
, Disconnect());
243 connection_
= connection
.get();
245 client_session_
.reset(new ClientSession(
246 &session_event_handler_
,
247 task_runner_
, // Audio thread.
248 task_runner_
, // Input thread.
249 task_runner_
, // Capture thread.
250 task_runner_
, // Encode thread.
251 task_runner_
, // Network thread.
252 task_runner_
, // UI thread.
254 desktop_environment_factory_
.get(),
260 void ClientSessionTest::DisconnectClientSession() {
261 client_session_
->DisconnectSession();
262 // MockSession won't trigger OnConnectionClosed, so fake it.
263 client_session_
->OnConnectionClosed(client_session_
->connection(),
267 void ClientSessionTest::StopClientSession() {
268 client_session_
.reset();
270 desktop_environment_factory_
.reset();
273 DesktopEnvironment
* ClientSessionTest::CreateDesktopEnvironment() {
274 MockDesktopEnvironment
* desktop_environment
= new MockDesktopEnvironment();
275 EXPECT_CALL(*desktop_environment
, CreateAudioCapturerPtr())
277 EXPECT_CALL(*desktop_environment
, CreateInputInjectorPtr())
278 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector
));
279 EXPECT_CALL(*desktop_environment
, CreateScreenControlsPtr())
281 EXPECT_CALL(*desktop_environment
, CreateVideoCapturerPtr())
282 .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer
));
283 EXPECT_CALL(*desktop_environment
, CreateMouseCursorMonitorPtr())
285 Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor
));
286 EXPECT_CALL(*desktop_environment
, GetCapabilities())
288 .WillOnce(Return(kDefaultTestCapability
));
289 EXPECT_CALL(*desktop_environment
, SetCapabilities(_
))
292 return desktop_environment
;
295 InputInjector
* ClientSessionTest::CreateInputInjector() {
296 EXPECT_TRUE(input_injector_
);
297 return input_injector_
.release();
300 webrtc::DesktopCapturer
* ClientSessionTest::CreateVideoCapturer() {
301 return new FakeDesktopCapturer();
304 webrtc::MouseCursorMonitor
* ClientSessionTest::CreateMouseCursorMonitor() {
305 return new FakeMouseCursorMonitor();
308 void ClientSessionTest::ConnectClientSession() {
309 // Stubs should be set only after connection is authenticated.
310 EXPECT_FALSE(connection_
->clipboard_stub());
311 EXPECT_FALSE(connection_
->input_stub());
313 client_session_
->OnConnectionAuthenticated(client_session_
->connection());
315 EXPECT_TRUE(connection_
->clipboard_stub());
316 EXPECT_TRUE(connection_
->input_stub());
318 client_session_
->OnConnectionChannelsConnected(client_session_
->connection());
321 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
322 // Set the client to report the same capabilities as the host.
323 EXPECT_CALL(client_stub_
, SetCapabilities(_
))
325 .WillOnce(Invoke(client_session_
.get(), &ClientSession::SetCapabilities
));
328 void ClientSessionTest::SetSendMessageAndDisconnectExpectation(
329 const std::string
& message_type
) {
330 protocol::ExtensionMessage message
;
331 message
.set_type(message_type
);
332 message
.set_data("data");
334 Expectation authenticated
=
335 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
336 .WillOnce(Return(true));
337 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
338 .After(authenticated
)
340 DeliverClientMessage(client_session_
.get(), message
),
341 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
342 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
345 TEST_F(ClientSessionTest
, ClipboardStubFilter
) {
346 CreateClientSession();
348 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
349 .WillOnce(Return(true));
350 EXPECT_CALL(*input_injector_
, StartPtr(_
));
351 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
));
353 // Wait for the first video packet to be captured to make sure that
354 // the injected input will go though. Otherwise mouse events will be blocked
355 // by the mouse clamping filter.
356 base::RunLoop run_loop
;
357 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
359 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
362 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
363 kMimeTypeTextUtf8
, "a")));
364 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, true)));
365 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, false)));
366 EXPECT_CALL(*input_injector_
,
367 InjectMouseEvent(EqualsMouseMoveEvent(100, 101)));
369 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
370 kMimeTypeTextUtf8
, "c")));
371 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(3, true)));
372 EXPECT_CALL(*input_injector_
,
373 InjectMouseEvent(EqualsMouseMoveEvent(300, 301)));
374 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(3, false)));
377 ConnectClientSession();
379 // Wait for the first frame.
382 // Inject test events that are expected to be injected.
383 protocol::ClipboardEvent clipboard_event
;
384 clipboard_event
.set_mime_type(kMimeTypeTextUtf8
);
385 clipboard_event
.set_data("a");
386 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
388 protocol::KeyEvent key_event
;
389 key_event
.set_pressed(true);
390 key_event
.set_usb_keycode(1);
391 connection_
->input_stub()->InjectKeyEvent(key_event
);
393 protocol::MouseEvent mouse_event
;
394 mouse_event
.set_x(100);
395 mouse_event
.set_y(101);
396 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
398 base::RunLoop().RunUntilIdle();
401 client_session_
->SetDisableInputs(true);
403 // These event shouldn't get though to the input injector.
404 clipboard_event
.set_data("b");
405 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
407 key_event
.set_pressed(true);
408 key_event
.set_usb_keycode(2);
409 connection_
->input_stub()->InjectKeyEvent(key_event
);
410 key_event
.set_pressed(false);
411 key_event
.set_usb_keycode(2);
412 connection_
->input_stub()->InjectKeyEvent(key_event
);
414 mouse_event
.set_x(200);
415 mouse_event
.set_y(201);
416 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
418 base::RunLoop().RunUntilIdle();
420 // Enable input again.
421 client_session_
->SetDisableInputs(false);
423 clipboard_event
.set_data("c");
424 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
425 base::RunLoop().RunUntilIdle();
427 key_event
.set_pressed(true);
428 key_event
.set_usb_keycode(3);
429 connection_
->input_stub()->InjectKeyEvent(key_event
);
431 mouse_event
.set_x(300);
432 mouse_event
.set_y(301);
433 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
435 client_session_
->DisconnectSession();
436 client_session_
->OnConnectionClosed(connection_
, protocol::OK
);
437 client_session_
.reset();
440 TEST_F(ClientSessionTest
, LocalInputTest
) {
441 CreateClientSession();
443 protocol::MouseEvent mouse_event1
;
444 mouse_event1
.set_x(100);
445 mouse_event1
.set_y(101);
446 protocol::MouseEvent mouse_event2
;
447 mouse_event2
.set_x(200);
448 mouse_event2
.set_y(201);
449 protocol::MouseEvent mouse_event3
;
450 mouse_event3
.set_x(300);
451 mouse_event3
.set_y(301);
453 Expectation authenticated
=
454 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
455 .WillOnce(Return(true));
456 EXPECT_CALL(*input_injector_
, StartPtr(_
))
457 .After(authenticated
);
458 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
459 .After(authenticated
);
461 // Wait for the first video packet to be captured to make sure that
462 // the injected input will go though. Otherwise mouse events will be blocked
463 // by the mouse clamping filter.
465 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
467 .After(authenticated
)
469 // This event should get through to the input stub.
470 InjectMouseEvent(connection_
, mouse_event1
),
472 // The OS echoes the injected event back.
473 LocalMouseMoved(client_session_
.get(), mouse_event1
),
474 #endif // !defined(OS_WIN)
475 // This one should get throught as well.
476 InjectMouseEvent(connection_
, mouse_event2
),
477 // Now this is a genuine local event.
478 LocalMouseMoved(client_session_
.get(), mouse_event1
),
479 // This one should be blocked because of the previous local input
481 InjectMouseEvent(connection_
, mouse_event3
),
482 // TODO(jamiewalch): Verify that remote inputs are re-enabled
483 // eventually (via dependency injection, not sleep!)
484 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
485 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
486 EXPECT_CALL(*input_injector_
,
487 InjectMouseEvent(EqualsMouseMoveEvent(100, 101))).InSequence(s
);
488 EXPECT_CALL(*input_injector_
,
489 InjectMouseEvent(EqualsMouseMoveEvent(200, 201))).InSequence(s
);
490 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).InSequence(s
);
492 ConnectClientSession();
495 TEST_F(ClientSessionTest
, RestoreEventState
) {
496 CreateClientSession();
498 protocol::KeyEvent key1
;
499 key1
.set_pressed(true);
500 key1
.set_usb_keycode(1);
502 protocol::KeyEvent key2
;
503 key2
.set_pressed(true);
504 key2
.set_usb_keycode(2);
506 protocol::MouseEvent mousedown
;
507 mousedown
.set_button(protocol::MouseEvent::BUTTON_LEFT
);
508 mousedown
.set_button_down(true);
510 Expectation authenticated
=
511 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
512 .WillOnce(Return(true));
513 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
514 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
515 .After(authenticated
);
517 // Wait for the first video packet to be captured to make sure that
518 // the injected input will go though. Otherwise mouse events will be blocked
519 // by the mouse clamping filter.
521 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
523 .After(authenticated
)
525 InjectKeyEvent(connection_
, key1
), InjectKeyEvent(connection_
, key2
),
526 InjectMouseEvent(connection_
, mousedown
),
527 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
528 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
529 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, true)))
531 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(2, true)))
533 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
534 protocol::MouseEvent::BUTTON_LEFT
, true)))
536 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(1, false)))
538 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsKeyEvent(2, false)))
540 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
541 protocol::MouseEvent::BUTTON_LEFT
, false)))
543 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).InSequence(s
);
545 ConnectClientSession();
548 TEST_F(ClientSessionTest
, ClampMouseEvents
) {
549 CreateClientSession();
551 Expectation authenticated
=
552 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
553 .WillOnce(Return(true));
554 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
555 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
556 .After(authenticated
);
557 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
)).After(authenticated
);
559 Expectation connected
= authenticated
;
561 int input_x
[3] = { -999, 100, 999 };
562 int expected_x
[3] = { 0, 100, FakeDesktopCapturer::kWidth
- 1 };
563 int input_y
[3] = { -999, 50, 999 };
564 int expected_y
[3] = { 0, 50, FakeDesktopCapturer::kHeight
- 1 };
566 protocol::MouseEvent expected_event
;
567 for (int j
= 0; j
< 3; j
++) {
568 for (int i
= 0; i
< 3; i
++) {
569 protocol::MouseEvent injected_event
;
570 injected_event
.set_x(input_x
[i
]);
571 injected_event
.set_y(input_y
[j
]);
573 if (i
== 0 && j
== 0) {
574 // Inject the 1st event once a video packet has been received.
576 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
578 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
580 // Every next event is injected once the previous event has been
583 EXPECT_CALL(*input_injector_
,
584 InjectMouseEvent(EqualsMouseMoveEvent(
585 expected_event
.x(), expected_event
.y())))
587 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
590 expected_event
.set_x(expected_x
[i
]);
591 expected_event
.set_y(expected_y
[j
]);
595 // Shutdown the connection once the last event has been received.
596 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseMoveEvent(
597 expected_event
.x(), expected_event
.y())))
600 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
601 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
603 ConnectClientSession();
606 TEST_F(ClientSessionTest
, NoGnubbyAuth
) {
607 CreateClientSession();
609 protocol::ExtensionMessage message
;
610 message
.set_type("gnubby-auth");
611 message
.set_data("test");
613 Expectation authenticated
=
614 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
615 .WillOnce(Return(true));
616 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
617 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
618 .After(authenticated
)
620 DeliverClientMessage(client_session_
.get(), message
),
621 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
622 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
623 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
625 ConnectClientSession();
628 TEST_F(ClientSessionTest
, EnableGnubbyAuth
) {
629 CreateClientSession();
631 // Lifetime controlled by object under test.
632 MockGnubbyAuthHandler
* gnubby_auth_handler
= new MockGnubbyAuthHandler();
634 protocol::ExtensionMessage message
;
635 message
.set_type("gnubby-auth");
636 message
.set_data("test");
638 Expectation authenticated
=
639 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
640 .WillOnce(Return(true));
641 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
642 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
643 .After(authenticated
)
645 SetGnubbyAuthHandlerForTesting(client_session_
.get(),
646 gnubby_auth_handler
),
647 DeliverClientMessage(client_session_
.get(), message
),
648 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
649 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
650 EXPECT_CALL(*gnubby_auth_handler
, DeliverClientMessage(_
));
651 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
653 ConnectClientSession();
656 // Verifies that the client's video pipeline can be reset mid-session.
657 TEST_F(ClientSessionTest
, ResetVideoPipeline
) {
658 CreateClientSession();
660 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
661 .WillOnce(Return(true));
663 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
665 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
666 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
668 ConnectClientSession();
670 client_session_
->ResetVideoPipeline();
673 // Verifies that clients can have extensions registered, resulting in the
674 // correct capabilities being reported, and messages delivered correctly.
675 // The extension system is tested more extensively in the
676 // HostExtensionSessionManager unit-tests.
677 TEST_F(ClientSessionTest
, Extensions
) {
678 // Configure fake extensions for testing.
679 FakeExtension
extension1("ext1", "cap1");
680 extensions_
.push_back(&extension1
);
681 FakeExtension
extension2("ext2", "");
682 extensions_
.push_back(&extension2
);
683 FakeExtension
extension3("ext3", "cap3");
684 extensions_
.push_back(&extension3
);
686 // Set the second extension to request to modify the video pipeline.
687 extension2
.set_steal_video_capturer(true);
689 CreateClientSession();
691 Expectation authenticated
=
692 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
693 .WillOnce(Return(true));
695 // Verify that the ClientSession reports the correct capabilities, and mimic
696 // the client reporting an overlapping set of capabilities.
697 EXPECT_CALL(client_stub_
,
698 SetCapabilities(EqCapabilities("cap1 cap3 default")))
699 .After(authenticated
)
700 .WillOnce(SetCapabilities(client_session_
.get(), "cap1 cap4 default"));
702 // Verify that the correct extension messages are delivered, and dropped.
703 protocol::ExtensionMessage message1
;
704 message1
.set_type("ext1");
705 message1
.set_data("data");
706 protocol::ExtensionMessage message3
;
707 message3
.set_type("ext3");
708 message3
.set_data("data");
709 protocol::ExtensionMessage message4
;
710 message4
.set_type("ext4");
711 message4
.set_data("data");
712 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
714 DeliverClientMessage(client_session_
.get(), message1
),
715 DeliverClientMessage(client_session_
.get(), message3
),
716 DeliverClientMessage(client_session_
.get(), message4
),
717 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
718 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
720 // Simulate the ClientSession connect and extension negotiation.
721 ConnectClientSession();
722 base::RunLoop().RunUntilIdle();
724 // ext1 was instantiated and sent a message, and did not wrap anything.
725 EXPECT_TRUE(extension1
.was_instantiated());
726 EXPECT_TRUE(extension1
.has_handled_message());
727 EXPECT_FALSE(extension1
.has_wrapped_video_encoder());
729 // ext2 was instantiated but not sent a message, and wrapped video encoder.
730 EXPECT_TRUE(extension2
.was_instantiated());
731 EXPECT_FALSE(extension2
.has_handled_message());
732 EXPECT_TRUE(extension2
.has_wrapped_video_encoder());
734 // ext3 was sent a message but not instantiated.
735 EXPECT_FALSE(extension3
.was_instantiated());
738 // Verifies that an extension can "steal" the video capture, in which case no
739 // VideoFramePump is instantiated.
740 TEST_F(ClientSessionTest
, StealVideoCapturer
) {
741 FakeExtension
extension("ext1", "cap1");
742 extensions_
.push_back(&extension
);
744 CreateClientSession();
746 SetMatchCapabilitiesExpectation();
748 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
749 .WillOnce(Return(true));
751 ConnectClientSession();
753 base::RunLoop().RunUntilIdle();
755 extension
.set_steal_video_capturer(true);
756 client_session_
->ResetVideoPipeline();
758 base::RunLoop().RunUntilIdle();
760 // Verify that video control messages received while there is no video
761 // scheduler active won't crash things.
762 protocol::VideoControl video_control
;
763 video_control
.set_enable(false);
764 video_control
.set_lossless_encode(true);
765 video_control
.set_lossless_color(true);
766 client_session_
->ControlVideo(video_control
);
768 // TODO(wez): Find a way to verify that the ClientSession never captures any
769 // frames in this case.
771 DisconnectClientSession();
774 // ext1 was instantiated and wrapped the video capturer.
775 EXPECT_TRUE(extension
.was_instantiated());
776 EXPECT_TRUE(extension
.has_wrapped_video_capturer());
779 } // namespace remoting