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: 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. 70 class 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 85 bool FakeDaemonSender::Send(IPC::Message* message) { 86 OnMessageReceived(*message); 87 delete message; 88 return true; 89 } 90 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 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 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 225 IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() { 226 } 227 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 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 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 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 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 346 webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() { 347 return new ScreenCapturerFake(); 348 } 349 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 359 void IpcDesktopEnvironmentTest::ReflectClipboardEvent( 360 const protocol::ClipboardEvent& event) { 361 clipboard_stub_->InjectClipboardEvent(event); 362 } 363 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 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 404 void IpcDesktopEnvironmentTest::OnDisconnectCallback() { 405 DeleteDesktopEnvironment(); 406 } 407 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. 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. 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. 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. 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. 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. 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. 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. 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