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