Home | History | Annotate | Download | only in host
      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
    818