basic_desktop_environment.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright (c) 2012 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/basic_desktop_environment.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/check.h"
  9. #include "base/task/single_thread_task_runner.h"
  10. #include "build/build_config.h"
  11. #include "remoting/host/action_executor.h"
  12. #include "remoting/host/audio_capturer.h"
  13. #include "remoting/host/base/screen_controls.h"
  14. #include "remoting/host/client_session_control.h"
  15. #include "remoting/host/desktop_capturer_proxy.h"
  16. #include "remoting/host/desktop_display_info_monitor.h"
  17. #include "remoting/host/file_transfer/local_file_operations.h"
  18. #include "remoting/host/input_injector.h"
  19. #include "remoting/host/keyboard_layout_monitor.h"
  20. #include "remoting/host/mouse_cursor_monitor_proxy.h"
  21. #include "remoting/host/remote_open_url/url_forwarder_configurator.h"
  22. #include "remoting/host/webauthn/remote_webauthn_extension_notifier.h"
  23. #include "remoting/protocol/capability_names.h"
  24. #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
  25. #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
  26. #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
  27. #if BUILDFLAG(IS_WIN)
  28. #include "remoting/host/win/evaluate_d3d.h"
  29. #endif
  30. #if defined(REMOTING_USE_X11)
  31. #include "base/threading/watchdog.h"
  32. #include "remoting/host/linux/x11_util.h"
  33. #endif
  34. namespace remoting {
  35. #if defined(REMOTING_USE_X11)
  36. namespace {
  37. // The maximum amount of time we will wait for the IgnoreXServerGrabs() to
  38. // return before we crash the host.
  39. constexpr base::TimeDelta kWaitForIgnoreXServerGrabsTimeout = base::Seconds(30);
  40. // Helper class to monitor the call to
  41. // webrtc::SharedXDisplay::IgnoreXServerGrabs() (on a temporary thread), which
  42. // has been observed to occasionally hang forever and zombify the host.
  43. // This class crashes the host if the IgnoreXServerGrabs() call takes too long,
  44. // so that the ME2ME daemon process can respawn the host.
  45. // See: crbug.com/1130090
  46. class IgnoreXServerGrabsWatchdog : public base::Watchdog {
  47. public:
  48. IgnoreXServerGrabsWatchdog()
  49. : base::Watchdog(kWaitForIgnoreXServerGrabsTimeout,
  50. "IgnoreXServerGrabs Watchdog",
  51. /* enabled= */ true) {}
  52. ~IgnoreXServerGrabsWatchdog() override = default;
  53. void Alarm() override {
  54. // Crash the host if IgnoreXServerGrabs() takes too long.
  55. CHECK(false) << "IgnoreXServerGrabs() timed out.";
  56. }
  57. };
  58. } // namespace
  59. #endif // defined(REMOTING_USE_X11)
  60. BasicDesktopEnvironment::~BasicDesktopEnvironment() {
  61. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  62. }
  63. std::unique_ptr<ActionExecutor>
  64. BasicDesktopEnvironment::CreateActionExecutor() {
  65. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  66. // Connection mode derivations (It2Me/Me2Me) should override this method and
  67. // return an executor instance if applicable.
  68. return nullptr;
  69. }
  70. std::unique_ptr<AudioCapturer> BasicDesktopEnvironment::CreateAudioCapturer() {
  71. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  72. return AudioCapturer::Create();
  73. }
  74. std::unique_ptr<InputInjector> BasicDesktopEnvironment::CreateInputInjector() {
  75. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  76. return InputInjector::Create(input_task_runner(), ui_task_runner());
  77. }
  78. std::unique_ptr<ScreenControls>
  79. BasicDesktopEnvironment::CreateScreenControls() {
  80. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  81. return nullptr;
  82. }
  83. DesktopDisplayInfoMonitor* BasicDesktopEnvironment::GetDisplayInfoMonitor() {
  84. if (!display_info_monitor_) {
  85. using VideoLayoutCallback =
  86. base::RepeatingCallback<void(std::unique_ptr<protocol::VideoLayout>)>;
  87. VideoLayoutCallback video_layout_callback =
  88. base::BindRepeating(&ClientSessionControl::OnDesktopDisplayChanged,
  89. client_session_control_);
  90. // |video_layout_callback| is bound to |client_session_control_| which is a
  91. // WeakPtr, but it accepts a VideoLayout proto as the parameter. DDIM needs
  92. // a callback that accepts a DesktopDisplayInfo& instead.
  93. auto converting_callback =
  94. base::BindRepeating([](const DesktopDisplayInfo& info) {
  95. return info.GetVideoLayoutProto();
  96. });
  97. DesktopDisplayInfoMonitor::Callback callback =
  98. std::move(converting_callback).Then(std::move(video_layout_callback));
  99. display_info_monitor_ =
  100. std::make_unique<DesktopDisplayInfoMonitor>(ui_task_runner_);
  101. display_info_monitor_->AddCallback(std::move(callback));
  102. }
  103. return display_info_monitor_.get();
  104. }
  105. std::unique_ptr<webrtc::MouseCursorMonitor>
  106. BasicDesktopEnvironment::CreateMouseCursorMonitor() {
  107. return std::make_unique<MouseCursorMonitorProxy>(video_capture_task_runner_,
  108. desktop_capture_options());
  109. }
  110. std::unique_ptr<KeyboardLayoutMonitor>
  111. BasicDesktopEnvironment::CreateKeyboardLayoutMonitor(
  112. base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback) {
  113. return KeyboardLayoutMonitor::Create(std::move(callback), input_task_runner_);
  114. }
  115. std::unique_ptr<FileOperations>
  116. BasicDesktopEnvironment::CreateFileOperations() {
  117. return std::make_unique<LocalFileOperations>(ui_task_runner_);
  118. }
  119. std::unique_ptr<UrlForwarderConfigurator>
  120. BasicDesktopEnvironment::CreateUrlForwarderConfigurator() {
  121. return UrlForwarderConfigurator::Create();
  122. }
  123. std::string BasicDesktopEnvironment::GetCapabilities() const {
  124. // This capability is added here because it is not supported by
  125. // multi-process hosts, so it should not be returned by the
  126. // overridden method IpcDesktopEnvironment::GetCapabilities().
  127. //
  128. // TODO(lambroslambrou): When this feature is working for
  129. // multi-process hosts, move this capability from here to
  130. // ClientSession::OnConnectionAuthenticated().
  131. return protocol::kMultiStreamCapability;
  132. }
  133. void BasicDesktopEnvironment::SetCapabilities(const std::string& capabilities) {
  134. }
  135. uint32_t BasicDesktopEnvironment::GetDesktopSessionId() const {
  136. return UINT32_MAX;
  137. }
  138. std::unique_ptr<DesktopAndCursorConditionalComposer>
  139. BasicDesktopEnvironment::CreateComposingVideoCapturer() {
  140. #if BUILDFLAG(IS_APPLE)
  141. // Mac includes the mouse cursor in the captured image in curtain mode.
  142. if (options_.enable_curtaining())
  143. return nullptr;
  144. #endif
  145. return std::make_unique<DesktopAndCursorConditionalComposer>(
  146. CreateVideoCapturer());
  147. }
  148. std::unique_ptr<RemoteWebAuthnStateChangeNotifier>
  149. BasicDesktopEnvironment::CreateRemoteWebAuthnStateChangeNotifier() {
  150. return std::make_unique<RemoteWebAuthnExtensionNotifier>();
  151. }
  152. std::unique_ptr<DesktopCapturer>
  153. BasicDesktopEnvironment::CreateVideoCapturer() {
  154. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  155. auto result = std::make_unique<DesktopCapturerProxy>(
  156. video_capture_task_runner_, ui_task_runner_);
  157. result->set_desktop_display_info_monitor(GetDisplayInfoMonitor());
  158. result->CreateCapturer(desktop_capture_options());
  159. return std::move(result);
  160. }
  161. BasicDesktopEnvironment::BasicDesktopEnvironment(
  162. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  163. scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
  164. scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
  165. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
  166. base::WeakPtr<ClientSessionControl> client_session_control,
  167. const DesktopEnvironmentOptions& options)
  168. : caller_task_runner_(caller_task_runner),
  169. video_capture_task_runner_(video_capture_task_runner),
  170. input_task_runner_(input_task_runner),
  171. ui_task_runner_(ui_task_runner),
  172. client_session_control_(client_session_control),
  173. options_(options) {
  174. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  175. #if defined(REMOTING_USE_X11)
  176. // TODO(yuweih): The watchdog is just to test the hypothesis.
  177. // The IgnoreXServerGrabs() call should probably be moved to whichever
  178. // thread that created desktop_capture_options().x_display().
  179. IgnoreXServerGrabsWatchdog watchdog;
  180. watchdog.Arm();
  181. desktop_capture_options().x_display()->IgnoreXServerGrabs();
  182. watchdog.Disarm();
  183. #elif BUILDFLAG(IS_WIN)
  184. options_.desktop_capture_options()->set_allow_directx_capturer(
  185. IsD3DAvailable());
  186. #endif
  187. }
  188. BasicDesktopEnvironmentFactory::BasicDesktopEnvironmentFactory(
  189. scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
  190. scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
  191. scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
  192. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
  193. : caller_task_runner_(caller_task_runner),
  194. video_capture_task_runner_(video_capture_task_runner),
  195. input_task_runner_(input_task_runner),
  196. ui_task_runner_(ui_task_runner) {}
  197. BasicDesktopEnvironmentFactory::~BasicDesktopEnvironmentFactory() = default;
  198. bool BasicDesktopEnvironmentFactory::SupportsAudioCapture() const {
  199. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  200. return AudioCapturer::IsSupported();
  201. }
  202. } // namespace remoting