• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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 "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/callback.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/process/process.h"
12 #include "base/process/process_handle.h"
13 #include "base/run_loop.h"
14 #include "ipc/ipc_channel.h"
15 #include "ipc/ipc_channel_proxy.h"
16 #include "ipc/ipc_listener.h"
17 #include "ipc/ipc_message.h"
18 #include "ipc/ipc_platform_file.h"
19 #include "remoting/base/auto_thread.h"
20 #include "remoting/base/auto_thread_task_runner.h"
21 #include "remoting/base/constants.h"
22 #include "remoting/host/chromoting_messages.h"
23 #include "remoting/host/desktop_process.h"
24 #include "remoting/host/desktop_session.h"
25 #include "remoting/host/desktop_session_connector.h"
26 #include "remoting/host/desktop_session_proxy.h"
27 #include "remoting/host/host_mock_objects.h"
28 #include "remoting/host/ipc_desktop_environment.h"
29 #include "remoting/host/screen_capturer_fake.h"
30 #include "remoting/protocol/protocol_mock_objects.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
34 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
35 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
36 
37 using testing::_;
38 using testing::AnyNumber;
39 using testing::AtLeast;
40 using testing::AtMost;
41 using testing::DeleteArg;
42 using testing::DoAll;
43 using testing::Return;
44 using testing::ReturnRef;
45 
46 namespace remoting {
47 
48 namespace {
49 
50 // Receives messages sent from the network process to the daemon.
51 class FakeDaemonSender : public IPC::Sender {
52  public:
FakeDaemonSender()53   FakeDaemonSender() {}
~FakeDaemonSender()54   virtual ~FakeDaemonSender() {}
55 
56   // IPC::Sender implementation.
57   virtual bool Send(IPC::Message* message) OVERRIDE;
58 
59   MOCK_METHOD3(ConnectTerminal, void(int, const ScreenResolution&, bool));
60   MOCK_METHOD1(DisconnectTerminal, void(int));
61   MOCK_METHOD2(SetScreenResolution, void(int, const ScreenResolution&));
62 
63  private:
64   void OnMessageReceived(const IPC::Message& message);
65 
66   DISALLOW_COPY_AND_ASSIGN(FakeDaemonSender);
67 };
68 
69 // Receives messages sent from the desktop process to the daemon.
70 class MockDaemonListener : public IPC::Listener {
71  public:
MockDaemonListener()72   MockDaemonListener() {}
~MockDaemonListener()73   virtual ~MockDaemonListener() {}
74 
75   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
76 
77   MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
78   MOCK_METHOD1(OnChannelConnected, void(int32));
79   MOCK_METHOD0(OnChannelError, void());
80 
81  private:
82   DISALLOW_COPY_AND_ASSIGN(MockDaemonListener);
83 };
84 
Send(IPC::Message * message)85 bool FakeDaemonSender::Send(IPC::Message* message) {
86   OnMessageReceived(*message);
87   delete message;
88   return true;
89 }
90 
OnMessageReceived(const IPC::Message & message)91 void FakeDaemonSender::OnMessageReceived(const IPC::Message& message) {
92   bool handled = true;
93   IPC_BEGIN_MESSAGE_MAP(FakeDaemonSender, message)
94     IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_ConnectTerminal,
95                         ConnectTerminal)
96     IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_DisconnectTerminal,
97                         DisconnectTerminal)
98     IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_SetScreenResolution,
99                         SetScreenResolution)
100     IPC_MESSAGE_UNHANDLED(handled = false)
101   IPC_END_MESSAGE_MAP()
102 
103   EXPECT_TRUE(handled);
104 }
105 
OnMessageReceived(const IPC::Message & message)106 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
107   bool handled = true;
108   IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
109     IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
110                         OnDesktopAttached)
111     IPC_MESSAGE_UNHANDLED(handled = false)
112   IPC_END_MESSAGE_MAP()
113 
114   EXPECT_TRUE(handled);
115   return handled;
116 }
117 
118 }  // namespace
119 
120 class IpcDesktopEnvironmentTest : public testing::Test {
121  public:
122   IpcDesktopEnvironmentTest();
123   virtual ~IpcDesktopEnvironmentTest();
124 
125   virtual void SetUp() OVERRIDE;
126 
127   void ConnectTerminal(int terminal_id,
128                        const ScreenResolution& resolution,
129                        bool virtual_terminal);
130   void DisconnectTerminal(int terminal_id);
131 
132   // Creates a DesktopEnvironment with a fake webrtc::ScreenCapturer, to mock
133   // DesktopEnvironmentFactory::Create().
134   DesktopEnvironment* CreateDesktopEnvironment();
135 
136   // Creates a dummy InputInjector, to mock
137   // DesktopEnvironment::CreateInputInjector().
138   InputInjector* CreateInputInjector();
139 
140   // Creates a fake webrtc::ScreenCapturer, to mock
141   // DesktopEnvironment::CreateVideoCapturer().
142   webrtc::ScreenCapturer* CreateVideoCapturer();
143 
144   void DeleteDesktopEnvironment();
145 
146   // Forwards |event| to |clipboard_stub_|.
147   void ReflectClipboardEvent(const protocol::ClipboardEvent& event);
148 
149  protected:
150   // Creates and starts an instance of desktop process object.
151   void CreateDesktopProcess();
152 
153   // Destroys the desktop process object created by CreateDesktopProcess().
154   void DestoyDesktopProcess();
155 
156   void OnDisconnectCallback();
157 
158   // Invoked when ChromotingDesktopDaemonMsg_DesktopAttached message is
159   // received.
160   void OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe);
161 
162   // The main message loop.
163   base::MessageLoop message_loop_;
164 
165   // Runs until |desktop_session_proxy_| is connected to the desktop.
166   scoped_ptr<base::RunLoop> setup_run_loop_;
167 
168   // Runs until there are references to |task_runner_|.
169   base::RunLoop main_run_loop_;
170 
171   scoped_refptr<AutoThreadTaskRunner> task_runner_;
172   scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
173 
174   std::string client_jid_;
175 
176   // Clipboard stub that receives clipboard events from the desktop process.
177   protocol::ClipboardStub* clipboard_stub_;
178 
179   // The daemons's end of the daemon-to-desktop channel.
180   scoped_ptr<IPC::ChannelProxy> desktop_channel_;
181 
182   // Name of the daemon-to-desktop channel.
183   std::string desktop_channel_name_;
184 
185   // Delegate that is passed to |desktop_channel_|.
186   MockDaemonListener desktop_listener_;
187 
188   FakeDaemonSender daemon_channel_;
189 
190   scoped_ptr<IpcDesktopEnvironmentFactory> desktop_environment_factory_;
191   scoped_ptr<DesktopEnvironment> desktop_environment_;
192 
193   // The IPC input injector.
194   scoped_ptr<InputInjector> input_injector_;
195 
196   // The IPC screen controls.
197   scoped_ptr<ScreenControls> screen_controls_;
198 
199   // The IPC screen capturer.
200   scoped_ptr<webrtc::ScreenCapturer> video_capturer_;
201 
202   // Represents the desktop process running in a user session.
203   scoped_ptr<DesktopProcess> desktop_process_;
204 
205   // Input injector owned by |desktop_process_|.
206   MockInputInjector* remote_input_injector_;
207 
208   // The last |terminal_id| passed to ConnectTermina();
209   int terminal_id_;
210 
211   webrtc::MockScreenCapturerCallback screen_capturer_callback_;
212 
213   MockClientSessionControl client_session_control_;
214   base::WeakPtrFactory<ClientSessionControl> client_session_control_factory_;
215 };
216 
IpcDesktopEnvironmentTest()217 IpcDesktopEnvironmentTest::IpcDesktopEnvironmentTest()
218     : message_loop_(base::MessageLoop::TYPE_UI),
219       client_jid_("user@domain/rest-of-jid"),
220       clipboard_stub_(NULL),
221       remote_input_injector_(NULL),
222       terminal_id_(-1),
223       client_session_control_factory_(&client_session_control_) {
224 }
225 
~IpcDesktopEnvironmentTest()226 IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() {
227 }
228 
SetUp()229 void IpcDesktopEnvironmentTest::SetUp() {
230   // Arrange to run |message_loop_| until no components depend on it.
231   task_runner_ = new AutoThreadTaskRunner(
232       message_loop_.message_loop_proxy(), main_run_loop_.QuitClosure());
233 
234   io_task_runner_ = AutoThread::CreateWithType(
235       "IPC thread", task_runner_, base::MessageLoop::TYPE_IO);
236 
237   setup_run_loop_.reset(new base::RunLoop());
238 
239   // Set expectation that the DaemonProcess will send DesktopAttached message
240   // once it is ready.
241   EXPECT_CALL(desktop_listener_, OnChannelConnected(_))
242       .Times(AnyNumber());
243   EXPECT_CALL(desktop_listener_, OnDesktopAttached(_))
244       .Times(AnyNumber())
245       .WillRepeatedly(Invoke(this,
246                              &IpcDesktopEnvironmentTest::OnDesktopAttached));
247   EXPECT_CALL(desktop_listener_, OnChannelError())
248       .Times(AnyNumber())
249       .WillOnce(Invoke(this,
250                        &IpcDesktopEnvironmentTest::DestoyDesktopProcess));
251 
252   // Intercept requests to connect and disconnect a terminal.
253   EXPECT_CALL(daemon_channel_, ConnectTerminal(_, _, _))
254       .Times(AnyNumber())
255       .WillRepeatedly(Invoke(this,
256                              &IpcDesktopEnvironmentTest::ConnectTerminal));
257   EXPECT_CALL(daemon_channel_, DisconnectTerminal(_))
258       .Times(AnyNumber())
259       .WillRepeatedly(Invoke(this,
260                              &IpcDesktopEnvironmentTest::DisconnectTerminal));
261 
262   EXPECT_CALL(client_session_control_, client_jid())
263       .Times(AnyNumber())
264       .WillRepeatedly(ReturnRef(client_jid_));
265   EXPECT_CALL(client_session_control_, DisconnectSession())
266       .Times(AnyNumber())
267       .WillRepeatedly(Invoke(
268           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
269   EXPECT_CALL(client_session_control_, OnLocalMouseMoved(_))
270       .Times(0);
271   EXPECT_CALL(client_session_control_, SetDisableInputs(_))
272       .Times(0);
273 
274   // Create a desktop environment instance.
275   desktop_environment_factory_.reset(new IpcDesktopEnvironmentFactory(
276       task_runner_,
277       task_runner_,
278       task_runner_,
279       io_task_runner_,
280       &daemon_channel_));
281   desktop_environment_ = desktop_environment_factory_->Create(
282       client_session_control_factory_.GetWeakPtr());
283 
284   screen_controls_ = desktop_environment_->CreateScreenControls();
285 
286   // Create the input injector.
287   input_injector_ = desktop_environment_->CreateInputInjector();
288 
289   // Create the screen capturer.
290   video_capturer_ =
291       desktop_environment_->CreateVideoCapturer();
292 
293   desktop_environment_->SetCapabilities(std::string());
294 }
295 
ConnectTerminal(int terminal_id,const ScreenResolution & resolution,bool virtual_terminal)296 void IpcDesktopEnvironmentTest::ConnectTerminal(
297     int terminal_id,
298     const ScreenResolution& resolution,
299     bool virtual_terminal) {
300   EXPECT_NE(terminal_id_, terminal_id);
301 
302   terminal_id_ = terminal_id;
303   CreateDesktopProcess();
304 }
305 
DisconnectTerminal(int terminal_id)306 void IpcDesktopEnvironmentTest::DisconnectTerminal(int terminal_id) {
307   EXPECT_EQ(terminal_id_, terminal_id);
308 
309   // The IPC desktop environment is fully destroyed now. Release the remaining
310   // task runners.
311   desktop_environment_factory_.reset();
312 }
313 
CreateDesktopEnvironment()314 DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() {
315   MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
316   EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
317       .Times(0);
318   EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
319       .Times(AtMost(1))
320       .WillOnce(Invoke(
321           this, &IpcDesktopEnvironmentTest::CreateInputInjector));
322   EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
323       .Times(AtMost(1));
324   EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
325       .Times(AtMost(1))
326       .WillOnce(Invoke(
327           this, &IpcDesktopEnvironmentTest::CreateVideoCapturer));
328   EXPECT_CALL(*desktop_environment, GetCapabilities())
329       .Times(AtMost(1));
330   EXPECT_CALL(*desktop_environment, SetCapabilities(_))
331       .Times(AtMost(1));
332 
333   // Let tests know that the remote desktop environment is created.
334   message_loop_.PostTask(FROM_HERE, setup_run_loop_->QuitClosure());
335 
336   return desktop_environment;
337 }
338 
CreateInputInjector()339 InputInjector* IpcDesktopEnvironmentTest::CreateInputInjector() {
340   EXPECT_TRUE(remote_input_injector_ == NULL);
341   remote_input_injector_ = new MockInputInjector();
342 
343   EXPECT_CALL(*remote_input_injector_, StartPtr(_));
344   return remote_input_injector_;
345 }
346 
CreateVideoCapturer()347 webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
348   return new ScreenCapturerFake();
349 }
350 
DeleteDesktopEnvironment()351 void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
352   input_injector_.reset();
353   screen_controls_.reset();
354   video_capturer_.reset();
355 
356   // Trigger DisconnectTerminal().
357   desktop_environment_.reset();
358 }
359 
ReflectClipboardEvent(const protocol::ClipboardEvent & event)360 void IpcDesktopEnvironmentTest::ReflectClipboardEvent(
361     const protocol::ClipboardEvent& event) {
362   clipboard_stub_->InjectClipboardEvent(event);
363 }
364 
CreateDesktopProcess()365 void IpcDesktopEnvironmentTest::CreateDesktopProcess() {
366   EXPECT_TRUE(task_runner_.get());
367   EXPECT_TRUE(io_task_runner_.get());
368 
369   // Create the daemon end of the daemon-to-desktop channel.
370   desktop_channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID();
371   desktop_channel_.reset(
372       new IPC::ChannelProxy(IPC::ChannelHandle(desktop_channel_name_),
373                             IPC::Channel::MODE_SERVER,
374                             &desktop_listener_,
375                             io_task_runner_.get()));
376 
377   // Create and start the desktop process.
378   desktop_process_.reset(new DesktopProcess(task_runner_,
379                                             io_task_runner_,
380                                             desktop_channel_name_));
381 
382   scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory(
383       new MockDesktopEnvironmentFactory());
384   EXPECT_CALL(*desktop_environment_factory, CreatePtr())
385       .Times(AnyNumber())
386       .WillRepeatedly(Invoke(
387           this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment));
388   EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture())
389       .Times(AnyNumber())
390       .WillRepeatedly(Return(false));
391 
392   EXPECT_TRUE(desktop_process_->Start(
393       desktop_environment_factory.PassAs<DesktopEnvironmentFactory>()));
394 }
395 
DestoyDesktopProcess()396 void IpcDesktopEnvironmentTest::DestoyDesktopProcess() {
397   desktop_channel_.reset();
398   if (desktop_process_) {
399     desktop_process_->OnChannelError();
400     desktop_process_.reset();
401   }
402   remote_input_injector_ = NULL;
403 }
404 
OnDisconnectCallback()405 void IpcDesktopEnvironmentTest::OnDisconnectCallback() {
406   DeleteDesktopEnvironment();
407 }
408 
OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe)409 void IpcDesktopEnvironmentTest::OnDesktopAttached(
410     IPC::PlatformFileForTransit desktop_pipe) {
411 
412   // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe.
413   desktop_environment_factory_->OnDesktopSessionAgentAttached(
414       terminal_id_, base::GetCurrentProcessHandle(), desktop_pipe);
415 }
416 
417 // Runs until the desktop is attached and exits immediately after that.
TEST_F(IpcDesktopEnvironmentTest,Basic)418 TEST_F(IpcDesktopEnvironmentTest, Basic) {
419   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
420       new protocol::MockClipboardStub());
421   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
422       .Times(0);
423 
424   // Start the input injector and screen capturer.
425   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
426 
427   // Run the message loop until the desktop is attached.
428   setup_run_loop_->Run();
429 
430   // Input injector should receive no events.
431   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
432       .Times(0);
433   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
434       .Times(0);
435   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
436       .Times(0);
437 
438   // Stop the test.
439   DeleteDesktopEnvironment();
440 
441   task_runner_ = NULL;
442   io_task_runner_ = NULL;
443   main_run_loop_.Run();
444 }
445 
446 // Tests that the video capturer receives a frame over IPC.
TEST_F(IpcDesktopEnvironmentTest,CaptureFrame)447 TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) {
448   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
449       new protocol::MockClipboardStub());
450   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
451       .Times(0);
452 
453   // Start the input injector and screen capturer.
454   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
455   video_capturer_->Start(&screen_capturer_callback_);
456 
457   // Run the message loop until the desktop is attached.
458   setup_run_loop_->Run();
459 
460   // Input injector should receive no events.
461   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
462       .Times(0);
463   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
464       .Times(0);
465   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
466       .Times(0);
467 
468   // Stop the test when the first frame is captured.
469   EXPECT_CALL(screen_capturer_callback_, OnCaptureCompleted(_))
470       .WillOnce(DoAll(
471           DeleteArg<0>(),
472           InvokeWithoutArgs(
473               this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)));
474 
475   // Capture a single frame.
476   video_capturer_->Capture(webrtc::DesktopRegion());
477 
478   task_runner_ = NULL;
479   io_task_runner_ = NULL;
480   main_run_loop_.Run();
481 }
482 
483 // Tests that attaching to a new desktop works.
TEST_F(IpcDesktopEnvironmentTest,Reattach)484 TEST_F(IpcDesktopEnvironmentTest, Reattach) {
485   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
486       new protocol::MockClipboardStub());
487   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
488       .Times(0);
489 
490   // Start the input injector and screen capturer.
491   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
492   video_capturer_->Start(&screen_capturer_callback_);
493 
494   // Run the message loop until the desktop is attached.
495   setup_run_loop_->Run();
496 
497   // Create and start a new desktop process object.
498   setup_run_loop_.reset(new base::RunLoop());
499   DestoyDesktopProcess();
500   CreateDesktopProcess();
501   setup_run_loop_->Run();
502 
503   // Input injector should receive no events.
504   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
505       .Times(0);
506   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
507       .Times(0);
508   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
509       .Times(0);
510 
511   // Stop the test.
512   DeleteDesktopEnvironment();
513 
514   task_runner_ = NULL;
515   io_task_runner_ = NULL;
516   main_run_loop_.Run();
517 }
518 
519 // Tests injection of clipboard events.
TEST_F(IpcDesktopEnvironmentTest,InjectClipboardEvent)520 TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) {
521   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
522       new protocol::MockClipboardStub());
523   clipboard_stub_ = clipboard_stub.get();
524 
525   // Stop the test when a clipboard event is received from the desktop process.
526   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
527       .Times(1)
528       .WillOnce(InvokeWithoutArgs(
529           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
530 
531   // Start the input injector and screen capturer.
532   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
533   video_capturer_->Start(&screen_capturer_callback_);
534 
535   // Run the message loop until the desktop is attached.
536   setup_run_loop_->Run();
537 
538   // Expect a single clipboard event.
539   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
540       .Times(1)
541       .WillOnce(Invoke(this,
542                        &IpcDesktopEnvironmentTest::ReflectClipboardEvent));
543   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
544       .Times(0);
545   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
546       .Times(0);
547 
548   // Send a clipboard event.
549   protocol::ClipboardEvent event;
550   event.set_mime_type(kMimeTypeTextUtf8);
551   event.set_data("a");
552   input_injector_->InjectClipboardEvent(event);
553 
554   task_runner_ = NULL;
555   io_task_runner_ = NULL;
556   main_run_loop_.Run();
557 }
558 
559 // Tests injection of key events.
TEST_F(IpcDesktopEnvironmentTest,InjectKeyEvent)560 TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) {
561   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
562       new protocol::MockClipboardStub());
563   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
564       .Times(0);
565 
566   // Start the input injector and screen capturer.
567   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
568   video_capturer_->Start(&screen_capturer_callback_);
569 
570   // Run the message loop until the desktop is attached.
571   setup_run_loop_->Run();
572 
573   // Expect a single key event.
574   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
575       .Times(0);
576   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
577       .Times(AtLeast(1))
578       .WillRepeatedly(InvokeWithoutArgs(
579           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
580   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
581       .Times(0);
582 
583   // Send a key event.
584   protocol::KeyEvent event;
585   event.set_usb_keycode(0x070004);
586   event.set_pressed(true);
587   input_injector_->InjectKeyEvent(event);
588 
589   task_runner_ = NULL;
590   io_task_runner_ = NULL;
591   main_run_loop_.Run();
592 }
593 
594 // Tests injection of mouse events.
TEST_F(IpcDesktopEnvironmentTest,InjectMouseEvent)595 TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
596   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
597       new protocol::MockClipboardStub());
598   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
599       .Times(0);
600 
601   // Start the input injector and screen capturer.
602   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
603   video_capturer_->Start(&screen_capturer_callback_);
604 
605   // Run the message loop until the desktop is attached.
606   setup_run_loop_->Run();
607 
608   // Expect a single mouse event.
609   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
610       .Times(0);
611   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
612       .Times(0);
613   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
614       .Times(1)
615       .WillOnce(InvokeWithoutArgs(
616           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
617 
618   // Send a mouse event.
619   protocol::MouseEvent event;
620   event.set_x(0);
621   event.set_y(0);
622   input_injector_->InjectMouseEvent(event);
623 
624   task_runner_ = NULL;
625   io_task_runner_ = NULL;
626   main_run_loop_.Run();
627 }
628 
629 // Tests that setting the desktop resolution works.
TEST_F(IpcDesktopEnvironmentTest,SetScreenResolution)630 TEST_F(IpcDesktopEnvironmentTest, SetScreenResolution) {
631   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
632       new protocol::MockClipboardStub());
633   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
634       .Times(0);
635 
636   // Start the input injector and screen capturer.
637   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
638   video_capturer_->Start(&screen_capturer_callback_);
639 
640   // Run the message loop until the desktop is attached.
641   setup_run_loop_->Run();
642 
643   EXPECT_CALL(daemon_channel_, SetScreenResolution(_, _))
644       .Times(1)
645       .WillOnce(InvokeWithoutArgs(
646           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
647 
648   // Change the desktop resolution.
649   screen_controls_->SetScreenResolution(ScreenResolution(
650       webrtc::DesktopSize(100, 100),
651       webrtc::DesktopVector(96, 96)));
652 
653   task_runner_ = NULL;
654   io_task_runner_ = NULL;
655   main_run_loop_.Run();
656 }
657 
658 }  // namespace remoting
659