ipc_desktop_environment_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
37using testing::_;
38using testing::AnyNumber;
39using testing::AtLeast;
40using testing::AtMost;
41using testing::DeleteArg;
42using testing::DoAll;
43using testing::Return;
44using testing::ReturnRef;
45
46namespace remoting {
47
48namespace {
49
50// Receives messages sent from the network process to the daemon.
51class FakeDaemonSender : public IPC::Sender {
52 public:
53  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.
70class MockDaemonListener : public IPC::Listener {
71 public:
72  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
85bool FakeDaemonSender::Send(IPC::Message* message) {
86  OnMessageReceived(*message);
87  delete message;
88  return true;
89}
90
91void 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
106bool 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
120class 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
217IpcDesktopEnvironmentTest::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
225IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() {
226}
227
228void 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
295void 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
305void 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
313DesktopEnvironment* 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
338InputInjector* IpcDesktopEnvironmentTest::CreateInputInjector() {
339  EXPECT_TRUE(remote_input_injector_ == NULL);
340  remote_input_injector_ = new MockInputInjector();
341
342  EXPECT_CALL(*remote_input_injector_, StartPtr(_));
343  return remote_input_injector_;
344}
345
346webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
347  return new ScreenCapturerFake();
348}
349
350void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
351  input_injector_.reset();
352  screen_controls_.reset();
353  video_capturer_.reset();
354
355  // Trigger DisconnectTerminal().
356  desktop_environment_.reset();
357}
358
359void IpcDesktopEnvironmentTest::ReflectClipboardEvent(
360    const protocol::ClipboardEvent& event) {
361  clipboard_stub_->InjectClipboardEvent(event);
362}
363
364void 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_.reset(
371      new IPC::ChannelProxy(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
395void 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
404void IpcDesktopEnvironmentTest::OnDisconnectCallback() {
405  DeleteDesktopEnvironment();
406}
407
408void 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.
417TEST_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  // Input injector should receive no events.
430  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
431      .Times(0);
432  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
433      .Times(0);
434  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
435      .Times(0);
436
437  // Stop the test.
438  DeleteDesktopEnvironment();
439
440  task_runner_ = NULL;
441  io_task_runner_ = NULL;
442  main_run_loop_.Run();
443}
444
445// Tests that the video capturer receives a frame over IPC.
446TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) {
447  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
448      new protocol::MockClipboardStub());
449  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
450      .Times(0);
451
452  // Start the input injector and screen capturer.
453  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
454  video_capturer_->Start(&screen_capturer_callback_);
455
456  // Run the message loop until the desktop is attached.
457  setup_run_loop_->Run();
458
459  // Input injector should receive no events.
460  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
461      .Times(0);
462  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
463      .Times(0);
464  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
465      .Times(0);
466
467  // Stop the test when the first frame is captured.
468  EXPECT_CALL(screen_capturer_callback_, OnCaptureCompleted(_))
469      .WillOnce(DoAll(
470          DeleteArg<0>(),
471          InvokeWithoutArgs(
472              this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment)));
473
474  // Capture a single frame.
475  video_capturer_->Capture(webrtc::DesktopRegion());
476
477  task_runner_ = NULL;
478  io_task_runner_ = NULL;
479  main_run_loop_.Run();
480}
481
482// Tests that attaching to a new desktop works.
483TEST_F(IpcDesktopEnvironmentTest, Reattach) {
484  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
485      new protocol::MockClipboardStub());
486  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
487      .Times(0);
488
489  // Start the input injector and screen capturer.
490  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
491  video_capturer_->Start(&screen_capturer_callback_);
492
493  // Run the message loop until the desktop is attached.
494  setup_run_loop_->Run();
495
496  // Create and start a new desktop process object.
497  setup_run_loop_.reset(new base::RunLoop());
498  DestoyDesktopProcess();
499  CreateDesktopProcess();
500  setup_run_loop_->Run();
501
502  // Input injector should receive no events.
503  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
504      .Times(0);
505  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
506      .Times(0);
507  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
508      .Times(0);
509
510  // Stop the test.
511  DeleteDesktopEnvironment();
512
513  task_runner_ = NULL;
514  io_task_runner_ = NULL;
515  main_run_loop_.Run();
516}
517
518// Tests injection of clipboard events.
519TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) {
520  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
521      new protocol::MockClipboardStub());
522  clipboard_stub_ = clipboard_stub.get();
523
524  // Stop the test when a clipboard event is received from the desktop process.
525  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
526      .Times(1)
527      .WillOnce(InvokeWithoutArgs(
528          this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
529
530  // Start the input injector and screen capturer.
531  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
532  video_capturer_->Start(&screen_capturer_callback_);
533
534  // Run the message loop until the desktop is attached.
535  setup_run_loop_->Run();
536
537  // Expect a single clipboard event.
538  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
539      .Times(1)
540      .WillOnce(Invoke(this,
541                       &IpcDesktopEnvironmentTest::ReflectClipboardEvent));
542  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
543      .Times(0);
544  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
545      .Times(0);
546
547  // Send a clipboard event.
548  protocol::ClipboardEvent event;
549  event.set_mime_type(kMimeTypeTextUtf8);
550  event.set_data("a");
551  input_injector_->InjectClipboardEvent(event);
552
553  task_runner_ = NULL;
554  io_task_runner_ = NULL;
555  main_run_loop_.Run();
556}
557
558// Tests injection of key events.
559TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) {
560  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
561      new protocol::MockClipboardStub());
562  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
563      .Times(0);
564
565  // Start the input injector and screen capturer.
566  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
567  video_capturer_->Start(&screen_capturer_callback_);
568
569  // Run the message loop until the desktop is attached.
570  setup_run_loop_->Run();
571
572  // Expect a single key event.
573  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
574      .Times(0);
575  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
576      .Times(AtLeast(1))
577      .WillRepeatedly(InvokeWithoutArgs(
578          this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
579  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
580      .Times(0);
581
582  // Send a key event.
583  protocol::KeyEvent event;
584  event.set_usb_keycode(0x070004);
585  event.set_pressed(true);
586  input_injector_->InjectKeyEvent(event);
587
588  task_runner_ = NULL;
589  io_task_runner_ = NULL;
590  main_run_loop_.Run();
591}
592
593// Tests injection of mouse events.
594TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
595  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
596      new protocol::MockClipboardStub());
597  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
598      .Times(0);
599
600  // Start the input injector and screen capturer.
601  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
602  video_capturer_->Start(&screen_capturer_callback_);
603
604  // Run the message loop until the desktop is attached.
605  setup_run_loop_->Run();
606
607  // Expect a single mouse event.
608  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
609      .Times(0);
610  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
611      .Times(0);
612  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
613      .Times(1)
614      .WillOnce(InvokeWithoutArgs(
615          this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
616
617  // Send a mouse event.
618  protocol::MouseEvent event;
619  event.set_x(0);
620  event.set_y(0);
621  input_injector_->InjectMouseEvent(event);
622
623  task_runner_ = NULL;
624  io_task_runner_ = NULL;
625  main_run_loop_.Run();
626}
627
628// Tests that setting the desktop resolution works.
629TEST_F(IpcDesktopEnvironmentTest, SetScreenResolution) {
630  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
631      new protocol::MockClipboardStub());
632  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
633      .Times(0);
634
635  // Start the input injector and screen capturer.
636  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
637  video_capturer_->Start(&screen_capturer_callback_);
638
639  // Run the message loop until the desktop is attached.
640  setup_run_loop_->Run();
641
642  EXPECT_CALL(daemon_channel_, SetScreenResolution(_, _))
643      .Times(1)
644      .WillOnce(InvokeWithoutArgs(
645          this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
646
647  // Change the desktop resolution.
648  screen_controls_->SetScreenResolution(ScreenResolution(
649      webrtc::DesktopSize(100, 100),
650      webrtc::DesktopVector(96, 96)));
651
652  task_runner_ = NULL;
653  io_task_runner_ = NULL;
654  main_run_loop_.Run();
655}
656
657}  // namespace remoting
658