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