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::AtLeast
;
46 using testing::CreateFunctor
;
47 using testing::DeleteArg
;
49 using testing::Expectation
;
50 using testing::Invoke
;
51 using testing::Return
;
52 using testing::ReturnRef
;
53 using testing::Sequence
;
55 using testing::StrictMock
;
59 const char kDefaultTestCapability
[] = "default";
61 ACTION_P2(InjectClipboardEvent
, connection
, event
) {
62 connection
->clipboard_stub()->InjectClipboardEvent(event
);
65 ACTION_P2(InjectKeyEvent
, connection
, event
) {
66 connection
->input_stub()->InjectKeyEvent(event
);
69 ACTION_P2(InjectMouseEvent
, connection
, event
) {
70 connection
->input_stub()->InjectMouseEvent(event
);
73 ACTION_P2(LocalMouseMoved
, client_session
, event
) {
74 client_session
->OnLocalMouseMoved(
75 webrtc::DesktopVector(event
.x(), event
.y()));
78 ACTION_P2(SetGnubbyAuthHandlerForTesting
, client_session
, gnubby_auth_handler
) {
79 client_session
->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler
);
82 ACTION_P2(DeliverClientMessage
, client_session
, message
) {
83 client_session
->DeliverClientMessage(message
);
86 ACTION_P2(SetCapabilities
, client_session
, capabilities
) {
87 protocol::Capabilities capabilities_message
;
88 capabilities_message
.set_capabilities(capabilities
);
89 client_session
->SetCapabilities(capabilities_message
);
92 MATCHER_P2(EqualsUsbEvent
, usb_keycode
, pressed
, "") {
93 return arg
.usb_keycode() == (unsigned int)usb_keycode
&&
94 arg
.pressed() == pressed
;
97 MATCHER_P2(EqualsMouseEvent
, x
, y
, "") {
98 return arg
.x() == x
&& arg
.y() == y
;
101 MATCHER_P2(EqualsMouseButtonEvent
, button
, down
, "") {
102 return arg
.button() == button
&& arg
.button_down() == down
;
105 // Matches a |protocol::Capabilities| argument against a list of capabilities
106 // formatted as a space-separated string.
107 MATCHER_P(EqCapabilities
, expected_capabilities
, "") {
108 if (!arg
.has_capabilities())
111 std::vector
<std::string
> words_args
;
112 std::vector
<std::string
> words_expected
;
113 Tokenize(arg
.capabilities(), " ", &words_args
);
114 Tokenize(expected_capabilities
, " ", &words_expected
);
115 std::sort(words_args
.begin(), words_args
.end());
116 std::sort(words_expected
.begin(), words_expected
.end());
117 return words_args
== words_expected
;
122 class ClientSessionTest
: public testing::Test
{
124 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
126 void SetUp() override
;
127 void TearDown() override
;
129 // Creates the client session.
130 void CreateClientSession();
132 // Disconnects the client session.
133 void DisconnectClientSession();
135 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
136 void StopClientSession();
139 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
140 // DesktopEnvironmentFactory::Create().
141 DesktopEnvironment
* CreateDesktopEnvironment();
143 // Returns |input_injector_| created and initialized by SetUp(), to mock
144 // DesktopEnvironment::CreateInputInjector().
145 InputInjector
* CreateInputInjector();
147 // Creates a fake webrtc::DesktopCapturer, to mock
148 // DesktopEnvironment::CreateVideoCapturer().
149 webrtc::DesktopCapturer
* CreateVideoCapturer();
151 // Creates a MockMouseCursorMonitor, to mock
152 // DesktopEnvironment::CreateMouseCursorMonitor
153 webrtc::MouseCursorMonitor
* CreateMouseCursorMonitor();
155 // Notifies the client session that the client connection has been
156 // authenticated and channels have been connected. This effectively enables
157 // the input pipe line and starts video capturing.
158 void ConnectClientSession();
160 // Creates expectation that simulates client supporting same capabilities as
162 void SetMatchCapabilitiesExpectation();
164 // Creates expectations to send an extension message and to disconnect
166 void SetSendMessageAndDisconnectExpectation(const std::string
& message_type
);
168 // Message loop that will process all ClientSession tasks.
169 base::MessageLoop message_loop_
;
171 // AutoThreadTaskRunner on which |client_session_| will be run.
172 scoped_refptr
<AutoThreadTaskRunner
> task_runner_
;
174 // Used to run |message_loop_| after each test, until no objects remain that
176 base::RunLoop run_loop_
;
178 // HostExtensions to pass when creating the ClientSession. Caller retains
179 // ownership of the HostExtensions themselves.
180 std::vector
<HostExtension
*> extensions_
;
182 // ClientSession instance under test.
183 scoped_ptr
<ClientSession
> client_session_
;
185 // ClientSession::EventHandler mock for use in tests.
186 MockClientSessionEventHandler session_event_handler_
;
188 // Storage for values to be returned by the protocol::Session mock.
189 SessionConfig session_config_
;
190 const std::string client_jid_
;
192 // Stubs returned to |client_session_| components by |connection_|.
193 MockClientStub client_stub_
;
194 MockVideoStub video_stub_
;
196 // DesktopEnvironment owns |input_injector_|, but input injection tests need
197 // to express expectations on it.
198 scoped_ptr
<MockInputInjector
> input_injector_
;
200 // ClientSession owns |connection_| but tests need it to inject fake events.
201 MockConnectionToClient
* connection_
;
203 scoped_ptr
<MockDesktopEnvironmentFactory
> desktop_environment_factory_
;
206 void ClientSessionTest::SetUp() {
207 // Arrange to run |message_loop_| until no components depend on it.
208 task_runner_
= new AutoThreadTaskRunner(
209 message_loop_
.message_loop_proxy(), run_loop_
.QuitClosure());
211 desktop_environment_factory_
.reset(new MockDesktopEnvironmentFactory());
212 EXPECT_CALL(*desktop_environment_factory_
, CreatePtr())
214 .WillRepeatedly(Invoke(this,
215 &ClientSessionTest::CreateDesktopEnvironment
));
216 EXPECT_CALL(*desktop_environment_factory_
, SupportsAudioCapture())
218 .WillRepeatedly(Return(false));
220 input_injector_
.reset(new MockInputInjector());
222 session_config_
= SessionConfig::ForTest();
225 void ClientSessionTest::TearDown() {
226 // Clear out |task_runner_| reference so the loop can quit, and run it until
228 task_runner_
= nullptr;
232 void ClientSessionTest::CreateClientSession() {
233 // Mock protocol::Session APIs called directly by ClientSession.
234 protocol::MockSession
* session
= new MockSession();
235 EXPECT_CALL(*session
, config()).WillRepeatedly(ReturnRef(session_config_
));
236 EXPECT_CALL(*session
, jid()).WillRepeatedly(ReturnRef(client_jid_
));
237 EXPECT_CALL(*session
, SetEventHandler(_
));
239 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
240 // HostStub is not touched by ClientSession, so we can safely pass nullptr.
241 scoped_ptr
<MockConnectionToClient
> connection(
242 new MockConnectionToClient(session
, nullptr));
243 EXPECT_CALL(*connection
, session()).WillRepeatedly(Return(session
));
244 EXPECT_CALL(*connection
, client_stub())
245 .WillRepeatedly(Return(&client_stub_
));
246 EXPECT_CALL(*connection
, video_stub()).WillRepeatedly(Return(&video_stub_
));
247 EXPECT_CALL(*connection
, Disconnect());
248 connection_
= connection
.get();
250 client_session_
.reset(new ClientSession(
251 &session_event_handler_
,
252 task_runner_
, // Audio thread.
253 task_runner_
, // Input thread.
254 task_runner_
, // Capture thread.
255 task_runner_
, // Encode thread.
256 task_runner_
, // Network thread.
257 task_runner_
, // UI thread.
259 desktop_environment_factory_
.get(),
265 void ClientSessionTest::DisconnectClientSession() {
266 client_session_
->DisconnectSession();
267 // MockSession won't trigger OnConnectionClosed, so fake it.
268 client_session_
->OnConnectionClosed(client_session_
->connection(),
272 void ClientSessionTest::StopClientSession() {
273 client_session_
.reset();
275 desktop_environment_factory_
.reset();
278 DesktopEnvironment
* ClientSessionTest::CreateDesktopEnvironment() {
279 MockDesktopEnvironment
* desktop_environment
= new MockDesktopEnvironment();
280 EXPECT_CALL(*desktop_environment
, CreateAudioCapturerPtr())
282 EXPECT_CALL(*desktop_environment
, CreateInputInjectorPtr())
283 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector
));
284 EXPECT_CALL(*desktop_environment
, CreateScreenControlsPtr())
286 EXPECT_CALL(*desktop_environment
, CreateVideoCapturerPtr())
287 .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer
));
288 EXPECT_CALL(*desktop_environment
, CreateMouseCursorMonitorPtr())
290 Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor
));
291 EXPECT_CALL(*desktop_environment
, GetCapabilities())
293 .WillOnce(Return(kDefaultTestCapability
));
294 EXPECT_CALL(*desktop_environment
, SetCapabilities(_
))
297 return desktop_environment
;
300 InputInjector
* ClientSessionTest::CreateInputInjector() {
301 EXPECT_TRUE(input_injector_
);
302 return input_injector_
.release();
305 webrtc::DesktopCapturer
* ClientSessionTest::CreateVideoCapturer() {
306 return new FakeDesktopCapturer();
309 webrtc::MouseCursorMonitor
* ClientSessionTest::CreateMouseCursorMonitor() {
310 return new FakeMouseCursorMonitor();
313 void ClientSessionTest::ConnectClientSession() {
314 // Stubs should be set only after connection is authenticated.
315 EXPECT_FALSE(connection_
->clipboard_stub());
316 EXPECT_FALSE(connection_
->input_stub());
318 client_session_
->OnConnectionAuthenticated(client_session_
->connection());
320 EXPECT_TRUE(connection_
->clipboard_stub());
321 EXPECT_TRUE(connection_
->input_stub());
323 client_session_
->OnConnectionChannelsConnected(client_session_
->connection());
326 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
327 // Set the client to report the same capabilities as the host.
328 EXPECT_CALL(client_stub_
, SetCapabilities(_
))
330 .WillOnce(Invoke(client_session_
.get(), &ClientSession::SetCapabilities
));
333 void ClientSessionTest::SetSendMessageAndDisconnectExpectation(
334 const std::string
& message_type
) {
335 protocol::ExtensionMessage message
;
336 message
.set_type(message_type
);
337 message
.set_data("data");
339 Expectation authenticated
=
340 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
341 .WillOnce(Return(true));
342 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
343 .After(authenticated
)
345 DeliverClientMessage(client_session_
.get(), message
),
346 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
347 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
350 MATCHER_P2(EqualsClipboardEvent
, m
, d
, "") {
351 return (strcmp(arg
.mime_type().c_str(), m
) == 0 &&
352 memcmp(arg
.data().data(), d
, arg
.data().size()) == 0);
355 TEST_F(ClientSessionTest
, ClipboardStubFilter
) {
356 CreateClientSession();
358 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
359 .WillOnce(Return(true));
360 EXPECT_CALL(*input_injector_
, StartPtr(_
));
361 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
));
363 // Wait for the first video packet to be captured to make sure that
364 // the injected input will go though. Otherwise mouse events will be blocked
365 // by the mouse clamping filter.
366 base::RunLoop run_loop
;
367 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
369 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
372 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
373 kMimeTypeTextUtf8
, "a")));
374 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, true)));
375 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, false)));
376 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(100, 101)));
378 EXPECT_CALL(*input_injector_
, InjectClipboardEvent(EqualsClipboardEvent(
379 kMimeTypeTextUtf8
, "c")));
380 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(3, true)));
381 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(300, 301)));
382 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(3, false)));
385 ConnectClientSession();
387 // Wait for the first frame.
390 // Inject test events that are expected to be injected.
391 protocol::ClipboardEvent clipboard_event
;
392 clipboard_event
.set_mime_type(kMimeTypeTextUtf8
);
393 clipboard_event
.set_data("a");
394 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
396 protocol::KeyEvent key_event
;
397 key_event
.set_pressed(true);
398 key_event
.set_usb_keycode(1);
399 connection_
->input_stub()->InjectKeyEvent(key_event
);
401 protocol::MouseEvent mouse_event
;
402 mouse_event
.set_x(100);
403 mouse_event
.set_y(101);
404 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
406 base::RunLoop().RunUntilIdle();
409 client_session_
->SetDisableInputs(true);
411 // These event shouldn't get though to the input injector.
412 clipboard_event
.set_data("b");
413 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
415 key_event
.set_pressed(true);
416 key_event
.set_usb_keycode(2);
417 connection_
->input_stub()->InjectKeyEvent(key_event
);
418 key_event
.set_pressed(false);
419 key_event
.set_usb_keycode(2);
420 connection_
->input_stub()->InjectKeyEvent(key_event
);
422 mouse_event
.set_x(200);
423 mouse_event
.set_y(201);
424 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
426 base::RunLoop().RunUntilIdle();
428 // Enable input again.
429 client_session_
->SetDisableInputs(false);
431 clipboard_event
.set_data("c");
432 connection_
->clipboard_stub()->InjectClipboardEvent(clipboard_event
);
433 base::RunLoop().RunUntilIdle();
435 key_event
.set_pressed(true);
436 key_event
.set_usb_keycode(3);
437 connection_
->input_stub()->InjectKeyEvent(key_event
);
439 mouse_event
.set_x(300);
440 mouse_event
.set_y(301);
441 connection_
->input_stub()->InjectMouseEvent(mouse_event
);
443 client_session_
->DisconnectSession();
444 client_session_
->OnConnectionClosed(connection_
, protocol::OK
);
445 client_session_
.reset();
448 TEST_F(ClientSessionTest
, LocalInputTest
) {
449 CreateClientSession();
451 protocol::MouseEvent mouse_event1
;
452 mouse_event1
.set_x(100);
453 mouse_event1
.set_y(101);
454 protocol::MouseEvent mouse_event2
;
455 mouse_event2
.set_x(200);
456 mouse_event2
.set_y(201);
457 protocol::MouseEvent mouse_event3
;
458 mouse_event3
.set_x(300);
459 mouse_event3
.set_y(301);
461 Expectation authenticated
=
462 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
463 .WillOnce(Return(true));
464 EXPECT_CALL(*input_injector_
, StartPtr(_
))
465 .After(authenticated
);
466 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
467 .After(authenticated
);
469 // Wait for the first video packet to be captured to make sure that
470 // the injected input will go though. Otherwise mouse events will be blocked
471 // by the mouse clamping filter.
473 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
475 .After(authenticated
)
477 // This event should get through to the input stub.
478 InjectMouseEvent(connection_
, mouse_event1
),
480 // The OS echoes the injected event back.
481 LocalMouseMoved(client_session_
.get(), mouse_event1
),
482 #endif // !defined(OS_WIN)
483 // This one should get throught as well.
484 InjectMouseEvent(connection_
, mouse_event2
),
485 // Now this is a genuine local event.
486 LocalMouseMoved(client_session_
.get(), mouse_event1
),
487 // This one should be blocked because of the previous local input
489 InjectMouseEvent(connection_
, mouse_event3
),
490 // TODO(jamiewalch): Verify that remote inputs are re-enabled
491 // eventually (via dependency injection, not sleep!)
492 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
493 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
494 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(100, 101)))
496 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseEvent(200, 201)))
498 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
501 ConnectClientSession();
504 TEST_F(ClientSessionTest
, RestoreEventState
) {
505 CreateClientSession();
507 protocol::KeyEvent key1
;
508 key1
.set_pressed(true);
509 key1
.set_usb_keycode(1);
511 protocol::KeyEvent key2
;
512 key2
.set_pressed(true);
513 key2
.set_usb_keycode(2);
515 protocol::MouseEvent mousedown
;
516 mousedown
.set_button(protocol::MouseEvent::BUTTON_LEFT
);
517 mousedown
.set_button_down(true);
519 Expectation authenticated
=
520 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
521 .WillOnce(Return(true));
522 EXPECT_CALL(*input_injector_
, StartPtr(_
))
523 .After(authenticated
);
524 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
525 .After(authenticated
);
527 // Wait for the first video packet to be captured to make sure that
528 // the injected input will go though. Otherwise mouse events will be blocked
529 // by the mouse clamping filter.
531 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
533 .After(authenticated
)
535 InjectKeyEvent(connection_
, key1
),
536 InjectKeyEvent(connection_
, key2
),
537 InjectMouseEvent(connection_
, mousedown
),
538 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
539 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
540 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, true)))
542 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, true)))
544 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
545 protocol::MouseEvent::BUTTON_LEFT
, true)))
547 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(1, false)))
549 EXPECT_CALL(*input_injector_
, InjectKeyEvent(EqualsUsbEvent(2, false)))
551 EXPECT_CALL(*input_injector_
, InjectMouseEvent(EqualsMouseButtonEvent(
552 protocol::MouseEvent::BUTTON_LEFT
, false)))
554 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
557 ConnectClientSession();
560 TEST_F(ClientSessionTest
, ClampMouseEvents
) {
561 CreateClientSession();
563 Expectation authenticated
=
564 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
565 .WillOnce(Return(true));
566 EXPECT_CALL(*input_injector_
, StartPtr(_
))
567 .After(authenticated
);
568 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
569 .After(authenticated
);
570 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
))
571 .After(authenticated
);
573 Expectation connected
= authenticated
;
575 int input_x
[3] = { -999, 100, 999 };
576 int expected_x
[3] = { 0, 100, FakeDesktopCapturer::kWidth
- 1 };
577 int input_y
[3] = { -999, 50, 999 };
578 int expected_y
[3] = { 0, 50, FakeDesktopCapturer::kHeight
- 1 };
580 protocol::MouseEvent expected_event
;
581 for (int j
= 0; j
< 3; j
++) {
582 for (int i
= 0; i
< 3; i
++) {
583 protocol::MouseEvent injected_event
;
584 injected_event
.set_x(input_x
[i
]);
585 injected_event
.set_y(input_y
[j
]);
587 if (i
== 0 && j
== 0) {
588 // Inject the 1st event once a video packet has been received.
590 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
592 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
594 // Every next event is injected once the previous event has been
597 EXPECT_CALL(*input_injector_
,
598 InjectMouseEvent(EqualsMouseEvent(expected_event
.x(),
599 expected_event
.y())))
601 .WillOnce(InjectMouseEvent(connection_
, injected_event
));
604 expected_event
.set_x(expected_x
[i
]);
605 expected_event
.set_y(expected_y
[j
]);
609 // Shutdown the connection once the last event has been received.
610 EXPECT_CALL(*input_injector_
,
611 InjectMouseEvent(EqualsMouseEvent(expected_event
.x(),
612 expected_event
.y())))
615 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
616 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
618 ConnectClientSession();
621 TEST_F(ClientSessionTest
, NoGnubbyAuth
) {
622 CreateClientSession();
624 protocol::ExtensionMessage message
;
625 message
.set_type("gnubby-auth");
626 message
.set_data("test");
628 Expectation authenticated
=
629 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
630 .WillOnce(Return(true));
631 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
632 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
633 .After(authenticated
)
635 DeliverClientMessage(client_session_
.get(), message
),
636 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
637 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
638 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
640 ConnectClientSession();
643 TEST_F(ClientSessionTest
, EnableGnubbyAuth
) {
644 CreateClientSession();
646 // Lifetime controlled by object under test.
647 MockGnubbyAuthHandler
* gnubby_auth_handler
= new MockGnubbyAuthHandler();
649 protocol::ExtensionMessage message
;
650 message
.set_type("gnubby-auth");
651 message
.set_data("test");
653 Expectation authenticated
=
654 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
655 .WillOnce(Return(true));
656 EXPECT_CALL(*input_injector_
, StartPtr(_
)).After(authenticated
);
657 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
658 .After(authenticated
)
660 SetGnubbyAuthHandlerForTesting(client_session_
.get(),
661 gnubby_auth_handler
),
662 DeliverClientMessage(client_session_
.get(), message
),
663 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
664 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
665 EXPECT_CALL(*gnubby_auth_handler
, DeliverClientMessage(_
));
666 EXPECT_CALL(session_event_handler_
, OnSessionClosed(_
));
668 ConnectClientSession();
671 // Verifies that the client's video pipeline can be reset mid-session.
672 TEST_F(ClientSessionTest
, ResetVideoPipeline
) {
673 CreateClientSession();
675 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
676 .WillOnce(Return(true));
678 EXPECT_CALL(video_stub_
, ProcessVideoPacketPtr(_
, _
))
680 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
681 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
683 ConnectClientSession();
685 client_session_
->ResetVideoPipeline();
688 // Verifies that clients can have extensions registered, resulting in the
689 // correct capabilities being reported, and messages delivered correctly.
690 // The extension system is tested more extensively in the
691 // HostExtensionSessionManager unit-tests.
692 TEST_F(ClientSessionTest
, Extensions
) {
693 // Configure fake extensions for testing.
694 FakeExtension
extension1("ext1", "cap1");
695 extensions_
.push_back(&extension1
);
696 FakeExtension
extension2("ext2", "");
697 extensions_
.push_back(&extension2
);
698 FakeExtension
extension3("ext3", "cap3");
699 extensions_
.push_back(&extension3
);
701 // Set the second extension to request to modify the video pipeline.
702 extension2
.set_steal_video_capturer(true);
704 CreateClientSession();
706 Expectation authenticated
=
707 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
708 .WillOnce(Return(true));
710 // Verify that the ClientSession reports the correct capabilities, and mimic
711 // the client reporting an overlapping set of capabilities.
712 EXPECT_CALL(client_stub_
,
713 SetCapabilities(EqCapabilities("cap1 cap3 default")))
714 .After(authenticated
)
715 .WillOnce(SetCapabilities(client_session_
.get(), "cap1 cap4 default"));
717 // Verify that the correct extension messages are delivered, and dropped.
718 protocol::ExtensionMessage message1
;
719 message1
.set_type("ext1");
720 message1
.set_data("data");
721 protocol::ExtensionMessage message3
;
722 message3
.set_type("ext3");
723 message3
.set_data("data");
724 protocol::ExtensionMessage message4
;
725 message4
.set_type("ext4");
726 message4
.set_data("data");
727 EXPECT_CALL(session_event_handler_
, OnSessionChannelsConnected(_
))
729 DeliverClientMessage(client_session_
.get(), message1
),
730 DeliverClientMessage(client_session_
.get(), message3
),
731 DeliverClientMessage(client_session_
.get(), message4
),
732 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession
),
733 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession
)));
735 // Simulate the ClientSession connect and extension negotiation.
736 ConnectClientSession();
737 base::RunLoop().RunUntilIdle();
739 // ext1 was instantiated and sent a message, and did not wrap anything.
740 EXPECT_TRUE(extension1
.was_instantiated());
741 EXPECT_TRUE(extension1
.has_handled_message());
742 EXPECT_FALSE(extension1
.has_wrapped_video_encoder());
744 // ext2 was instantiated but not sent a message, and wrapped video encoder.
745 EXPECT_TRUE(extension2
.was_instantiated());
746 EXPECT_FALSE(extension2
.has_handled_message());
747 EXPECT_TRUE(extension2
.has_wrapped_video_encoder());
749 // ext3 was sent a message but not instantiated.
750 EXPECT_FALSE(extension3
.was_instantiated());
753 // Verifies that an extension can "steal" the video capture, in which case no
754 // VideoFramePump is instantiated.
755 TEST_F(ClientSessionTest
, StealVideoCapturer
) {
756 FakeExtension
extension("ext1", "cap1");
757 extensions_
.push_back(&extension
);
759 CreateClientSession();
761 SetMatchCapabilitiesExpectation();
763 EXPECT_CALL(session_event_handler_
, OnSessionAuthenticated(_
))
764 .WillOnce(Return(true));
766 ConnectClientSession();
768 base::RunLoop().RunUntilIdle();
770 extension
.set_steal_video_capturer(true);
771 client_session_
->ResetVideoPipeline();
773 base::RunLoop().RunUntilIdle();
775 // Verify that video control messages received while there is no video
776 // scheduler active won't crash things.
777 protocol::VideoControl video_control
;
778 video_control
.set_enable(false);
779 video_control
.set_lossless_encode(true);
780 video_control
.set_lossless_color(true);
781 client_session_
->ControlVideo(video_control
);
783 // TODO(wez): Find a way to verify that the ClientSession never captures any
784 // frames in this case.
786 DisconnectClientSession();
789 // ext1 was instantiated and wrapped the video capturer.
790 EXPECT_TRUE(extension
.was_instantiated());
791 EXPECT_TRUE(extension
.has_wrapped_video_capturer());
794 } // namespace remoting