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
5 #include "remoting/host/me2me_desktop_environment.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/single_thread_task_runner.h"
12 #include "build/build_config.h"
13 #include "remoting/base/logging.h"
14 #include "remoting/host/action_executor.h"
15 #include "remoting/host/client_session_control.h"
16 #include "remoting/host/curtain_mode.h"
17 #include "remoting/host/desktop_resizer.h"
18 #include "remoting/host/host_window.h"
19 #include "remoting/host/host_window_proxy.h"
20 #include "remoting/host/input_injector.h"
21 #include "remoting/host/input_monitor/local_input_monitor.h"
22 #include "remoting/host/resizing_host_observer.h"
23 #include "remoting/host/screen_controls.h"
24 #include "remoting/protocol/capability_names.h"
25 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
26 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
27
28 #if defined(OS_POSIX)
29 #include <sys/types.h>
30 #include <unistd.h>
31 #endif // defined(OS_POSIX)
32
33 #if defined(OS_WIN)
34 #include "base/win/windows_version.h"
35 #endif // defined(OS_WIN)
36
37 namespace remoting {
38
~Me2MeDesktopEnvironment()39 Me2MeDesktopEnvironment::~Me2MeDesktopEnvironment() {
40 DCHECK(caller_task_runner()->BelongsToCurrentThread());
41 }
42
43 std::unique_ptr<ActionExecutor>
CreateActionExecutor()44 Me2MeDesktopEnvironment::CreateActionExecutor() {
45 DCHECK(caller_task_runner()->BelongsToCurrentThread());
46
47 return ActionExecutor::Create();
48 }
49
50 std::unique_ptr<ScreenControls>
CreateScreenControls()51 Me2MeDesktopEnvironment::CreateScreenControls() {
52 DCHECK(caller_task_runner()->BelongsToCurrentThread());
53
54 // We only want to restore the host resolution on disconnect if we are not
55 // curtained so we don't mess up the user's window layout unnecessarily if
56 // they disconnect and reconnect. Both OS X and Windows will restore the
57 // resolution automatically when the user logs back in on the console, and on
58 // Linux the curtain-mode uses a separate session.
59 return base::WrapUnique(new ResizingHostObserver(DesktopResizer::Create(),
60 curtain_ == nullptr));
61 }
62
GetCapabilities() const63 std::string Me2MeDesktopEnvironment::GetCapabilities() const {
64 std::string capabilities;
65 capabilities += protocol::kRateLimitResizeRequests;
66
67 if (InputInjector::SupportsTouchEvents()) {
68 capabilities += " ";
69 capabilities += protocol::kTouchEventsCapability;
70 }
71
72 if (desktop_environment_options().enable_file_transfer()) {
73 capabilities += " ";
74 capabilities += protocol::kFileTransferCapability;
75 }
76
77 #if defined(OS_WIN)
78 capabilities += " ";
79 capabilities += protocol::kSendAttentionSequenceAction;
80
81 if (base::win::OSInfo::GetInstance()->version_type() !=
82 base::win::VersionType::SUITE_HOME) {
83 capabilities += " ";
84 capabilities += protocol::kLockWorkstationAction;
85 }
86 #endif // defined(OS_WIN)
87
88 return capabilities;
89 }
90
Me2MeDesktopEnvironment(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,base::WeakPtr<ClientSessionControl> client_session_control,const DesktopEnvironmentOptions & options)91 Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
92 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
93 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
94 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
95 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
96 base::WeakPtr<ClientSessionControl> client_session_control,
97 const DesktopEnvironmentOptions& options)
98 : BasicDesktopEnvironment(caller_task_runner,
99 video_capture_task_runner,
100 input_task_runner,
101 ui_task_runner,
102 client_session_control,
103 options) {
104 DCHECK(caller_task_runner->BelongsToCurrentThread());
105
106 // TODO(zijiehe): This logic should belong to RemotingMe2MeHost, instead of
107 // Me2MeDesktopEnvironment, which does not take response to create a new
108 // session.
109 // X DAMAGE is not enabled by default, since it is broken on many systems -
110 // see http://crbug.com/73423. It's safe to enable it here because it works
111 // properly under Xvfb.
112 mutable_desktop_capture_options()->set_use_update_notifications(true);
113 }
114
InitializeSecurity(base::WeakPtr<ClientSessionControl> client_session_control)115 bool Me2MeDesktopEnvironment::InitializeSecurity(
116 base::WeakPtr<ClientSessionControl> client_session_control) {
117 DCHECK(caller_task_runner()->BelongsToCurrentThread());
118
119 // Detach the session from the local console if the caller requested.
120 if (desktop_environment_options().enable_curtaining()) {
121 curtain_ = CurtainMode::Create(
122 caller_task_runner(), ui_task_runner(), client_session_control);
123 if (!curtain_->Activate()) {
124 LOG(ERROR) << "Failed to activate the curtain mode.";
125 curtain_ = nullptr;
126 return false;
127 }
128 return true;
129 }
130
131 // Otherwise, if the session is shared with the local user start monitoring
132 // the local input and create the in-session UI.
133 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
134 bool want_user_interface = false;
135 #elif defined(OS_APPLE)
136 // Don't try to display any UI on top of the system's login screen as this
137 // is rejected by the Window Server on OS X 10.7.4, and prevents the
138 // capturer from working (http://crbug.com/140984).
139
140 // TODO(lambroslambrou): Use a better technique of detecting whether we're
141 // running in the LoginWindow context, and refactor this into a separate
142 // function to be used here and in CurtainMode::ActivateCurtain().
143 bool want_user_interface = getuid() != 0;
144 #else
145 bool want_user_interface =
146 desktop_environment_options().enable_user_interface();
147 #endif
148
149 if (want_user_interface) {
150 // Create the local input monitor.
151 local_input_monitor_ = LocalInputMonitor::Create(
152 caller_task_runner(), input_task_runner(), ui_task_runner());
153 local_input_monitor_->StartMonitoringForClientSession(
154 client_session_control);
155
156 // Create the disconnect window.
157 #if defined(OS_WIN)
158 disconnect_window_ =
159 HostWindow::CreateAutoHidingDisconnectWindow(LocalInputMonitor::Create(
160 caller_task_runner(), input_task_runner(), ui_task_runner()));
161 #else
162 disconnect_window_ = HostWindow::CreateDisconnectWindow();
163 #endif
164 disconnect_window_.reset(new HostWindowProxy(
165 caller_task_runner(), ui_task_runner(), std::move(disconnect_window_)));
166 disconnect_window_->Start(client_session_control);
167 }
168
169 return true;
170 }
171
Me2MeDesktopEnvironmentFactory(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)172 Me2MeDesktopEnvironmentFactory::Me2MeDesktopEnvironmentFactory(
173 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
174 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
175 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
176 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
177 : BasicDesktopEnvironmentFactory(caller_task_runner,
178 video_capture_task_runner,
179 input_task_runner,
180 ui_task_runner) {}
181
~Me2MeDesktopEnvironmentFactory()182 Me2MeDesktopEnvironmentFactory::~Me2MeDesktopEnvironmentFactory() {
183 }
184
Create(base::WeakPtr<ClientSessionControl> client_session_control,const DesktopEnvironmentOptions & options)185 std::unique_ptr<DesktopEnvironment> Me2MeDesktopEnvironmentFactory::Create(
186 base::WeakPtr<ClientSessionControl> client_session_control,
187 const DesktopEnvironmentOptions& options) {
188 DCHECK(caller_task_runner()->BelongsToCurrentThread());
189
190 std::unique_ptr<Me2MeDesktopEnvironment> desktop_environment(
191 new Me2MeDesktopEnvironment(caller_task_runner(),
192 video_capture_task_runner(),
193 input_task_runner(), ui_task_runner(),
194 client_session_control, options));
195 if (!desktop_environment->InitializeSecurity(client_session_control)) {
196 return nullptr;
197 }
198
199 return std::move(desktop_environment);
200 }
201
202 } // namespace remoting
203