blob: 0632537ba7168c7e8e2f46a4af4525c6b032c35d [file] [log] [blame]
Avi Drissmand6cdf9b2022-09-15 19:52:531// Copyright 2012 The Chromium Authors
[email protected]da457fc2013-03-14 16:32:122// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/host/me2me_desktop_environment.h"
6
Peter Boström42afa23f2021-04-02 22:10:467#include <memory>
sergeyu1417e0132015-12-23 19:01:228#include <utility>
9
Yuwei Huangc7ec1c02022-09-22 22:09:2910#include "base/environment.h"
[email protected]da457fc2013-03-14 16:32:1211#include "base/logging.h"
dcheng0765c492016-04-06 22:41:5312#include "base/memory/ptr_util.h"
Patrick Monette643cdf62021-10-15 19:13:4213#include "base/task/single_thread_task_runner.h"
avic5960f32015-12-22 22:49:4814#include "build/build_config.h"
[email protected]3a5b82c2014-02-20 13:28:1415#include "remoting/base/logging.h"
Joe Downing505ae0d02018-10-17 17:47:3016#include "remoting/host/action_executor.h"
Joe Downingb0fb5422021-12-07 21:26:2017#include "remoting/host/base/screen_controls.h"
[email protected]231316a2013-03-25 06:01:1218#include "remoting/host/client_session_control.h"
[email protected]96361d02013-05-08 18:26:1819#include "remoting/host/curtain_mode.h"
[email protected]da457fc2013-03-14 16:32:1220#include "remoting/host/desktop_resizer.h"
[email protected]c308f5122013-04-05 03:32:0621#include "remoting/host/host_window.h"
[email protected]ac115ce2013-04-24 20:44:3822#include "remoting/host/host_window_proxy.h"
sergeyub3e637e2016-10-27 23:31:2123#include "remoting/host/input_injector.h"
Joe Downing4dfb3892018-08-24 18:56:0624#include "remoting/host/input_monitor/local_input_monitor.h"
Yuwei Huang6df36ef2021-09-15 18:48:0625#include "remoting/host/remote_open_url/remote_open_url_util.h"
[email protected]da457fc2013-03-14 16:32:1226#include "remoting/host/resizing_host_observer.h"
rkuroiwaa7815e72015-06-05 21:39:0427#include "remoting/protocol/capability_names.h"
[email protected]cd8088052013-10-15 02:39:0228#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
zijiehea69c7842016-11-11 01:28:2029#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
[email protected]ac115ce2013-04-24 20:44:3830
Xiaohan Wang453b38672022-01-13 20:02:4431#if BUILDFLAG(IS_POSIX)
[email protected]ac115ce2013-04-24 20:44:3832#include <sys/types.h>
33#include <unistd.h>
Xiaohan Wang453b38672022-01-13 20:02:4434#endif // BUILDFLAG(IS_POSIX)
[email protected]da457fc2013-03-14 16:32:1235
Xiaohan Wang453b38672022-01-13 20:02:4436#if BUILDFLAG(IS_WIN)
Joe Downingb511e4a92018-11-16 21:10:1337#include "base/win/windows_version.h"
Xiaohan Wang453b38672022-01-13 20:02:4438#endif // BUILDFLAG(IS_WIN)
Joe Downingb511e4a92018-11-16 21:10:1339
Yuwei Huang0b237c4cb2022-09-23 22:58:5440#if defined(REMOTING_USE_X11)
Salman3948951802023-01-19 13:13:4041#include "remoting/host/linux/wayland_utils.h"
Yuwei Huang0b237c4cb2022-09-23 22:58:5442#include "remoting/host/linux/x11_util.h"
43#include "ui/gfx/x/connection.h"
44#endif // defined(REMOTING_USE_X11)
45
[email protected]da457fc2013-03-14 16:32:1246namespace remoting {
47
Yuwei Huangc7ec1c02022-09-22 22:09:2948namespace {
49
Yuwei Huang0b237c4cb2022-09-23 22:58:5450#if defined(REMOTING_USE_X11)
Yuwei Huangc7ec1c02022-09-22 22:09:2951
Yuwei Huang0b237c4cb2022-09-23 22:58:5452// Helper function that caches the result of IsUsingVideoDummyDriver().
53bool UsingVideoDummyDriver() {
54 static bool is_using_dummy_driver =
55 IsUsingVideoDummyDriver(x11::Connection::Get());
56 return is_using_dummy_driver;
57}
Yuwei Huangc7ec1c02022-09-22 22:09:2958
Yuwei Huang0b237c4cb2022-09-23 22:58:5459#endif // defined(REMOTING_USE_X11)
Yuwei Huangc7ec1c02022-09-22 22:09:2960
61} // namespace
62
[email protected]da457fc2013-03-14 16:32:1263Me2MeDesktopEnvironment::~Me2MeDesktopEnvironment() {
[email protected]231316a2013-03-25 06:01:1264 DCHECK(caller_task_runner()->BelongsToCurrentThread());
[email protected]da457fc2013-03-14 16:32:1265}
66
Joe Downing505ae0d02018-10-17 17:47:3067std::unique_ptr<ActionExecutor>
68Me2MeDesktopEnvironment::CreateActionExecutor() {
69 DCHECK(caller_task_runner()->BelongsToCurrentThread());
70
71 return ActionExecutor::Create();
72}
73
dcheng0765c492016-04-06 22:41:5374std::unique_ptr<ScreenControls>
75Me2MeDesktopEnvironment::CreateScreenControls() {
[email protected]231316a2013-03-25 06:01:1276 DCHECK(caller_task_runner()->BelongsToCurrentThread());
[email protected]da457fc2013-03-14 16:32:1277
rkjnsn5d5d89b92016-06-07 21:34:2178 // We only want to restore the host resolution on disconnect if we are not
79 // curtained so we don't mess up the user's window layout unnecessarily if
80 // they disconnect and reconnect. Both OS X and Windows will restore the
81 // resolution automatically when the user logs back in on the console, and on
82 // Linux the curtain-mode uses a separate session.
Lambros Lambroud27736d2022-06-16 00:52:2783 auto resizer = std::make_unique<ResizingHostObserver>(
84 DesktopResizer::Create(), curtain_ == nullptr);
85 resizer->RegisterForDisplayChanges(*GetDisplayInfoMonitor());
86 return resizer;
[email protected]da457fc2013-03-14 16:32:1287}
88
[email protected]4a444c42013-06-09 01:43:1489std::string Me2MeDesktopEnvironment::GetCapabilities() const {
Lambros Lambrouf9a02aaf2022-03-29 00:39:4290 std::string capabilities = BasicDesktopEnvironment::GetCapabilities();
91 if (!capabilities.empty()) {
92 capabilities += " ";
93 }
sergeyub3e637e2016-10-27 23:31:2194 capabilities += protocol::kRateLimitResizeRequests;
Lambros Lambrou4c46dcb02020-07-22 18:14:5495
sergeyub3e637e2016-10-27 23:31:2196 if (InputInjector::SupportsTouchEvents()) {
97 capabilities += " ";
98 capabilities += protocol::kTouchEventsCapability;
99 }
Joseph Arhare76c3042017-08-03 02:01:13100
Joseph Arhar111ddceb2017-09-01 04:57:30101 if (desktop_environment_options().enable_file_transfer()) {
102 capabilities += " ";
103 capabilities += protocol::kFileTransferCapability;
104 }
Joseph Arhare76c3042017-08-03 02:01:13105
Xiaohan Wang453b38672022-01-13 20:02:44106#if BUILDFLAG(IS_WIN)
Joe Downingb511e4a92018-11-16 21:10:13107 capabilities += " ";
108 capabilities += protocol::kSendAttentionSequenceAction;
109
110 if (base::win::OSInfo::GetInstance()->version_type() !=
111 base::win::VersionType::SUITE_HOME) {
112 capabilities += " ";
113 capabilities += protocol::kLockWorkstationAction;
114 }
Xiaohan Wang453b38672022-01-13 20:02:44115#endif // BUILDFLAG(IS_WIN)
Joe Downingb511e4a92018-11-16 21:10:13116
Yuwei Huangc31b4d72021-09-13 23:04:49117 if (desktop_environment_options().enable_remote_open_url() &&
118 IsRemoteOpenUrlSupported()) {
Yuwei Huangc49279792021-07-22 23:31:48119 capabilities += " ";
120 capabilities += protocol::kRemoteOpenUrlCapability;
121 }
Yuwei Huang9d0cb6dc2021-05-10 21:04:51122
Yuwei Huang78b3fc52021-10-20 21:03:24123 if (desktop_environment_options().enable_remote_webauthn()) {
124 capabilities += " ";
125 capabilities += protocol::kRemoteWebAuthnCapability;
126 }
127
Lambros Lambroubbb4e162022-12-12 23:14:46128#if BUILDFLAG(IS_LINUX) && defined(REMOTING_USE_X11)
Salman3948951802023-01-19 13:13:40129 if (!IsRunningWayland()) {
Yuwei Huangc7ec1c02022-09-22 22:09:29130 capabilities += " ";
Salman3948951802023-01-19 13:13:40131 capabilities += protocol::kMultiStreamCapability;
132
133 // Client-controlled layout is only supported with Xorg+video-dummy.
134 if (UsingVideoDummyDriver()) {
135 capabilities += " ";
136 capabilities += protocol::kClientControlledLayoutCapability;
137 }
Yuwei Huangc7ec1c02022-09-22 22:09:29138 }
Salman Malik46a0f062022-11-08 17:28:23139#endif // BUILDFLAG(IS_LINUX) && defined(REMOTING_USE_X11)
Lambros Lambroufc279d82022-09-21 18:37:39140
rkuroiwaa7815e72015-06-05 21:39:04141 return capabilities;
[email protected]4a444c42013-06-09 01:43:14142}
143
[email protected]231316a2013-03-25 06:01:12144Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
145 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
sergeyu85df3c482016-02-15 05:59:08146 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
[email protected]231316a2013-03-25 06:01:12147 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
zijiehe4aa6ea42016-11-12 01:28:16148 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
Gary Kacmarcika7e33e42019-02-22 19:23:28149 base::WeakPtr<ClientSessionControl> client_session_control,
zijiehe4aa6ea42016-11-12 01:28:16150 const DesktopEnvironmentOptions& options)
[email protected]231316a2013-03-25 06:01:12151 : BasicDesktopEnvironment(caller_task_runner,
sergeyu85df3c482016-02-15 05:59:08152 video_capture_task_runner,
[email protected]231316a2013-03-25 06:01:12153 input_task_runner,
zijiehe4aa6ea42016-11-12 01:28:16154 ui_task_runner,
Gary Kacmarcika7e33e42019-02-22 19:23:28155 client_session_control,
zijiehe4aa6ea42016-11-12 01:28:16156 options) {
[email protected]231316a2013-03-25 06:01:12157 DCHECK(caller_task_runner->BelongsToCurrentThread());
sergeyu85df3c482016-02-15 05:59:08158
zijiehe4aa6ea42016-11-12 01:28:16159 // TODO(zijiehe): This logic should belong to RemotingMe2MeHost, instead of
160 // Me2MeDesktopEnvironment, which does not take response to create a new
161 // session.
sergeyu85df3c482016-02-15 05:59:08162 // X DAMAGE is not enabled by default, since it is broken on many systems -
163 // see http://crbug.com/73423. It's safe to enable it here because it works
164 // properly under Xvfb.
zijiehe4aa6ea42016-11-12 01:28:16165 mutable_desktop_capture_options()->set_use_update_notifications(true);
Joe Downing3588e232022-11-18 23:30:16166
167#if BUILDFLAG(IS_LINUX)
168 // Setting this option to false means that the capture differ wrapper will not
169 // be used when the X11 capturer is selected. This reduces the X11 capture
170 // time by a few milliseconds per frame and is safe because we can rely on
171 // XDAMAGE to identify the changed regions rather than checking each pixel
172 // ourselves.
173 mutable_desktop_capture_options()->set_detect_updated_region(false);
174#endif
Salman1c8dcf22022-11-28 15:53:21175
Salman3948951802023-01-19 13:13:40176#if BUILDFLAG(IS_LINUX)
177 if (IsRunningWayland()) {
178 mutable_desktop_capture_options()->set_prefer_cursor_embedded(false);
179 }
Salman1c8dcf22022-11-28 15:53:21180#endif
[email protected]96361d02013-05-08 18:26:18181}
182
183bool Me2MeDesktopEnvironment::InitializeSecurity(
zijiehe4aa6ea42016-11-12 01:28:16184 base::WeakPtr<ClientSessionControl> client_session_control) {
[email protected]96361d02013-05-08 18:26:18185 DCHECK(caller_task_runner()->BelongsToCurrentThread());
186
187 // Detach the session from the local console if the caller requested.
zijiehe4aa6ea42016-11-12 01:28:16188 if (desktop_environment_options().enable_curtaining()) {
Joe Downingfd8a4222023-01-11 23:39:40189 curtain_ = CurtainMode::Create(caller_task_runner(), ui_task_runner(),
190 client_session_control);
rkjnsn5d5d89b92016-06-07 21:34:21191 if (!curtain_->Activate()) {
[email protected]04eca612013-05-15 04:02:25192 LOG(ERROR) << "Failed to activate the curtain mode.";
rkjnsn5d5d89b92016-06-07 21:34:21193 curtain_ = nullptr;
194 return false;
195 }
196 return true;
[email protected]96361d02013-05-08 18:26:18197 }
198
199 // Otherwise, if the session is shared with the local user start monitoring
200 // the local input and create the in-session UI.
Xiaohan Wang453b38672022-01-13 20:02:44201#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
[email protected]04eca612013-05-15 04:02:25202 bool want_user_interface = false;
Xiaohan Wang453b38672022-01-13 20:02:44203#elif BUILDFLAG(IS_APPLE)
[email protected]ac115ce2013-04-24 20:44:38204 // Don't try to display any UI on top of the system's login screen as this
205 // is rejected by the Window Server on OS X 10.7.4, and prevents the
206 // capturer from working (http://crbug.com/140984).
207
208 // TODO(lambroslambrou): Use a better technique of detecting whether we're
209 // running in the LoginWindow context, and refactor this into a separate
210 // function to be used here and in CurtainMode::ActivateCurtain().
[email protected]04eca612013-05-15 04:02:25211 bool want_user_interface = getuid() != 0;
lambroslambrou51e19b92016-04-13 21:30:41212#else
zijiehe4aa6ea42016-11-12 01:28:16213 bool want_user_interface =
214 desktop_environment_options().enable_user_interface();
lambroslambrou51e19b92016-04-13 21:30:41215#endif
[email protected]ac115ce2013-04-24 20:44:38216
[email protected]ac115ce2013-04-24 20:44:38217 if (want_user_interface) {
[email protected]04eca612013-05-15 04:02:25218 // Create the local input monitor.
zijiehe4aa6ea42016-11-12 01:28:16219 local_input_monitor_ = LocalInputMonitor::Create(
Joe Downingf86c8a012018-08-29 16:49:04220 caller_task_runner(), input_task_runner(), ui_task_runner());
221 local_input_monitor_->StartMonitoringForClientSession(
zijiehe4aa6ea42016-11-12 01:28:16222 client_session_control);
[email protected]04eca612013-05-15 04:02:25223
Joe Downingf86c8a012018-08-29 16:49:04224 // Create the disconnect window.
Xiaohan Wang453b38672022-01-13 20:02:44225#if BUILDFLAG(IS_WIN)
Joe Downing8e95ed182018-08-30 22:57:19226 disconnect_window_ =
227 HostWindow::CreateAutoHidingDisconnectWindow(LocalInputMonitor::Create(
228 caller_task_runner(), input_task_runner(), ui_task_runner()));
229#else
[email protected]fc877cf2013-07-31 23:08:39230 disconnect_window_ = HostWindow::CreateDisconnectWindow();
Joe Downing8e95ed182018-08-30 22:57:19231#endif
Peter Boström42afa23f2021-04-02 22:10:46232 disconnect_window_ = std::make_unique<HostWindowProxy>(
233 caller_task_runner(), ui_task_runner(), std::move(disconnect_window_));
[email protected]ac115ce2013-04-24 20:44:38234 disconnect_window_->Start(client_session_control);
235 }
[email protected]96361d02013-05-08 18:26:18236
237 return true;
[email protected]da457fc2013-03-14 16:32:12238}
239
[email protected]231316a2013-03-25 06:01:12240Me2MeDesktopEnvironmentFactory::Me2MeDesktopEnvironmentFactory(
241 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
sergeyu85df3c482016-02-15 05:59:08242 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
[email protected]231316a2013-03-25 06:01:12243 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
Scott Violet9778dcd2019-06-20 21:59:37244 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
[email protected]231316a2013-03-25 06:01:12245 : BasicDesktopEnvironmentFactory(caller_task_runner,
sergeyu85df3c482016-02-15 05:59:08246 video_capture_task_runner,
[email protected]231316a2013-03-25 06:01:12247 input_task_runner,
Scott Violet9778dcd2019-06-20 21:59:37248 ui_task_runner) {}
[email protected]da457fc2013-03-14 16:32:12249
Joe Downingfd8a4222023-01-11 23:39:40250Me2MeDesktopEnvironmentFactory::~Me2MeDesktopEnvironmentFactory() = default;
[email protected]da457fc2013-03-14 16:32:12251
dcheng0765c492016-04-06 22:41:53252std::unique_ptr<DesktopEnvironment> Me2MeDesktopEnvironmentFactory::Create(
zijiehe4aa6ea42016-11-12 01:28:16253 base::WeakPtr<ClientSessionControl> client_session_control,
Yuwei Huang3628aa52021-12-08 23:00:55254 base::WeakPtr<ClientSessionEvents> client_session_events,
zijiehe4aa6ea42016-11-12 01:28:16255 const DesktopEnvironmentOptions& options) {
[email protected]231316a2013-03-25 06:01:12256 DCHECK(caller_task_runner()->BelongsToCurrentThread());
257
dcheng0765c492016-04-06 22:41:53258 std::unique_ptr<Me2MeDesktopEnvironment> desktop_environment(
Scott Violet9778dcd2019-06-20 21:59:37259 new Me2MeDesktopEnvironment(caller_task_runner(),
260 video_capture_task_runner(),
261 input_task_runner(), ui_task_runner(),
262 client_session_control, options));
zijiehe4aa6ea42016-11-12 01:28:16263 if (!desktop_environment->InitializeSecurity(client_session_control)) {
sergeyuafce9782014-09-29 19:38:30264 return nullptr;
[email protected]96361d02013-05-08 18:26:18265 }
266
Jeroen Dhollandera3ce38f2022-08-25 07:18:02267 return desktop_environment;
[email protected]96361d02013-05-08 18:26:18268}
269
[email protected]da457fc2013-03-14 16:32:12270} // namespace remoting