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