• 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::MessageLoopForUI 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     : client_jid_("user@domain/rest-of-jid"),
219       clipboard_stub_(NULL),
220       remote_input_injector_(NULL),
221       terminal_id_(-1),
222       client_session_control_factory_(&client_session_control_) {
223 }
224 
~IpcDesktopEnvironmentTest()225 IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() {
226 }
227 
SetUp()228 void IpcDesktopEnvironmentTest::SetUp() {
229   // Arrange to run |message_loop_| until no components depend on it.
230   task_runner_ = new AutoThreadTaskRunner(
231       message_loop_.message_loop_proxy(), main_run_loop_.QuitClosure());
232 
233   io_task_runner_ = AutoThread::CreateWithType(
234       "IPC thread", task_runner_, base::MessageLoop::TYPE_IO);
235 
236   setup_run_loop_.reset(new base::RunLoop());
237 
238   // Set expectation that the DaemonProcess will send DesktopAttached message
239   // once it is ready.
240   EXPECT_CALL(desktop_listener_, OnChannelConnected(_))
241       .Times(AnyNumber());
242   EXPECT_CALL(desktop_listener_, OnDesktopAttached(_))
243       .Times(AnyNumber())
244       .WillRepeatedly(Invoke(this,
245                              &IpcDesktopEnvironmentTest::OnDesktopAttached));
246   EXPECT_CALL(desktop_listener_, OnChannelError())
247       .Times(AnyNumber())
248       .WillOnce(Invoke(this,
249                        &IpcDesktopEnvironmentTest::DestoyDesktopProcess));
250 
251   // Intercept requests to connect and disconnect a terminal.
252   EXPECT_CALL(daemon_channel_, ConnectTerminal(_, _, _))
253       .Times(AnyNumber())
254       .WillRepeatedly(Invoke(this,
255                              &IpcDesktopEnvironmentTest::ConnectTerminal));
256   EXPECT_CALL(daemon_channel_, DisconnectTerminal(_))
257       .Times(AnyNumber())
258       .WillRepeatedly(Invoke(this,
259                              &IpcDesktopEnvironmentTest::DisconnectTerminal));
260 
261   EXPECT_CALL(client_session_control_, client_jid())
262       .Times(AnyNumber())
263       .WillRepeatedly(ReturnRef(client_jid_));
264   EXPECT_CALL(client_session_control_, DisconnectSession())
265       .Times(AnyNumber())
266       .WillRepeatedly(Invoke(
267           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
268   EXPECT_CALL(client_session_control_, OnLocalMouseMoved(_))
269       .Times(0);
270   EXPECT_CALL(client_session_control_, SetDisableInputs(_))
271       .Times(0);
272 
273   // Create a desktop environment instance.
274   desktop_environment_factory_.reset(new IpcDesktopEnvironmentFactory(
275       task_runner_,
276       task_runner_,
277       task_runner_,
278       io_task_runner_,
279       &daemon_channel_));
280   desktop_environment_ = desktop_environment_factory_->Create(
281       client_session_control_factory_.GetWeakPtr());
282 
283   screen_controls_ = desktop_environment_->CreateScreenControls();
284 
285   // Create the input injector.
286   input_injector_ = desktop_environment_->CreateInputInjector();
287 
288   // Create the screen capturer.
289   video_capturer_ =
290       desktop_environment_->CreateVideoCapturer();
291 
292   desktop_environment_->SetCapabilities(std::string());
293 }
294 
ConnectTerminal(int terminal_id,const ScreenResolution & resolution,bool virtual_terminal)295 void IpcDesktopEnvironmentTest::ConnectTerminal(
296     int terminal_id,
297     const ScreenResolution& resolution,
298     bool virtual_terminal) {
299   EXPECT_NE(terminal_id_, terminal_id);
300 
301   terminal_id_ = terminal_id;
302   CreateDesktopProcess();
303 }
304 
DisconnectTerminal(int terminal_id)305 void IpcDesktopEnvironmentTest::DisconnectTerminal(int terminal_id) {
306   EXPECT_EQ(terminal_id_, terminal_id);
307 
308   // The IPC desktop environment is fully destroyed now. Release the remaining
309   // task runners.
310   desktop_environment_factory_.reset();
311 }
312 
CreateDesktopEnvironment()313 DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() {
314   MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
315   EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
316       .Times(0);
317   EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
318       .Times(AtMost(1))
319       .WillOnce(Invoke(
320           this, &IpcDesktopEnvironmentTest::CreateInputInjector));
321   EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
322       .Times(AtMost(1));
323   EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
324       .Times(AtMost(1))
325       .WillOnce(Invoke(
326           this, &IpcDesktopEnvironmentTest::CreateVideoCapturer));
327   EXPECT_CALL(*desktop_environment, GetCapabilities())
328       .Times(AtMost(1));
329   EXPECT_CALL(*desktop_environment, SetCapabilities(_))
330       .Times(AtMost(1));
331 
332   // Let tests know that the remote desktop environment is created.
333   message_loop_.PostTask(FROM_HERE, setup_run_loop_->QuitClosure());
334 
335   return desktop_environment;
336 }
337 
CreateInputInjector()338 InputInjector* IpcDesktopEnvironmentTest::CreateInputInjector() {
339   EXPECT_TRUE(remote_input_injector_ == NULL);
340   remote_input_injector_ = new testing::StrictMock<MockInputInjector>();
341 
342   EXPECT_CALL(*remote_input_injector_, StartPtr(_));
343   return remote_input_injector_;
344 }
345 
CreateVideoCapturer()346 webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
347   return new ScreenCapturerFake();
348 }
349 
DeleteDesktopEnvironment()350 void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
351   input_injector_.reset();
352   screen_controls_.reset();
353   video_capturer_.reset();
354 
355   // Trigger DisconnectTerminal().
356   desktop_environment_.reset();
357 }
358 
ReflectClipboardEvent(const protocol::ClipboardEvent & event)359 void IpcDesktopEnvironmentTest::ReflectClipboardEvent(
360     const protocol::ClipboardEvent& event) {
361   clipboard_stub_->InjectClipboardEvent(event);
362 }
363 
CreateDesktopProcess()364 void IpcDesktopEnvironmentTest::CreateDesktopProcess() {
365   EXPECT_TRUE(task_runner_.get());
366   EXPECT_TRUE(io_task_runner_.get());
367 
368   // Create the daemon end of the daemon-to-desktop channel.
369   desktop_channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID();
370   desktop_channel_ =
371       IPC::ChannelProxy::Create(IPC::ChannelHandle(desktop_channel_name_),
372                                 IPC::Channel::MODE_SERVER,
373                                 &desktop_listener_,
374                                 io_task_runner_.get());
375 
376   // Create and start the desktop process.
377   desktop_process_.reset(new DesktopProcess(task_runner_,
378                                             io_task_runner_,
379                                             desktop_channel_name_));
380 
381   scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory(
382       new MockDesktopEnvironmentFactory());
383   EXPECT_CALL(*desktop_environment_factory, CreatePtr())
384       .Times(AnyNumber())
385       .WillRepeatedly(Invoke(
386           this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment));
387   EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture())
388       .Times(AnyNumber())
389       .WillRepeatedly(Return(false));
390 
391   EXPECT_TRUE(desktop_process_->Start(
392       desktop_environment_factory.PassAs<DesktopEnvironmentFactory>()));
393 }
394 
DestoyDesktopProcess()395 void IpcDesktopEnvironmentTest::DestoyDesktopProcess() {
396   desktop_channel_.reset();
397   if (desktop_process_) {
398     desktop_process_->OnChannelError();
399     desktop_process_.reset();
400   }
401   remote_input_injector_ = NULL;
402 }
403 
OnDisconnectCallback()404 void IpcDesktopEnvironmentTest::OnDisconnectCallback() {
405   DeleteDesktopEnvironment();
406 }
407 
OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe)408 void IpcDesktopEnvironmentTest::OnDesktopAttached(
409     IPC::PlatformFileForTransit desktop_pipe) {
410 
411   // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe.
412   desktop_environment_factory_->OnDesktopSessionAgentAttached(
413       terminal_id_, base::GetCurrentProcessHandle(), desktop_pipe);
414 }
415 
416 // Runs until the desktop is attached and exits immediately after that.
TEST_F(IpcDesktopEnvironmentTest,Basic)417 TEST_F(IpcDesktopEnvironmentTest, Basic) {
418   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
419       new protocol::MockClipboardStub());
420   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
421       .Times(0);
422 
423   // Start the input injector and screen capturer.
424   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
425 
426   // Run the message loop until the desktop is attached.
427   setup_run_loop_->Run();
428 
429   // Stop the test.
430   DeleteDesktopEnvironment();
431 
432   task_runner_ = NULL;
433   io_task_runner_ = NULL;
434   main_run_loop_.Run();
435 }
436 
437 // Tests that the video capturer receives a frame over IPC.
TEST_F(IpcDesktopEnvironmentTest,CaptureFrame)438 TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) {
439   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
440       new protocol::MockClipboardStub());
441   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
442       .Times(0);
443 
444   // Start the input injector and screen capturer.
445   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
446   video_capturer_->Start(&screen_capturer_callback_);
447 
448   // Run the message loop until the desktop is attached.
449   setup_run_loop_->Run();
450 
451   // Stop the test when the first frame is captured.
452   EXPECT_CALL(screen_capturer_callback_, OnCaptureCompleted(_))
453       .WillOnce(DoAll(
454           DeleteArg<0>(),
455           InvokeWithoutArgs(
456               this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)));
457 
458   // Capture a single frame.
459   video_capturer_->Capture(webrtc::DesktopRegion());
460 
461   task_runner_ = NULL;
462   io_task_runner_ = NULL;
463   main_run_loop_.Run();
464 }
465 
466 // Tests that attaching to a new desktop works.
TEST_F(IpcDesktopEnvironmentTest,Reattach)467 TEST_F(IpcDesktopEnvironmentTest, Reattach) {
468   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
469       new protocol::MockClipboardStub());
470   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
471       .Times(0);
472 
473   // Start the input injector and screen capturer.
474   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
475   video_capturer_->Start(&screen_capturer_callback_);
476 
477   // Run the message loop until the desktop is attached.
478   setup_run_loop_->Run();
479 
480   // Create and start a new desktop process object.
481   setup_run_loop_.reset(new base::RunLoop());
482   DestoyDesktopProcess();
483   CreateDesktopProcess();
484   setup_run_loop_->Run();
485 
486   // Stop the test.
487   DeleteDesktopEnvironment();
488 
489   task_runner_ = NULL;
490   io_task_runner_ = NULL;
491   main_run_loop_.Run();
492 }
493 
494 // Tests injection of clipboard events.
TEST_F(IpcDesktopEnvironmentTest,InjectClipboardEvent)495 TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) {
496   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
497       new protocol::MockClipboardStub());
498   clipboard_stub_ = clipboard_stub.get();
499 
500   // Stop the test when a clipboard event is received from the desktop process.
501   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
502       .Times(1)
503       .WillOnce(InvokeWithoutArgs(
504           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
505 
506   // Start the input injector and screen capturer.
507   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
508   video_capturer_->Start(&screen_capturer_callback_);
509 
510   // Run the message loop until the desktop is attached.
511   setup_run_loop_->Run();
512 
513   // Expect a single clipboard event.
514   EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
515       .Times(1)
516       .WillOnce(Invoke(this,
517                        &IpcDesktopEnvironmentTest::ReflectClipboardEvent));
518 
519   // Send a clipboard event.
520   protocol::ClipboardEvent event;
521   event.set_mime_type(kMimeTypeTextUtf8);
522   event.set_data("a");
523   input_injector_->InjectClipboardEvent(event);
524 
525   task_runner_ = NULL;
526   io_task_runner_ = NULL;
527   main_run_loop_.Run();
528 }
529 
530 // Tests injection of key events.
TEST_F(IpcDesktopEnvironmentTest,InjectKeyEvent)531 TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) {
532   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
533       new protocol::MockClipboardStub());
534   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
535       .Times(0);
536 
537   // Start the input injector and screen capturer.
538   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
539   video_capturer_->Start(&screen_capturer_callback_);
540 
541   // Run the message loop until the desktop is attached.
542   setup_run_loop_->Run();
543 
544   // Expect a single key event.
545   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
546       .Times(AtLeast(1))
547       .WillRepeatedly(InvokeWithoutArgs(
548           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
549 
550   // Send a key event.
551   protocol::KeyEvent event;
552   event.set_usb_keycode(0x070004);
553   event.set_pressed(true);
554   input_injector_->InjectKeyEvent(event);
555 
556   task_runner_ = NULL;
557   io_task_runner_ = NULL;
558   main_run_loop_.Run();
559 }
560 
561 // Tests injection of text events.
TEST_F(IpcDesktopEnvironmentTest,InjectTextEvent)562 TEST_F(IpcDesktopEnvironmentTest, InjectTextEvent) {
563   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
564       new protocol::MockClipboardStub());
565   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
566       .Times(0);
567 
568   // Start the input injector and screen capturer.
569   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
570   video_capturer_->Start(&screen_capturer_callback_);
571 
572   // Run the message loop until the desktop is attached.
573   setup_run_loop_->Run();
574 
575   // Expect a single text event.
576   EXPECT_CALL(*remote_input_injector_, InjectTextEvent(_))
577       .Times(AtLeast(1))
578       .WillRepeatedly(InvokeWithoutArgs(
579           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
580 
581   // Send a text event.
582   protocol::TextEvent event;
583   event.set_text("hello");
584   input_injector_->InjectTextEvent(event);
585 
586   task_runner_ = NULL;
587   io_task_runner_ = NULL;
588   main_run_loop_.Run();
589 }
590 
591 // Tests injection of mouse events.
TEST_F(IpcDesktopEnvironmentTest,InjectMouseEvent)592 TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
593   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
594       new protocol::MockClipboardStub());
595   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
596       .Times(0);
597 
598   // Start the input injector and screen capturer.
599   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
600   video_capturer_->Start(&screen_capturer_callback_);
601 
602   // Run the message loop until the desktop is attached.
603   setup_run_loop_->Run();
604 
605   // Expect a single mouse event.
606   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
607       .Times(1)
608       .WillOnce(InvokeWithoutArgs(
609           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
610 
611   // Send a mouse event.
612   protocol::MouseEvent event;
613   event.set_x(0);
614   event.set_y(0);
615   input_injector_->InjectMouseEvent(event);
616 
617   task_runner_ = NULL;
618   io_task_runner_ = NULL;
619   main_run_loop_.Run();
620 }
621 
622 // Tests that setting the desktop resolution works.
TEST_F(IpcDesktopEnvironmentTest,SetScreenResolution)623 TEST_F(IpcDesktopEnvironmentTest, SetScreenResolution) {
624   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
625       new protocol::MockClipboardStub());
626   EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
627       .Times(0);
628 
629   // Start the input injector and screen capturer.
630   input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
631   video_capturer_->Start(&screen_capturer_callback_);
632 
633   // Run the message loop until the desktop is attached.
634   setup_run_loop_->Run();
635 
636   EXPECT_CALL(daemon_channel_, SetScreenResolution(_, _))
637       .Times(1)
638       .WillOnce(InvokeWithoutArgs(
639           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
640 
641   // Change the desktop resolution.
642   screen_controls_->SetScreenResolution(ScreenResolution(
643       webrtc::DesktopSize(100, 100),
644       webrtc::DesktopVector(96, 96)));
645 
646   task_runner_ = NULL;
647   io_task_runner_ = NULL;
648   main_run_loop_.Run();
649 }
650 
651 }  // namespace remoting
652