ipc_desktop_environment_unittest.cc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  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. #include "remoting/host/ipc_desktop_environment.h"
  5. #include <stdint.h>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/message_loop/message_pump_type.h"
  15. #include "base/process/process.h"
  16. #include "base/process/process_handle.h"
  17. #include "base/run_loop.h"
  18. #include "base/task/single_thread_task_runner.h"
  19. #include "base/test/gmock_callback_support.h"
  20. #include "base/test/mock_callback.h"
  21. #include "base/test/task_environment.h"
  22. #include "base/threading/sequenced_task_runner_handle.h"
  23. #include "build/build_config.h"
  24. #include "ipc/ipc_channel.h"
  25. #include "ipc/ipc_channel_proxy.h"
  26. #include "ipc/ipc_listener.h"
  27. #include "ipc/ipc_message.h"
  28. #include "ipc/ipc_platform_file.h"
  29. #include "mojo/public/cpp/system/message_pipe.h"
  30. #include "remoting/base/auto_thread.h"
  31. #include "remoting/base/auto_thread_task_runner.h"
  32. #include "remoting/base/constants.h"
  33. #include "remoting/host/desktop_process.h"
  34. #include "remoting/host/desktop_session.h"
  35. #include "remoting/host/desktop_session_connector.h"
  36. #include "remoting/host/desktop_session_proxy.h"
  37. #include "remoting/host/fake_keyboard_layout_monitor.h"
  38. #include "remoting/host/fake_mouse_cursor_monitor.h"
  39. #include "remoting/host/host_mock_objects.h"
  40. #include "remoting/host/mojom/desktop_session.mojom.h"
  41. #include "remoting/protocol/fake_desktop_capturer.h"
  42. #include "remoting/protocol/protocol_mock_objects.h"
  43. #include "remoting/protocol/test_event_matchers.h"
  44. #include "testing/gmock/include/gmock/gmock.h"
  45. #include "testing/gtest/include/gtest/gtest.h"
  46. #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
  47. #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
  48. #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
  49. using base::test::RunCallback;
  50. using base::test::RunOnceCallback;
  51. using base::test::RunOnceClosure;
  52. using testing::_;
  53. using testing::AnyNumber;
  54. using testing::AtLeast;
  55. using testing::AtMost;
  56. using testing::ByMove;
  57. using testing::DeleteArg;
  58. using testing::DoAll;
  59. using testing::InSequence;
  60. using testing::Return;
  61. using testing::ReturnRef;
  62. namespace remoting {
  63. using protocol::test::EqualsTouchEvent;
  64. using protocol::test::EqualsTouchEventTypeAndId;
  65. using SetUpUrlForwarderResponse =
  66. protocol::UrlForwarderControl::SetUpUrlForwarderResponse;
  67. namespace {
  68. class MockScreenCapturerCallback : public webrtc::DesktopCapturer::Callback {
  69. public:
  70. MockScreenCapturerCallback() = default;
  71. MockScreenCapturerCallback(const MockScreenCapturerCallback&) = delete;
  72. MockScreenCapturerCallback& operator=(const MockScreenCapturerCallback&) =
  73. delete;
  74. ~MockScreenCapturerCallback() override = default;
  75. MOCK_METHOD(void,
  76. OnCaptureResultPtr,
  77. (webrtc::DesktopCapturer::Result,
  78. std::unique_ptr<webrtc::DesktopFrame>*));
  79. void OnCaptureResult(webrtc::DesktopCapturer::Result result,
  80. std::unique_ptr<webrtc::DesktopFrame> frame) override {
  81. OnCaptureResultPtr(result, &frame);
  82. }
  83. };
  84. // Receives messages sent from the desktop process to the daemon.
  85. class MockDaemonListener : public IPC::Listener,
  86. public mojom::DesktopSessionRequestHandler {
  87. public:
  88. MockDaemonListener() = default;
  89. MockDaemonListener(const MockDaemonListener&) = delete;
  90. MockDaemonListener& operator=(const MockDaemonListener&) = delete;
  91. ~MockDaemonListener() override = default;
  92. bool OnMessageReceived(const IPC::Message& message) override;
  93. void OnAssociatedInterfaceRequest(
  94. const std::string& interface_name,
  95. mojo::ScopedInterfaceEndpointHandle handle) override;
  96. MOCK_METHOD(void,
  97. ConnectDesktopChannel,
  98. (mojo::ScopedMessagePipeHandle handle),
  99. (override));
  100. MOCK_METHOD(void, InjectSecureAttentionSequence, (), (override));
  101. MOCK_METHOD(void, CrashNetworkProcess, (), (override));
  102. MOCK_METHOD(void, OnChannelConnected, (int32_t), (override));
  103. MOCK_METHOD(void, OnChannelError, (), (override));
  104. void Disconnect();
  105. private:
  106. mojo::AssociatedReceiver<mojom::DesktopSessionRequestHandler>
  107. desktop_session_request_handler_{this};
  108. };
  109. bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
  110. ADD_FAILURE() << "Unexpected call to OnMessageReceived()";
  111. return false;
  112. }
  113. void MockDaemonListener::OnAssociatedInterfaceRequest(
  114. const std::string& interface_name,
  115. mojo::ScopedInterfaceEndpointHandle handle) {
  116. EXPECT_EQ(mojom::DesktopSessionRequestHandler::Name_, interface_name);
  117. mojo::PendingAssociatedReceiver<mojom::DesktopSessionRequestHandler>
  118. pending_receiver(std::move(handle));
  119. desktop_session_request_handler_.Bind(std::move(pending_receiver));
  120. }
  121. void MockDaemonListener::Disconnect() {
  122. desktop_session_request_handler_.reset();
  123. }
  124. class MockDesktopSessionManager : public mojom::DesktopSessionManager {
  125. public:
  126. MockDesktopSessionManager() = default;
  127. ~MockDesktopSessionManager() override = default;
  128. void BindNewReceiver(
  129. mojo::PendingAssociatedReceiver<mojom::DesktopSessionManager> receiver);
  130. // mojom::DesktopSessionManager implementation.
  131. MOCK_METHOD(void,
  132. CreateDesktopSession,
  133. (int, const ScreenResolution&, bool),
  134. (override));
  135. MOCK_METHOD(void, CloseDesktopSession, (int), (override));
  136. MOCK_METHOD(void,
  137. SetScreenResolution,
  138. (int, const ScreenResolution&),
  139. (override));
  140. private:
  141. mojo::AssociatedReceiver<mojom::DesktopSessionManager>
  142. desktop_session_manager_{this};
  143. };
  144. void MockDesktopSessionManager::BindNewReceiver(
  145. mojo::PendingAssociatedReceiver<mojom::DesktopSessionManager> receiver) {
  146. desktop_session_manager_.reset();
  147. // EnableUnassociatedUsage() sets up a private message pipe for the remote /
  148. // receiver pair used in this test which simplifies our test setup and
  149. // doesn't change any behaviors being tested.
  150. receiver.EnableUnassociatedUsage();
  151. desktop_session_manager_.Bind(std::move(receiver));
  152. }
  153. } // namespace
  154. class IpcDesktopEnvironmentTest : public testing::Test {
  155. public:
  156. IpcDesktopEnvironmentTest();
  157. ~IpcDesktopEnvironmentTest() override;
  158. void SetUp() override;
  159. void TearDown() override;
  160. void CreateDesktopSession(int terminal_id,
  161. const ScreenResolution& resolution,
  162. bool virtual_terminal);
  163. void CloseDesktopSession(int terminal_id);
  164. // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
  165. // DesktopEnvironmentFactory::Create().
  166. std::unique_ptr<DesktopEnvironment> CreateDesktopEnvironment();
  167. // Creates a fake InputInjector, to mock
  168. // DesktopEnvironment::CreateInputInjector().
  169. std::unique_ptr<InputInjector> CreateInputInjector();
  170. void DeleteDesktopEnvironment();
  171. // Forwards |event| to |clipboard_stub_|.
  172. void ReflectClipboardEvent(const protocol::ClipboardEvent& event);
  173. protected:
  174. // Creates and starts an instance of desktop process object.
  175. void CreateDesktopProcess();
  176. // Destroys the desktop process object created by CreateDesktopProcess().
  177. void DestroyDesktopProcess();
  178. // Creates a new remote URL forwarder configurator for the desktop process.
  179. void ResetRemoteUrlForwarderConfigurator();
  180. void OnDisconnectCallback();
  181. // Invoked when ConnectDesktopChannel() is called over IPC.
  182. void ConnectDesktopChannel(mojo::ScopedMessagePipeHandle desktop_pipe);
  183. // Runs until there are no references to |task_runner_|. Calls after the main
  184. // loop has been run are no-op.
  185. void RunMainLoopUntilDone();
  186. // Some tests require |setup_run_loop_| to be reset so we need a method which
  187. // can be bound that will quit the current run loop.
  188. void QuitSetupRunLoop();
  189. base::test::TaskEnvironment task_environment_{
  190. base::test::TaskEnvironment::MainThreadType::UI};
  191. // Runs until |desktop_session_proxy_| is connected to the desktop.
  192. std::unique_ptr<base::RunLoop> setup_run_loop_;
  193. scoped_refptr<AutoThreadTaskRunner> task_runner_;
  194. scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
  195. std::string client_jid_;
  196. // Clipboard stub that receives clipboard events from the desktop process.
  197. raw_ptr<protocol::ClipboardStub> clipboard_stub_;
  198. // The daemons's end of the daemon-to-desktop channel.
  199. std::unique_ptr<IPC::ChannelProxy> desktop_channel_;
  200. MockDesktopSessionManager mock_desktop_session_manager_;
  201. // Delegate that is passed to |desktop_channel_|.
  202. MockDaemonListener desktop_listener_;
  203. std::unique_ptr<IpcDesktopEnvironmentFactory> desktop_environment_factory_;
  204. std::unique_ptr<DesktopEnvironment> desktop_environment_;
  205. // The IPC input injector.
  206. std::unique_ptr<InputInjector> input_injector_;
  207. // The IPC screen controls.
  208. std::unique_ptr<ScreenControls> screen_controls_;
  209. // The IPC screen capturer.
  210. std::unique_ptr<webrtc::DesktopCapturer> video_capturer_;
  211. // Represents the desktop process running in a user session.
  212. std::unique_ptr<DesktopProcess> desktop_process_;
  213. // Input injector owned by |desktop_process_|.
  214. raw_ptr<MockInputInjector> remote_input_injector_;
  215. // Will be transferred to the caller of
  216. // MockDesktopEnvironment::CreateUrlForwarderConfigurator().
  217. // We create the configurator in advance to allow setting expectations before
  218. // the desktop process is being created, during which the configurator will be
  219. // used.
  220. std::unique_ptr<MockUrlForwarderConfigurator>
  221. owned_remote_url_forwarder_configurator_;
  222. raw_ptr<MockUrlForwarderConfigurator> remote_url_forwarder_configurator_;
  223. std::unique_ptr<UrlForwarderConfigurator> url_forwarder_configurator_;
  224. // The last |terminal_id| passed to ConnectTermina();
  225. int terminal_id_;
  226. MockScreenCapturerCallback desktop_capturer_callback_;
  227. MockClientSessionControl client_session_control_;
  228. base::WeakPtrFactory<ClientSessionControl> client_session_control_factory_;
  229. MockClientSessionEvents client_session_events_;
  230. base::WeakPtrFactory<MockClientSessionEvents> client_session_events_factory_{
  231. &client_session_events_};
  232. private:
  233. // Runs until there are no references to |task_runner_|.
  234. base::RunLoop main_run_loop_;
  235. };
  236. IpcDesktopEnvironmentTest::IpcDesktopEnvironmentTest()
  237. : client_jid_("user@domain/rest-of-jid"),
  238. clipboard_stub_(nullptr),
  239. remote_input_injector_(nullptr),
  240. terminal_id_(-1),
  241. client_session_control_factory_(&client_session_control_) {
  242. }
  243. IpcDesktopEnvironmentTest::~IpcDesktopEnvironmentTest() = default;
  244. void IpcDesktopEnvironmentTest::SetUp() {
  245. // Arrange to run |message_loop_| until no components depend on it.
  246. task_runner_ =
  247. new AutoThreadTaskRunner(task_environment_.GetMainThreadTaskRunner(),
  248. main_run_loop_.QuitClosure());
  249. io_task_runner_ = AutoThread::CreateWithType("IPC thread", task_runner_,
  250. base::MessagePumpType::IO);
  251. setup_run_loop_ = std::make_unique<base::RunLoop>();
  252. // Set expectation that the DaemonProcess will send DesktopAttached message
  253. // once it is ready.
  254. EXPECT_CALL(desktop_listener_, OnChannelConnected(_))
  255. .Times(AnyNumber());
  256. EXPECT_CALL(desktop_listener_, ConnectDesktopChannel(_))
  257. .Times(AnyNumber())
  258. .WillRepeatedly([&](mojo::ScopedMessagePipeHandle desktop_pipe) {
  259. ConnectDesktopChannel(std::move(desktop_pipe));
  260. });
  261. EXPECT_CALL(desktop_listener_, OnChannelError())
  262. .Times(AnyNumber())
  263. .WillOnce(
  264. Invoke(this, &IpcDesktopEnvironmentTest::DestroyDesktopProcess));
  265. // Intercept requests to connect and disconnect a terminal.
  266. EXPECT_CALL(mock_desktop_session_manager_, CreateDesktopSession(_, _, _))
  267. .Times(AnyNumber())
  268. .WillRepeatedly(
  269. Invoke(this, &IpcDesktopEnvironmentTest::CreateDesktopSession));
  270. EXPECT_CALL(mock_desktop_session_manager_, CloseDesktopSession(_))
  271. .Times(AnyNumber())
  272. .WillRepeatedly(
  273. Invoke(this, &IpcDesktopEnvironmentTest::CloseDesktopSession));
  274. EXPECT_CALL(client_session_control_, client_jid())
  275. .Times(AnyNumber())
  276. .WillRepeatedly(ReturnRef(client_jid_));
  277. EXPECT_CALL(client_session_control_, DisconnectSession(_))
  278. .Times(AnyNumber())
  279. .WillRepeatedly(InvokeWithoutArgs(
  280. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  281. EXPECT_CALL(client_session_control_, OnLocalPointerMoved(_, _)).Times(0);
  282. EXPECT_CALL(client_session_control_, SetDisableInputs(_))
  283. .Times(0);
  284. // Most tests will only call this once but reattach will call multiple times.
  285. EXPECT_CALL(client_session_events_, OnDesktopAttached(_))
  286. .Times(AnyNumber())
  287. .WillRepeatedly(InvokeWithoutArgs(
  288. this, &IpcDesktopEnvironmentTest::QuitSetupRunLoop));
  289. EXPECT_CALL(client_session_events_, OnDesktopDetached()).Times(AnyNumber());
  290. // Create a desktop environment instance.
  291. mojo::AssociatedRemote<mojom::DesktopSessionManager> remote;
  292. mock_desktop_session_manager_.BindNewReceiver(
  293. remote.BindNewEndpointAndPassReceiver());
  294. desktop_environment_factory_ = std::make_unique<IpcDesktopEnvironmentFactory>(
  295. task_runner_, task_runner_, io_task_runner_, std::move(remote));
  296. desktop_environment_ = desktop_environment_factory_->Create(
  297. client_session_control_factory_.GetWeakPtr(),
  298. client_session_events_factory_.GetWeakPtr(), DesktopEnvironmentOptions());
  299. screen_controls_ = desktop_environment_->CreateScreenControls();
  300. // Create the input injector.
  301. input_injector_ = desktop_environment_->CreateInputInjector();
  302. // Create the screen capturer.
  303. video_capturer_ = desktop_environment_->CreateVideoCapturer();
  304. desktop_environment_->SetCapabilities(std::string());
  305. url_forwarder_configurator_ =
  306. desktop_environment_->CreateUrlForwarderConfigurator();
  307. ResetRemoteUrlForwarderConfigurator();
  308. }
  309. void IpcDesktopEnvironmentTest::TearDown() {
  310. RunMainLoopUntilDone();
  311. }
  312. void IpcDesktopEnvironmentTest::CreateDesktopSession(
  313. int terminal_id,
  314. const ScreenResolution& resolution,
  315. bool virtual_terminal) {
  316. EXPECT_NE(terminal_id_, terminal_id);
  317. terminal_id_ = terminal_id;
  318. CreateDesktopProcess();
  319. }
  320. void IpcDesktopEnvironmentTest::CloseDesktopSession(int terminal_id) {
  321. EXPECT_EQ(terminal_id_, terminal_id);
  322. // The IPC desktop environment is fully destroyed now. Release the remaining
  323. // task runners.
  324. desktop_environment_factory_.reset();
  325. }
  326. std::unique_ptr<DesktopEnvironment>
  327. IpcDesktopEnvironmentTest::CreateDesktopEnvironment() {
  328. auto desktop_environment = std::make_unique<MockDesktopEnvironment>();
  329. EXPECT_CALL(*desktop_environment, CreateAudioCapturer()).Times(0);
  330. EXPECT_CALL(*desktop_environment, CreateInputInjector())
  331. .Times(AtMost(1))
  332. .WillOnce(Invoke(this, &IpcDesktopEnvironmentTest::CreateInputInjector));
  333. EXPECT_CALL(*desktop_environment, CreateScreenControls()).Times(AtMost(1));
  334. EXPECT_CALL(*desktop_environment, CreateVideoCapturer())
  335. .Times(AtMost(1))
  336. .WillOnce(
  337. Return(ByMove(std::make_unique<protocol::FakeDesktopCapturer>())));
  338. EXPECT_CALL(*desktop_environment, CreateActionExecutor()).Times(AtMost(1));
  339. EXPECT_CALL(*desktop_environment, CreateFileOperations()).Times(AtMost(1));
  340. EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitor())
  341. .Times(AtMost(1))
  342. .WillOnce(Return(ByMove(std::make_unique<FakeMouseCursorMonitor>())));
  343. EXPECT_CALL(*desktop_environment, CreateKeyboardLayoutMonitor(_))
  344. .Times(AtMost(1))
  345. .WillOnce(Return(ByMove(std::make_unique<FakeKeyboardLayoutMonitor>())));
  346. EXPECT_CALL(*desktop_environment, GetCapabilities())
  347. .Times(AtMost(1));
  348. EXPECT_CALL(*desktop_environment, SetCapabilities(_))
  349. .Times(AtMost(1));
  350. DCHECK(owned_remote_url_forwarder_configurator_);
  351. EXPECT_CALL(*desktop_environment, CreateUrlForwarderConfigurator())
  352. .Times(AtMost(1))
  353. .WillOnce(
  354. Return(ByMove(std::move(owned_remote_url_forwarder_configurator_))));
  355. return desktop_environment;
  356. }
  357. std::unique_ptr<InputInjector>
  358. IpcDesktopEnvironmentTest::CreateInputInjector() {
  359. auto remote_input_injector =
  360. std::make_unique<testing::StrictMock<MockInputInjector>>();
  361. EXPECT_TRUE(remote_input_injector_ == nullptr);
  362. remote_input_injector_ = remote_input_injector.get();
  363. EXPECT_CALL(*remote_input_injector_, Start(_));
  364. return remote_input_injector;
  365. }
  366. void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
  367. input_injector_.reset();
  368. screen_controls_.reset();
  369. video_capturer_.reset();
  370. url_forwarder_configurator_.reset();
  371. // Trigger CloseDesktopSession().
  372. desktop_environment_.reset();
  373. }
  374. void IpcDesktopEnvironmentTest::ReflectClipboardEvent(
  375. const protocol::ClipboardEvent& event) {
  376. clipboard_stub_->InjectClipboardEvent(event);
  377. }
  378. void IpcDesktopEnvironmentTest::CreateDesktopProcess() {
  379. EXPECT_TRUE(task_runner_.get());
  380. EXPECT_TRUE(io_task_runner_.get());
  381. // Create the daemon end of the daemon-to-desktop channel.
  382. mojo::MessagePipe pipe;
  383. desktop_channel_ = IPC::ChannelProxy::Create(
  384. pipe.handle0.release(), IPC::Channel::MODE_SERVER, &desktop_listener_,
  385. io_task_runner_.get(), base::ThreadTaskRunnerHandle::Get());
  386. // Create and start the desktop process.
  387. desktop_process_ = std::make_unique<DesktopProcess>(
  388. task_runner_, io_task_runner_, io_task_runner_, std::move(pipe.handle1));
  389. std::unique_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory(
  390. new MockDesktopEnvironmentFactory());
  391. EXPECT_CALL(*desktop_environment_factory, Create(_, _, _))
  392. .Times(AnyNumber())
  393. .WillRepeatedly(
  394. Invoke(this, &IpcDesktopEnvironmentTest::CreateDesktopEnvironment));
  395. EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture())
  396. .Times(AnyNumber())
  397. .WillRepeatedly(Return(false));
  398. EXPECT_TRUE(desktop_process_->Start(std::move(desktop_environment_factory)));
  399. }
  400. void IpcDesktopEnvironmentTest::DestroyDesktopProcess() {
  401. desktop_channel_.reset();
  402. if (desktop_process_) {
  403. desktop_process_->OnChannelError();
  404. desktop_process_.reset();
  405. }
  406. desktop_listener_.Disconnect();
  407. remote_input_injector_ = nullptr;
  408. }
  409. void IpcDesktopEnvironmentTest::ResetRemoteUrlForwarderConfigurator() {
  410. owned_remote_url_forwarder_configurator_ =
  411. std::make_unique<MockUrlForwarderConfigurator>();
  412. remote_url_forwarder_configurator_ =
  413. owned_remote_url_forwarder_configurator_.get();
  414. ON_CALL(*remote_url_forwarder_configurator_, IsUrlForwarderSetUp(_))
  415. .WillByDefault(RunOnceCallback<0>(false));
  416. }
  417. void IpcDesktopEnvironmentTest::OnDisconnectCallback() {
  418. DeleteDesktopEnvironment();
  419. }
  420. void IpcDesktopEnvironmentTest::ConnectDesktopChannel(
  421. mojo::ScopedMessagePipeHandle desktop_pipe) {
  422. // Instruct DesktopSessionProxy to connect to the network-to-desktop pipe.
  423. desktop_environment_factory_->OnDesktopSessionAgentAttached(
  424. terminal_id_, /*session_id=*/0, std::move(desktop_pipe));
  425. }
  426. void IpcDesktopEnvironmentTest::RunMainLoopUntilDone() {
  427. bool should_run_loop = task_runner_ != nullptr;
  428. task_runner_ = nullptr;
  429. io_task_runner_ = nullptr;
  430. if (should_run_loop) {
  431. main_run_loop_.Run();
  432. }
  433. }
  434. void IpcDesktopEnvironmentTest::QuitSetupRunLoop() {
  435. setup_run_loop_->Quit();
  436. }
  437. // Runs until the desktop is attached and exits immediately after that.
  438. TEST_F(IpcDesktopEnvironmentTest, Basic) {
  439. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  440. new protocol::MockClipboardStub());
  441. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  442. .Times(0);
  443. // Start the input injector and screen capturer.
  444. input_injector_->Start(std::move(clipboard_stub));
  445. // Run the message loop until the desktop is attached.
  446. setup_run_loop_->Run();
  447. // Stop the test.
  448. DeleteDesktopEnvironment();
  449. }
  450. // Check touchEvents capability is set when the desktop environment can
  451. // inject touch events.
  452. TEST_F(IpcDesktopEnvironmentTest, TouchEventsCapabilities) {
  453. // Create an environment with multi touch enabled.
  454. desktop_environment_ = desktop_environment_factory_->Create(
  455. client_session_control_factory_.GetWeakPtr(),
  456. client_session_events_factory_.GetWeakPtr(), DesktopEnvironmentOptions());
  457. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  458. new protocol::MockClipboardStub());
  459. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  460. .Times(0);
  461. std::string expected_capabilities = "rateLimitResizeRequests";
  462. if (InputInjector::SupportsTouchEvents())
  463. expected_capabilities += " touchEvents";
  464. EXPECT_EQ(expected_capabilities, desktop_environment_->GetCapabilities());
  465. // Start the input injector and screen capturer.
  466. input_injector_->Start(std::move(clipboard_stub));
  467. // Run the message loop until the desktop is attached.
  468. setup_run_loop_->Run();
  469. // Stop the test.
  470. DeleteDesktopEnvironment();
  471. }
  472. // Tests that the video capturer receives a frame over IPC.
  473. TEST_F(IpcDesktopEnvironmentTest, CaptureFrame) {
  474. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  475. new protocol::MockClipboardStub());
  476. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  477. .Times(0);
  478. // Start the input injector and screen capturer.
  479. input_injector_->Start(std::move(clipboard_stub));
  480. video_capturer_->Start(&desktop_capturer_callback_);
  481. // Run the message loop until the desktop is attached.
  482. setup_run_loop_->Run();
  483. // Stop the test when the first frame is captured.
  484. EXPECT_CALL(desktop_capturer_callback_, OnCaptureResultPtr(_, _))
  485. .WillOnce(InvokeWithoutArgs(
  486. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  487. // Capture a single frame.
  488. video_capturer_->CaptureFrame();
  489. }
  490. // Tests that attaching to a new desktop works.
  491. TEST_F(IpcDesktopEnvironmentTest, Reattach) {
  492. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  493. new protocol::MockClipboardStub());
  494. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  495. .Times(0);
  496. // Start the input injector and screen capturer.
  497. input_injector_->Start(std::move(clipboard_stub));
  498. video_capturer_->Start(&desktop_capturer_callback_);
  499. // Run the message loop until the desktop is attached.
  500. setup_run_loop_->Run();
  501. // Create and start a new desktop process object.
  502. setup_run_loop_ = std::make_unique<base::RunLoop>();
  503. DestroyDesktopProcess();
  504. ResetRemoteUrlForwarderConfigurator();
  505. CreateDesktopProcess();
  506. setup_run_loop_->Run();
  507. // Stop the test.
  508. DeleteDesktopEnvironment();
  509. }
  510. // Tests injection of clipboard events.
  511. TEST_F(IpcDesktopEnvironmentTest, InjectClipboardEvent) {
  512. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  513. new protocol::MockClipboardStub());
  514. clipboard_stub_ = clipboard_stub.get();
  515. // Stop the test when a clipboard event is received from the desktop process.
  516. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  517. .Times(1)
  518. .WillOnce(InvokeWithoutArgs(
  519. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  520. // Start the input injector and screen capturer.
  521. input_injector_->Start(std::move(clipboard_stub));
  522. video_capturer_->Start(&desktop_capturer_callback_);
  523. // Run the message loop until the desktop is attached.
  524. setup_run_loop_->Run();
  525. // Expect a single clipboard event.
  526. EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
  527. .Times(1)
  528. .WillOnce(Invoke(this,
  529. &IpcDesktopEnvironmentTest::ReflectClipboardEvent));
  530. // Send a clipboard event.
  531. protocol::ClipboardEvent event;
  532. event.set_mime_type(kMimeTypeTextUtf8);
  533. event.set_data("a");
  534. input_injector_->InjectClipboardEvent(event);
  535. }
  536. // Tests injection of key events.
  537. TEST_F(IpcDesktopEnvironmentTest, InjectKeyEvent) {
  538. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  539. new protocol::MockClipboardStub());
  540. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  541. .Times(0);
  542. // Start the input injector and screen capturer.
  543. input_injector_->Start(std::move(clipboard_stub));
  544. video_capturer_->Start(&desktop_capturer_callback_);
  545. // Run the message loop until the desktop is attached.
  546. setup_run_loop_->Run();
  547. // Expect a single key event.
  548. EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
  549. .Times(AtLeast(1))
  550. .WillRepeatedly(InvokeWithoutArgs(
  551. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  552. // Send a key event.
  553. protocol::KeyEvent event;
  554. event.set_usb_keycode(0x070004);
  555. event.set_pressed(true);
  556. input_injector_->InjectKeyEvent(event);
  557. }
  558. // Tests injection of text events.
  559. TEST_F(IpcDesktopEnvironmentTest, InjectTextEvent) {
  560. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  561. new protocol::MockClipboardStub());
  562. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  563. .Times(0);
  564. // Start the input injector and screen capturer.
  565. input_injector_->Start(std::move(clipboard_stub));
  566. video_capturer_->Start(&desktop_capturer_callback_);
  567. // Run the message loop until the desktop is attached.
  568. setup_run_loop_->Run();
  569. // Expect a single text event.
  570. EXPECT_CALL(*remote_input_injector_, InjectTextEvent(_))
  571. .Times(AtLeast(1))
  572. .WillRepeatedly(InvokeWithoutArgs(
  573. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  574. // Send a text event.
  575. protocol::TextEvent event;
  576. event.set_text("hello");
  577. input_injector_->InjectTextEvent(event);
  578. }
  579. // Tests injection of mouse events.
  580. TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
  581. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  582. new protocol::MockClipboardStub());
  583. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  584. .Times(0);
  585. // Start the input injector and screen capturer.
  586. input_injector_->Start(std::move(clipboard_stub));
  587. video_capturer_->Start(&desktop_capturer_callback_);
  588. // Run the message loop until the desktop is attached.
  589. setup_run_loop_->Run();
  590. // Expect a single mouse event.
  591. EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
  592. .Times(1)
  593. .WillOnce(InvokeWithoutArgs(
  594. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  595. // Send a mouse event.
  596. protocol::MouseEvent event;
  597. event.set_x(0);
  598. event.set_y(0);
  599. input_injector_->InjectMouseEvent(event);
  600. }
  601. // Tests injection of touch events.
  602. TEST_F(IpcDesktopEnvironmentTest, InjectTouchEvent) {
  603. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  604. new protocol::MockClipboardStub());
  605. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  606. .Times(0);
  607. // Start the input injector and screen capturer.
  608. input_injector_->Start(std::move(clipboard_stub));
  609. video_capturer_->Start(&desktop_capturer_callback_);
  610. // Run the message loop until the desktop is attached.
  611. setup_run_loop_->Run();
  612. protocol::TouchEvent event;
  613. event.set_event_type(protocol::TouchEvent::TOUCH_POINT_START);
  614. protocol::TouchEventPoint* point = event.add_touch_points();
  615. point->set_id(0u);
  616. point->set_x(0.0f);
  617. point->set_y(0.0f);
  618. point->set_radius_x(0.0f);
  619. point->set_radius_y(0.0f);
  620. point->set_angle(0.0f);
  621. point->set_pressure(0.0f);
  622. ON_CALL(*remote_input_injector_, InjectTouchEvent(_))
  623. .WillByDefault(InvokeWithoutArgs(
  624. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  625. InSequence s;
  626. // Expect that the event gets propagated to remote_input_injector_.
  627. // And one more call for ReleaseAll().
  628. EXPECT_CALL(*remote_input_injector_,
  629. InjectTouchEvent(EqualsTouchEvent(event)));
  630. EXPECT_CALL(*remote_input_injector_,
  631. InjectTouchEvent(EqualsTouchEventTypeAndId(
  632. protocol::TouchEvent::TOUCH_POINT_CANCEL, 0u)));
  633. // Send the touch event.
  634. input_injector_->InjectTouchEvent(event);
  635. }
  636. // Tests that setting the desktop resolution works.
  637. TEST_F(IpcDesktopEnvironmentTest, SetScreenResolution) {
  638. std::unique_ptr<protocol::MockClipboardStub> clipboard_stub(
  639. new protocol::MockClipboardStub());
  640. EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
  641. .Times(0);
  642. // Start the input injector and screen capturer.
  643. input_injector_->Start(std::move(clipboard_stub));
  644. video_capturer_->Start(&desktop_capturer_callback_);
  645. // Run the message loop until the desktop is attached.
  646. setup_run_loop_->Run();
  647. EXPECT_CALL(mock_desktop_session_manager_, SetScreenResolution(_, _))
  648. .Times(1)
  649. .WillOnce(InvokeWithoutArgs(
  650. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  651. // Change the desktop resolution.
  652. screen_controls_->SetScreenResolution(
  653. ScreenResolution(webrtc::DesktopSize(100, 100),
  654. webrtc::DesktopVector(96, 96)),
  655. absl::nullopt);
  656. }
  657. TEST_F(IpcDesktopEnvironmentTest, CheckUrlForwarderState) {
  658. EXPECT_CALL(*remote_url_forwarder_configurator_, IsUrlForwarderSetUp(_))
  659. .WillOnce(RunOnceCallback<0>(true));
  660. base::MockCallback<UrlForwarderConfigurator::IsUrlForwarderSetUpCallback>
  661. callback;
  662. EXPECT_CALL(callback, Run(true))
  663. .WillOnce([&]() {
  664. // Do it again when the state is already known.
  665. url_forwarder_configurator_->IsUrlForwarderSetUp(callback.Get());
  666. })
  667. .WillOnce(InvokeWithoutArgs(
  668. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  669. // Run the message loop until the desktop is attached.
  670. setup_run_loop_->Run();
  671. url_forwarder_configurator_->IsUrlForwarderSetUp(callback.Get());
  672. // Run now rather than in TearDown() so that we can verify |callback|.
  673. RunMainLoopUntilDone();
  674. }
  675. TEST_F(IpcDesktopEnvironmentTest, SetUpUrlForwarderHappyPath) {
  676. EXPECT_CALL(*remote_url_forwarder_configurator_, IsUrlForwarderSetUp(_))
  677. .WillOnce(RunOnceCallback<0>(false));
  678. EXPECT_CALL(*remote_url_forwarder_configurator_, SetUpUrlForwarder(_))
  679. .WillOnce([](auto& callback) {
  680. callback.Run(SetUpUrlForwarderResponse::USER_INTERVENTION_REQUIRED);
  681. callback.Run(SetUpUrlForwarderResponse::COMPLETE);
  682. });
  683. base::MockCallback<UrlForwarderConfigurator::SetUpUrlForwarderCallback>
  684. setup_state_callback;
  685. base::MockCallback<UrlForwarderConfigurator::IsUrlForwarderSetUpCallback>
  686. is_set_up_callback;
  687. {
  688. InSequence s;
  689. EXPECT_CALL(is_set_up_callback, Run(false)).WillOnce([&]() {
  690. // Post task to prevent reentrant issue.
  691. base::SequencedTaskRunnerHandle::Get()->PostTask(
  692. FROM_HERE,
  693. base::BindOnce(&UrlForwarderConfigurator::SetUpUrlForwarder,
  694. base::Unretained(url_forwarder_configurator_.get()),
  695. setup_state_callback.Get()));
  696. });
  697. EXPECT_CALL(setup_state_callback,
  698. Run(SetUpUrlForwarderResponse::USER_INTERVENTION_REQUIRED))
  699. .Times(1);
  700. EXPECT_CALL(setup_state_callback, Run(SetUpUrlForwarderResponse::COMPLETE))
  701. .WillOnce([&]() {
  702. url_forwarder_configurator_->IsUrlForwarderSetUp(
  703. is_set_up_callback.Get());
  704. });
  705. EXPECT_CALL(is_set_up_callback, Run(true))
  706. .WillOnce(InvokeWithoutArgs(
  707. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  708. }
  709. // Run the message loop until the desktop is attached.
  710. setup_run_loop_->Run();
  711. url_forwarder_configurator_->IsUrlForwarderSetUp(is_set_up_callback.Get());
  712. // Run now rather than in TearDown() so that we can verify |callback|.
  713. RunMainLoopUntilDone();
  714. }
  715. TEST_F(IpcDesktopEnvironmentTest, SetUpUrlForwarderFailed) {
  716. EXPECT_CALL(*remote_url_forwarder_configurator_, IsUrlForwarderSetUp(_))
  717. .WillOnce(RunOnceCallback<0>(false));
  718. EXPECT_CALL(*remote_url_forwarder_configurator_, SetUpUrlForwarder(_))
  719. .WillOnce(RunOnceCallback<0>(SetUpUrlForwarderResponse::FAILED));
  720. base::MockCallback<UrlForwarderConfigurator::SetUpUrlForwarderCallback>
  721. setup_state_callback;
  722. base::MockCallback<UrlForwarderConfigurator::IsUrlForwarderSetUpCallback>
  723. is_set_up_callback;
  724. {
  725. InSequence s;
  726. EXPECT_CALL(is_set_up_callback, Run(false)).WillOnce([&]() {
  727. // Post task to prevent reentrant issue.
  728. base::SequencedTaskRunnerHandle::Get()->PostTask(
  729. FROM_HERE,
  730. base::BindOnce(&UrlForwarderConfigurator::SetUpUrlForwarder,
  731. base::Unretained(url_forwarder_configurator_.get()),
  732. setup_state_callback.Get()));
  733. });
  734. EXPECT_CALL(setup_state_callback, Run(SetUpUrlForwarderResponse::FAILED))
  735. .WillOnce([&]() {
  736. url_forwarder_configurator_->IsUrlForwarderSetUp(
  737. is_set_up_callback.Get());
  738. });
  739. EXPECT_CALL(is_set_up_callback, Run(false))
  740. .WillOnce(InvokeWithoutArgs(
  741. this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
  742. }
  743. // Run the message loop until the desktop is attached.
  744. setup_run_loop_->Run();
  745. url_forwarder_configurator_->IsUrlForwarderSetUp(is_set_up_callback.Get());
  746. // Run now rather than in TearDown() so that we can verify |callback|.
  747. RunMainLoopUntilDone();
  748. }
  749. } // namespace remoting