Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / remoting / host / client_session_unittest.cc
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.
4
5 #include <algorithm>
6 #include <string>
7 #include <vector>
8
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"
31
32 namespace remoting {
33
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;
41
42 using testing::_;
43 using testing::AnyNumber;
44 using testing::AtMost;
45 using testing::CreateFunctor;
46 using testing::DeleteArg;
47 using testing::DoAll;
48 using testing::Expectation;
49 using testing::Invoke;
50 using testing::Return;
51 using testing::ReturnRef;
52 using testing::Sequence;
53 using testing::StrEq;
54 using testing::StrictMock;
55
56 namespace {
57
58 const char kDefaultTestCapability[] = "default";
59
60 ACTION_P2(InjectClipboardEvent, connection, event) {
61   connection->clipboard_stub()->InjectClipboardEvent(event);
62 }
63
64 ACTION_P2(InjectKeyEvent, connection, event) {
65   connection->input_stub()->InjectKeyEvent(event);
66 }
67
68 ACTION_P2(InjectMouseEvent, connection, event) {
69   connection->input_stub()->InjectMouseEvent(event);
70 }
71
72 ACTION_P2(LocalMouseMoved, client_session, event) {
73   client_session->OnLocalMouseMoved(
74       webrtc::DesktopVector(event.x(), event.y()));
75 }
76
77 ACTION_P2(SetGnubbyAuthHandlerForTesting, client_session, gnubby_auth_handler) {
78   client_session->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler);
79 }
80
81 ACTION_P2(DeliverClientMessage, client_session, message) {
82   client_session->DeliverClientMessage(message);
83 }
84
85 ACTION_P2(SetCapabilities, client_session, capabilities) {
86   protocol::Capabilities capabilities_message;
87   capabilities_message.set_capabilities(capabilities);
88   client_session->SetCapabilities(capabilities_message);
89 }
90
91 MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") {
92   return arg.usb_keycode() == (unsigned int)usb_keycode &&
93          arg.pressed() == pressed;
94 }
95
96 MATCHER_P2(EqualsMouseEvent, x, y, "") {
97   return arg.x() == x && arg.y() == y;
98 }
99
100 MATCHER_P2(EqualsMouseButtonEvent, button, down, "") {
101   return arg.button() == button && arg.button_down() == down;
102 }
103
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())
108     return false;
109
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;
117 }
118
119 }  // namespace
120
121 class ClientSessionTest : public testing::Test {
122  public:
123   ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
124
125   virtual void SetUp() OVERRIDE;
126   virtual void TearDown() OVERRIDE;
127
128   // Creates the client session.
129   void CreateClientSession();
130
131   // Disconnects the client session.
132   void DisconnectClientSession();
133
134   // Stops and releases the ClientSession, allowing the MessageLoop to quit.
135   void StopClientSession();
136
137  protected:
138   // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
139   // DesktopEnvironmentFactory::Create().
140   DesktopEnvironment* CreateDesktopEnvironment();
141
142   // Returns |input_injector_| created and initialized by SetUp(), to mock
143   // DesktopEnvironment::CreateInputInjector().
144   InputInjector* CreateInputInjector();
145
146   // Creates a fake webrtc::DesktopCapturer, to mock
147   // DesktopEnvironment::CreateVideoCapturer().
148   webrtc::DesktopCapturer* CreateVideoCapturer();
149
150   // Creates a MockMouseCursorMonitor, to mock
151   // DesktopEnvironment::CreateMouseCursorMonitor
152   webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
153
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();
158
159   // Creates expectation that simulates client supporting same capabilities as
160   // host.
161   void SetMatchCapabilitiesExpectation();
162
163   // Creates expectations to send an extension message and to disconnect
164   // afterwards.
165   void SetSendMessageAndDisconnectExpectation(const std::string& message_type);
166
167   // Message loop that will process all ClientSession tasks.
168   base::MessageLoop message_loop_;
169
170   // AutoThreadTaskRunner on which |client_session_| will be run.
171   scoped_refptr<AutoThreadTaskRunner> task_runner_;
172
173   // Used to run |message_loop_| after each test, until no objects remain that
174   // require it.
175   base::RunLoop run_loop_;
176
177   // HostExtensions to pass when creating the ClientSession. Caller retains
178   // ownership of the HostExtensions themselves.
179   std::vector<HostExtension*> extensions_;
180
181   // ClientSession instance under test.
182   scoped_ptr<ClientSession> client_session_;
183
184   // ClientSession::EventHandler mock for use in tests.
185   MockClientSessionEventHandler session_event_handler_;
186
187   // Storage for values to be returned by the protocol::Session mock.
188   SessionConfig session_config_;
189   const std::string client_jid_;
190
191   // Stubs returned to |client_session_| components by |connection_|.
192   MockClientStub client_stub_;
193   MockVideoStub video_stub_;
194
195   // DesktopEnvironment owns |input_injector_|, but input injection tests need
196   // to express expectations on it.
197   scoped_ptr<MockInputInjector> input_injector_;
198
199   // ClientSession owns |connection_| but tests need it to inject fake events.
200   MockConnectionToClient* connection_;
201
202   scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_;
203 };
204
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());
209
210   desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
211   EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
212       .Times(AnyNumber())
213       .WillRepeatedly(Invoke(this,
214                              &ClientSessionTest::CreateDesktopEnvironment));
215   EXPECT_CALL(*desktop_environment_factory_, SupportsAudioCapture())
216       .Times(AnyNumber())
217       .WillRepeatedly(Return(false));
218
219   input_injector_.reset(new MockInputInjector());
220
221   session_config_ = SessionConfig::ForTest();
222 }
223
224 void ClientSessionTest::TearDown() {
225   // Clear out |task_runner_| reference so the loop can quit, and run it until
226   // it does.
227   task_runner_ = NULL;
228   run_loop_.Run();
229 }
230
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(_));
237
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();
248
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(),
259       base::TimeDelta(),
260       NULL,
261       extensions_));
262 }
263
264 void ClientSessionTest::DisconnectClientSession() {
265   client_session_->DisconnectSession();
266   // MockSession won't trigger OnConnectionClosed, so fake it.
267   client_session_->OnConnectionClosed(client_session_->connection(),
268                                       protocol::OK);
269 }
270
271 void ClientSessionTest::StopClientSession() {
272   client_session_.reset();
273
274   desktop_environment_factory_.reset();
275 }
276
277 DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
278   MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
279   EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
280       .Times(0);
281   EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
282       .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector));
283   EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
284       .Times(AtMost(1));
285   EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
286       .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
287   EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
288       .WillRepeatedly(
289           Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor));
290   EXPECT_CALL(*desktop_environment, GetCapabilities())
291       .Times(AtMost(1))
292        .WillOnce(Return(kDefaultTestCapability));
293   EXPECT_CALL(*desktop_environment, SetCapabilities(_))
294       .Times(AtMost(1));
295
296   return desktop_environment;
297 }
298
299 InputInjector* ClientSessionTest::CreateInputInjector() {
300   EXPECT_TRUE(input_injector_);
301   return input_injector_.release();
302 }
303
304 webrtc::DesktopCapturer* ClientSessionTest::CreateVideoCapturer() {
305   return new FakeDesktopCapturer();
306 }
307
308 webrtc::MouseCursorMonitor* ClientSessionTest::CreateMouseCursorMonitor() {
309   return new FakeMouseCursorMonitor();
310 }
311
312 void ClientSessionTest::ConnectClientSession() {
313   client_session_->OnConnectionAuthenticated(client_session_->connection());
314   client_session_->OnConnectionChannelsConnected(client_session_->connection());
315 }
316
317 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
318   // Set the client to report the same capabilities as the host.
319   EXPECT_CALL(client_stub_, SetCapabilities(_))
320       .Times(AtMost(1))
321       .WillOnce(Invoke(client_session_.get(), &ClientSession::SetCapabilities));
322 }
323
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");
329
330   Expectation authenticated =
331       EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
332       .WillOnce(Return(true));
333   EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
334       .After(authenticated)
335       .WillOnce(DoAll(
336           DeliverClientMessage(client_session_.get(), message),
337           InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
338           InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
339 }
340
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);
344 }
345
346 TEST_F(ClientSessionTest, ClipboardStubFilter) {
347   CreateClientSession();
348
349   protocol::ClipboardEvent clipboard_event1;
350   clipboard_event1.set_mime_type(kMimeTypeTextUtf8);
351   clipboard_event1.set_data("a");
352
353   protocol::ClipboardEvent clipboard_event2;
354   clipboard_event2.set_mime_type(kMimeTypeTextUtf8);
355   clipboard_event2.set_data("b");
356
357   protocol::ClipboardEvent clipboard_event3;
358   clipboard_event3.set_mime_type(kMimeTypeTextUtf8);
359   clipboard_event3.set_data("c");
360
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);
368
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.
372   Sequence s;
373   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
374       .InSequence(s)
375       .After(authenticated)
376       .WillOnce(DoAll(
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")))
386       .InSequence(s);
387   EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
388       .InSequence(s);
389
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);
393
394   ConnectClientSession();
395 }
396
397 TEST_F(ClientSessionTest, InputStubFilter) {
398   CreateClientSession();
399
400   protocol::KeyEvent key_event1;
401   key_event1.set_pressed(true);
402   key_event1.set_usb_keycode(1);
403
404   protocol::KeyEvent key_event2_down;
405   key_event2_down.set_pressed(true);
406   key_event2_down.set_usb_keycode(2);
407
408   protocol::KeyEvent key_event2_up;
409   key_event2_up.set_pressed(false);
410   key_event2_up.set_usb_keycode(2);
411
412   protocol::KeyEvent key_event3;
413   key_event3.set_pressed(true);
414   key_event3.set_usb_keycode(3);
415
416   protocol::MouseEvent mouse_event1;
417   mouse_event1.set_x(100);
418   mouse_event1.set_y(101);
419
420   protocol::MouseEvent mouse_event2;
421   mouse_event2.set_x(200);
422   mouse_event2.set_y(201);
423
424   protocol::MouseEvent mouse_event3;
425   mouse_event3.set_x(300);
426   mouse_event3.set_y(301);
427
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);
435
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.
439   Sequence s;
440   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
441       .InSequence(s)
442       .After(authenticated)
443       .WillOnce(DoAll(
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)))
455       .InSequence(s);
456   EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
457       .InSequence(s);
458   EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
459       .InSequence(s);
460   EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
461       .InSequence(s);
462
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);
467
468   ConnectClientSession();
469 }
470
471 TEST_F(ClientSessionTest, LocalInputTest) {
472   CreateClientSession();
473
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);
483
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);
491
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.
495   Sequence s;
496   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
497       .InSequence(s)
498       .After(authenticated)
499       .WillOnce(DoAll(
500           // This event should get through to the input stub.
501           InjectMouseEvent(connection_, mouse_event1),
502 #if !defined(OS_WIN)
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
511           // event.
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)))
518       .InSequence(s);
519   EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
520       .InSequence(s);
521   EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
522       .InSequence(s);
523
524   ConnectClientSession();
525 }
526
527 TEST_F(ClientSessionTest, RestoreEventState) {
528   CreateClientSession();
529
530   protocol::KeyEvent key1;
531   key1.set_pressed(true);
532   key1.set_usb_keycode(1);
533
534   protocol::KeyEvent key2;
535   key2.set_pressed(true);
536   key2.set_usb_keycode(2);
537
538   protocol::MouseEvent mousedown;
539   mousedown.set_button(protocol::MouseEvent::BUTTON_LEFT);
540   mousedown.set_button_down(true);
541
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);
549
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.
553   Sequence s;
554   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
555       .InSequence(s)
556       .After(authenticated)
557       .WillOnce(DoAll(
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)))
564       .InSequence(s);
565   EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
566       .InSequence(s);
567   EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
568       protocol::MouseEvent::BUTTON_LEFT, true)))
569       .InSequence(s);
570   EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, false)))
571       .InSequence(s);
572   EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
573       .InSequence(s);
574   EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
575       protocol::MouseEvent::BUTTON_LEFT, false)))
576       .InSequence(s);
577   EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
578       .InSequence(s);
579
580   ConnectClientSession();
581 }
582
583 TEST_F(ClientSessionTest, ClampMouseEvents) {
584   CreateClientSession();
585
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);
595
596   Expectation connected = authenticated;
597
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 };
602
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]);
609
610       if (i == 0 && j == 0) {
611         // Inject the 1st event once a video packet has been received.
612         connected =
613             EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
614                 .After(connected)
615                 .WillOnce(InjectMouseEvent(connection_, injected_event));
616       } else {
617         // Every next event is injected once the previous event has been
618         // received.
619         connected =
620             EXPECT_CALL(*input_injector_,
621                         InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
622                                                           expected_event.y())))
623                 .After(connected)
624                 .WillOnce(InjectMouseEvent(connection_, injected_event));
625       }
626
627       expected_event.set_x(expected_x[i]);
628       expected_event.set_y(expected_y[j]);
629     }
630   }
631
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())))
636       .After(connected)
637       .WillOnce(DoAll(
638           InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
639           InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
640
641   ConnectClientSession();
642 }
643
644 TEST_F(ClientSessionTest, NoGnubbyAuth) {
645   CreateClientSession();
646
647   protocol::ExtensionMessage message;
648   message.set_type("gnubby-auth");
649   message.set_data("test");
650
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)
657       .WillOnce(DoAll(
658            DeliverClientMessage(client_session_.get(), message),
659            InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
660            InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
661   EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
662
663   ConnectClientSession();
664 }
665
666 TEST_F(ClientSessionTest, EnableGnubbyAuth) {
667   CreateClientSession();
668
669   // Lifetime controlled by object under test.
670   MockGnubbyAuthHandler* gnubby_auth_handler = new MockGnubbyAuthHandler();
671
672   protocol::ExtensionMessage message;
673   message.set_type("gnubby-auth");
674   message.set_data("test");
675
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)
682       .WillOnce(DoAll(
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(_));
690
691   ConnectClientSession();
692 }
693
694 // Verifies that the client's video pipeline can be reset mid-session.
695 TEST_F(ClientSessionTest, ResetVideoPipeline) {
696   CreateClientSession();
697
698   EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
699       .WillOnce(Return(true));
700
701   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
702       .WillOnce(DoAll(
703           InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
704           InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
705
706   ConnectClientSession();
707
708   client_session_->ResetVideoPipeline();
709 }
710
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);
723
724   // Set the second extension to request to modify the video pipeline.
725   extension2.set_steal_video_capturer(true);
726
727   CreateClientSession();
728
729   Expectation authenticated =
730       EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
731           .WillOnce(Return(true));
732
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"));
739
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(_))
751       .WillOnce(DoAll(
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)));
757
758   // Simulate the ClientSession connect and extension negotiation.
759   ConnectClientSession();
760   base::RunLoop().RunUntilIdle();
761
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());
766
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());
771
772   // ext3 was sent a message but not instantiated.
773   EXPECT_FALSE(extension3.was_instantiated());
774 }
775
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);
781
782   CreateClientSession();
783
784   SetMatchCapabilitiesExpectation();
785
786   EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
787       .WillOnce(Return(true));
788
789   ConnectClientSession();
790
791   base::RunLoop().RunUntilIdle();
792
793   extension.set_steal_video_capturer(true);
794   client_session_->ResetVideoPipeline();
795
796   base::RunLoop().RunUntilIdle();
797
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);
805
806   // TODO(wez): Find a way to verify that the ClientSession never captures any
807   // frames in this case.
808
809   DisconnectClientSession();
810   StopClientSession();
811
812   // ext1 was instantiated and wrapped the video capturer.
813   EXPECT_TRUE(extension.was_instantiated());
814   EXPECT_TRUE(extension.has_wrapped_video_capturer());
815 }
816
817 }  // namespace remoting