blob: d256e8531305b388f34c05ed0703ed653564d155 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/ipc_desktop_environment.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "ipc/attachment_broker_privileged.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_platform_file.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/constants.h"
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/desktop_process.h"
#include "remoting/host/desktop_session.h"
#include "remoting/host/desktop_session_connector.h"
#include "remoting/host/desktop_session_proxy.h"
#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/host_mock_objects.h"
#include "remoting/protocol/fake_desktop_capturer.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "remoting/protocol/test_event_matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::AtMost;
using testing::DeleteArg;
using testing::DoAll;
using testing::InSequence;
using testing::Return;
using testing::ReturnRef;
namespace remoting {
using protocol::test::EqualsTouchEvent;
using protocol::test::EqualsTouchEventTypeAndId;
namespace {
class MockScreenCapturerCallback : public webrtc::ScreenCapturer::Callback {
public:
MockScreenCapturerCallback() {}
virtual ~MockScreenCapturerCallback() {}
MOCK_METHOD2(OnCaptureResultPtr,
void(webrtc::DesktopCapturer::Result result,
std::unique_ptr<webrtc::DesktopFrame>* frame));
void OnCaptureResult(webrtc::DesktopCapturer::Result result,
std::unique_ptr<webrtc::DesktopFrame> frame) override {
OnCaptureResultPtr(result, &frame);
}
private:
DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback);
};
// Receives messages sent from the network process to the daemon.
class FakeDaemonSender : public IPC::Sender {
public:
FakeDaemonSender() {}
~FakeDaemonSender() override {}
// IPC::Sender implementation.
bool Send(IPC::Message* message) override;
MOCK_METHOD3(ConnectTerminal, void(int, const ScreenResolution&, bool));
MOCK_METHOD1(DisconnectTerminal, void(int));
MOCK_METHOD2(SetScreenResolution, void(int, const ScreenResolution&));
private:
void OnMessageReceived(const IPC::Message& message);
DISALLOW_COPY_AND_ASSIGN(FakeDaemonSender);
};
// Receives messages sent from the desktop process to the daemon.
class MockDaemonListener : public IPC::Listener {
public:
MockDaemonListener() {}
~MockDaemonListener() override {}
bool OnMessageReceived(const IPC::Message& message) override;
MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
MOCK_METHOD1(OnChannelConnected, void(int32_t));
MOCK_METHOD0(OnChannelError, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockDaemonListener);
};
bool FakeDaemonSender::Send(IPC::Message* message) {
OnMessageReceived(*message);
delete message;
return true;
}
void FakeDaemonSender::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(FakeDaemonSender, message)
IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_ConnectTerminal,
ConnectTerminal)
IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_DisconnectTerminal,
DisconnectTerminal)
IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_SetScreenResolution,
SetScreenResolution)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
}
bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
OnDesktopAttached)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
return handled;
}
} // namespace
class IpcDesktopEnvironmentTest : public testing::Test {
public:
IpcDesktopEnvironmentTest();
~IpcDesktopEnvironmentTest() override;
void SetUp() override;
void TearDown() override;
void ConnectTerminal(int terminal_id,
const ScreenResolution& resolution,
bool virtual_terminal);
void DisconnectTerminal(int terminal_id);
// Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
// DesktopEnvironmentFactory::Create().
DesktopEnvironment* CreateDesktopEnvironment();
// Creates a dummy InputInjector, to mock
// DesktopEnvironment::CreateInputInjector().
InputInjector* CreateInputInjector();
// Creates a fake webrtc::DesktopCapturer, to mock
// DesktopEnvironment::CreateVideoCapturer().
webrtc::DesktopCapturer* CreateVideoCapturer();
// Creates a MockMouseCursorMonitor, to mock
// DesktopEnvironment::CreateMouseCursorMonitor
webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
void DeleteDesktopEnvironment();
// Forwards |event| to |clipboard_stub_|.
void ReflectClipboardEvent(const protocol::ClipboardEvent& event);
protected:
// Creates and starts an instance of desktop process object.
void CreateDesktopProcess();
// Destroys the desktop process object created by CreateDesktopProcess().
void DestoyDesktopProcess();
void OnDisconnectCallback();
// Invoked when ChromotingDesktopDaemonMsg_DesktopAttached message is
// received.
void OnDesktopAttached(IPC::PlatformFileForTransit desktop_pipe);
void RunMainLoopUntilDone();
// The main message loop.
base::MessageLoopForUI message_loop_;
// Runs until |desktop_session_proxy_| is connected to the desktop.
std::unique_ptr<base::RunLoop> setup_run_loop_;
scoped_refptr<AutoThreadTaskRunner> task_runner_;
scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
std::string client_jid_;
// Clipboard stub that receives clipboard events from the desktop process.
protocol::ClipboardStub* clipboard_stub_;
// The daemons's end of the daemon-to-desktop channel.
std::unique_ptr<IPC::ChannelProxy> desktop_channel_;
// Name of the daemon-to-desktop channel.
std::string desktop_channel_name_;
// Delegate that is passed to |desktop_channel_|.
MockDaemonListener desktop_listener_;
FakeDaemonSender daemon_channel_;
std::unique_ptr<IpcDesktopEnvironmentFactory> desktop_environment_factory_;
std::unique_ptr<DesktopEnvironment> desktop_environment_;
// The IPC input injector.
std::unique_ptr<InputInjector> input_injector_;
// The IPC screen controls.
std::unique_ptr<ScreenControls> screen_controls_;
// The IPC screen capturer.
std::unique_ptr<webrtc::DesktopCapturer> video_capturer_;
// Represents the desktop process running in a user session.
std::unique_ptr<DesktopProcess> desktop_process_;
// Input injector owned by |desktop_process_|.
MockInputInjector* remote_input_injector_;
// The last |terminal_id| passed to ConnectTermina();
int terminal_id_;
MockScreenCapturerCallback desktop_capturer_callback_;
MockClientSessionControl client_session_control_;
base::WeakPtrFactory<ClientSessionControl> client_session_control_factory_;
private:
// Runs until there are references to |task_runner_|.
base::RunLoop main_run_loop_;
};
IpcDesktopEnvironmentTest::IpcDesktopEnvironmentTest()
: client_jid_("user@domain/rest-of-jid"),
clipboard_stub_(nullptr),
remote_input_injector_(nullptr),
terminal_id_(-1),
client_session_control_factory_(&client_session_control_) {
IPC::AttachmentBrokerPrivileged::CreateBrokerForSingleProcessTests();
}
IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() {
}
void IpcDesktopEnvironmentTest::SetUp() {
// Arrange to run |message_loop_| until no components depend on it.
task_runner_ = new AutoThreadTaskRunner(
message_loop_.task_runner(), main_run_loop_.QuitClosure());
io_task_runner_ = AutoThread::CreateWithType(
"IPC thread", task_runner_, base::MessageLoop::TYPE_IO);
setup_run_loop_.reset(new base::RunLoop());
// Set expectation that the DaemonProcess will send DesktopAttached message
// once it is ready.
EXPECT_CALL(desktop_listener_, OnChannelConnected(_))
.Times(AnyNumber());
EXPECT_CALL(desktop_listener_, OnDesktopAttached(_))
.Times(AnyNumber())
.WillRepeatedly(Invoke(this,
&IpcDesktopEnvironmentTest::OnDesktopAttached));
EXPECT_CALL(desktop_listener_, OnChannelError())
.Times(AnyNumber())
.WillOnce(Invoke(this,
&IpcDesktopEnvironmentTest::DestoyDesktopProcess));
// Intercept requests to connect and disconnect a terminal.
EXPECT_CALL(daemon_channel_, ConnectTerminal(_, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(this,
&IpcDesktopEnvironmentTest::ConnectTerminal));
EXPECT_CALL(daemon_channel_, DisconnectTerminal(_))
.Times(AnyNumber())
.WillRepeatedly(Invoke(this,
&IpcDesktopEnvironmentTest::DisconnectTerminal));
EXPECT_CALL(client_session_control_, client_jid())
.Times(AnyNumber())
.WillRepeatedly(ReturnRef(client_jid_));
EXPECT_CALL(client_session_control_, DisconnectSession(_))
.Times(AnyNumber())
.WillRepeatedly(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
EXPECT_CALL(client_session_control_, OnLocalMouseMoved(_))
.Times(0);
EXPECT_CALL(client_session_control_, SetDisableInputs(_))
.Times(0);
// Create a desktop environment instance.
desktop_environment_factory_.reset(new IpcDesktopEnvironmentFactory(
task_runner_, task_runner_, io_task_runner_, &daemon_channel_));
desktop_environment_ = desktop_environment_factory_->Create(
client_session_control_factory_.GetWeakPtr());
screen_controls_ = desktop_environment_->CreateScreenControls();
// Create the input injector.
input_injector_ = desktop_environment_->CreateInputInjector();
// Create the screen capturer.
video_capturer_ =
desktop_environment_->CreateVideoCapturer();
desktop_environment_->SetCapabilities(std::string());
}
void IpcDesktopEnvironmentTest::TearDown() {
RunMainLoopUntilDone();
}
void IpcDesktopEnvironmentTest::ConnectTerminal(
int terminal_id,
const ScreenResolution& resolution,
bool virtual_terminal) {
EXPECT_NE(terminal_id_, terminal_id);
terminal_id_ = terminal_id;
CreateDesktopProcess();
}
void IpcDesktopEnvironmentTest::DisconnectTerminal(int terminal_id) {
EXPECT_EQ(terminal_id_, terminal_id);
// The IPC desktop environment is fully destroyed now. Release the remaining
// task runners.
desktop_environment_factory_.reset();
}
DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() {
MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
.Times(0);
EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
.Times(AtMost(1))
.WillOnce(Invoke(
this, &IpcDesktopEnvironmentTest::CreateInputInjector));
EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
.Times(AtMost(1))
.WillOnce(Invoke(
this, &IpcDesktopEnvironmentTest::CreateVideoCapturer));
EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
.Times(AtMost(1))
.WillOnce(Invoke(
this, &IpcDesktopEnvironmentTest::CreateMouseCursorMonitor));
EXPECT_CALL(*desktop_environment, GetCapabilities())
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, SetCapabilities(_))
.Times(AtMost(1));
// Let tests know that the remote desktop environment is created.
message_loop_.task_runner()->PostTask(FROM_HERE,
setup_run_loop_->QuitClosure());
return desktop_environment;
}
InputInjector* IpcDesktopEnvironmentTest::CreateInputInjector() {
EXPECT_TRUE(remote_input_injector_ == nullptr);
remote_input_injector_ = new testing::StrictMock<MockInputInjector>();
EXPECT_CALL(*remote_input_injector_, StartPtr(_));
return remote_input_injector_;
}
webrtc::DesktopCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
return new protocol::FakeDesktopCapturer();
}
webrtc::MouseCursorMonitor*
IpcDesktopEnvironmentTest::CreateMouseCursorMonitor() {
return new FakeMouseCursorMonitor();
}
void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
input_injector_.reset();
screen_controls_.reset();
video_capturer_.reset();
// Trigger DisconnectTerminal().
desktop_environment_.reset();
}
void IpcDesktopEnvironmentTest::ReflectClipboardEvent(
const protocol::ClipboardEvent& event) {
clipboard_stub_->InjectClipboardEvent(event);
}
void IpcDesktopEnvironmentTest::CreateDesktopProcess() {
EXPECT_TRUE(task_runner_.get());
EXPECT_TRUE(io_task_runner_.get());
// Create the daemon end of the daemon-to-desktop channel.
desktop_channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID();
desktop_channel_ = IPC::ChannelProxy::Create(
IPC::ChannelHandle(desktop_channel_name_), IPC::Channel::MODE_SERVER,
&desktop_listener_, io_task_runner_.get());
// Create and start the desktop process.
desktop_process_.reset(new DesktopProcess(task_runner_,
io_task_runner_,
desktop_channel_name_));
std::unique_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory(
new MockDesktopEnvironmentFactory());
EXPECT_CALL(*desktop_environment_factory, CreatePtr())
.Times(AnyNumber())
.WillRepeatedly(Invoke(
this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment));
EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
EXPECT_TRUE(desktop_process_->Start(std::move(desktop_environment_factory)));
}
void IpcDesktopEnvironmentTest::DestoyDesktopProcess() {
desktop_channel_.reset();
if (desktop_process_) {
desktop_process_->OnChannelError();
desktop_process_.reset();
}
remote_input_injector_ = nullptr;
}
void IpcDesktopEnvironmentTest::OnDisconnectCallback() {
DeleteDesktopEnvironment();
}
void IpcDesktopEnvironmentTest::OnDesktopAttached(
IPC::PlatformFileForTransit desktop_pipe) {
base::ProcessHandle process_handle = base::GetCurrentProcessHandle();
#if defined(OS_WIN)
ASSERT_NE(FALSE, ::DuplicateHandle(GetCurrentProcess(), process_handle,
GetCurrentProcess(), &process_handle,
0, FALSE, DUPLICATE_SAME_ACCESS));
#endif
// Instruct DesktopSessionProxy to connect to the network-to-desktop pipe.
desktop_environment_factory_->OnDesktopSessionAgentAttached(
terminal_id_, process_handle, desktop_pipe);
}
void IpcDesktopEnvironmentTest::RunMainLoopUntilDone() {
task_runner_ = nullptr;
io_task_runner_ = nullptr;
main_run_loop_.Run();
}
// Runs until the desktop is attached and exits immediately after that.
TEST_F(IpcDesktopEnvironmentTest, Basic) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Stop the test.
DeleteDesktopEnvironment();
}
// Check Capabilities.
TEST_F(IpcDesktopEnvironmentTest, CapabilitiesNoTouch) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
EXPECT_EQ("rateLimitResizeRequests", desktop_environment_->GetCapabilities());
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Stop the test.
DeleteDesktopEnvironment();
}
// Check touchEvents capability is set when the desktop environment can
// inject touch events.
TEST_F(IpcDesktopEnvironmentTest, TouchEventsCapabilities) {
// Create an environment with multi touch enabled.
desktop_environment_factory_->set_supports_touch_events(true);
desktop_environment_ = desktop_environment_factory_->Create(
client_session_control_factory_.GetWeakPtr());
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
EXPECT_EQ("rateLimitResizeRequests touchEvents",
desktop_environment_->GetCapabilities());
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Stop the test.
DeleteDesktopEnvironment();
}
// Tests that the video capturer receives a frame over IPC.
TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Stop the test when the first frame is captured.
EXPECT_CALL(desktop_capturer_callback_, OnCaptureResultPtr(_, _))
.WillOnce(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Capture a single frame.
video_capturer_->Capture(webrtc::DesktopRegion());
}
// Tests that attaching to a new desktop works.
TEST_F(IpcDesktopEnvironmentTest, Reattach) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Create and start a new desktop process object.
setup_run_loop_.reset(new base::RunLoop());
DestoyDesktopProcess();
CreateDesktopProcess();
setup_run_loop_->Run();
// Stop the test.
DeleteDesktopEnvironment();
}
// Tests injection of clipboard events.
TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
clipboard_stub_ = clipboard_stub.get();
// Stop the test when a clipboard event is received from the desktop process.
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Expect a single clipboard event.
EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
.Times(1)
.WillOnce(Invoke(this,
&IpcDesktopEnvironmentTest::ReflectClipboardEvent));
// Send a clipboard event.
protocol::ClipboardEvent event;
event.set_mime_type(kMimeTypeTextUtf8);
event.set_data("a");
input_injector_->InjectClipboardEvent(event);
}
// Tests injection of key events.
TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Expect a single key event.
EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
.Times(AtLeast(1))
.WillRepeatedly(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Send a key event.
protocol::KeyEvent event;
event.set_usb_keycode(0x070004);
event.set_pressed(true);
input_injector_->InjectKeyEvent(event);
}
// Tests injection of text events.
TEST_F(IpcDesktopEnvironmentTest, InjectTextEvent) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Expect a single text event.
EXPECT_CALL(*remote_input_injector_, InjectTextEvent(_))
.Times(AtLeast(1))
.WillRepeatedly(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Send a text event.
protocol::TextEvent event;
event.set_text("hello");
input_injector_->InjectTextEvent(event);
}
// Tests injection of mouse events.
TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
// Expect a single mouse event.
EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Send a mouse event.
protocol::MouseEvent event;
event.set_x(0);
event.set_y(0);
input_injector_->InjectMouseEvent(event);
}
// Tests injection of touch events.
TEST_F(IpcDesktopEnvironmentTest, InjectTouchEvent) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
protocol::TouchEvent event;
event.set_event_type(protocol::TouchEvent::TOUCH_POINT_START);
protocol::TouchEventPoint* point = event.add_touch_points();
point->set_id(0u);
point->set_x(0.0f);
point->set_y(0.0f);
point->set_radius_x(0.0f);
point->set_radius_y(0.0f);
point->set_angle(0.0f);
point->set_pressure(0.0f);
ON_CALL(*remote_input_injector_, InjectTouchEvent(_))
.WillByDefault(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
InSequence s;
// Expect that the event gets propagated to remote_input_injector_.
// And one more call for ReleaseAll().
EXPECT_CALL(*remote_input_injector_,
InjectTouchEvent(EqualsTouchEvent(event)));
EXPECT_CALL(*remote_input_injector_,
InjectTouchEvent(EqualsTouchEventTypeAndId(
protocol::TouchEvent::TOUCH_POINT_CANCEL, 0u)));
// Send the touch event.
input_injector_->InjectTouchEvent(event);
}
// Tests that setting the desktop resolution works.
TEST_F(IpcDesktopEnvironmentTest, SetScreenResolution) {
std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
new protocol::MockClipboardStub());
EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
.Times(0);
// Start the input injector and screen capturer.
input_injector_->Start(std::move(clipboard_stub));
video_capturer_->Start(&desktop_capturer_callback_);
// Run the message loop until the desktop is attached.
setup_run_loop_->Run();
EXPECT_CALL(daemon_channel_, SetScreenResolution(_, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(
this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
// Change the desktop resolution.
screen_controls_->SetScreenResolution(ScreenResolution(
webrtc::DesktopSize(100, 100),
webrtc::DesktopVector(96, 96)));
}
} // namespace remoting