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/ipc_desktop_environment.h"
6
7 #include <utility>
8
9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11 #include "base/process/process_handle.h"
12 #include "base/single_thread_task_runner.h"
13 #include "ipc/ipc_sender.h"
14 #include "remoting/host/audio_capturer.h"
15 #include "remoting/host/chromoting_messages.h"
16 #include "remoting/host/client_session_control.h"
17 #include "remoting/host/desktop_session.h"
18 #include "remoting/host/desktop_session_proxy.h"
19 #include "remoting/host/gnubby_auth_handler.h"
20 #include "remoting/host/input_injector.h"
21 #include "remoting/host/screen_controls.h"
22 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
23
24 namespace remoting {
25
IpcDesktopEnvironment(scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,base::WeakPtr<ClientSessionControl> client_session_control,base::WeakPtr<DesktopSessionConnector> desktop_session_connector,bool virtual_terminal)26 IpcDesktopEnvironment::IpcDesktopEnvironment(
27 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
28 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
29 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
30 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
31 base::WeakPtr<ClientSessionControl> client_session_control,
32 base::WeakPtr<DesktopSessionConnector> desktop_session_connector,
33 bool virtual_terminal) {
34 DCHECK(caller_task_runner->BelongsToCurrentThread());
35
36 desktop_session_proxy_ = new DesktopSessionProxy(audio_task_runner,
37 caller_task_runner,
38 io_task_runner,
39 capture_task_runner,
40 client_session_control,
41 desktop_session_connector,
42 virtual_terminal);
43 }
44
~IpcDesktopEnvironment()45 IpcDesktopEnvironment::~IpcDesktopEnvironment() {
46 }
47
CreateAudioCapturer()48 scoped_ptr<AudioCapturer> IpcDesktopEnvironment::CreateAudioCapturer() {
49 return desktop_session_proxy_->CreateAudioCapturer();
50 }
51
CreateInputInjector()52 scoped_ptr<InputInjector> IpcDesktopEnvironment::CreateInputInjector() {
53 return desktop_session_proxy_->CreateInputInjector();
54 }
55
CreateScreenControls()56 scoped_ptr<ScreenControls> IpcDesktopEnvironment::CreateScreenControls() {
57 return desktop_session_proxy_->CreateScreenControls();
58 }
59
60 scoped_ptr<webrtc::ScreenCapturer>
CreateVideoCapturer()61 IpcDesktopEnvironment::CreateVideoCapturer() {
62 return desktop_session_proxy_->CreateVideoCapturer();
63 }
64
GetCapabilities() const65 std::string IpcDesktopEnvironment::GetCapabilities() const {
66 return desktop_session_proxy_->GetCapabilities();
67 }
68
SetCapabilities(const std::string & capabilities)69 void IpcDesktopEnvironment::SetCapabilities(const std::string& capabilities) {
70 return desktop_session_proxy_->SetCapabilities(capabilities);
71 }
72
CreateGnubbyAuthHandler(protocol::ClientStub * client_stub)73 scoped_ptr<GnubbyAuthHandler> IpcDesktopEnvironment::CreateGnubbyAuthHandler(
74 protocol::ClientStub* client_stub) {
75 return scoped_ptr<GnubbyAuthHandler>();
76 }
77
IpcDesktopEnvironmentFactory(scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,IPC::Sender * daemon_channel)78 IpcDesktopEnvironmentFactory::IpcDesktopEnvironmentFactory(
79 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
80 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
81 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
82 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
83 IPC::Sender* daemon_channel)
84 : audio_task_runner_(audio_task_runner),
85 caller_task_runner_(caller_task_runner),
86 capture_task_runner_(capture_task_runner),
87 io_task_runner_(io_task_runner),
88 curtain_enabled_(false),
89 daemon_channel_(daemon_channel),
90 connector_factory_(this),
91 next_id_(0) {
92 }
93
~IpcDesktopEnvironmentFactory()94 IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() {
95 }
96
Create(base::WeakPtr<ClientSessionControl> client_session_control)97 scoped_ptr<DesktopEnvironment> IpcDesktopEnvironmentFactory::Create(
98 base::WeakPtr<ClientSessionControl> client_session_control) {
99 DCHECK(caller_task_runner_->BelongsToCurrentThread());
100
101 return scoped_ptr<DesktopEnvironment>(
102 new IpcDesktopEnvironment(audio_task_runner_,
103 caller_task_runner_,
104 capture_task_runner_,
105 io_task_runner_,
106 client_session_control,
107 connector_factory_.GetWeakPtr(),
108 curtain_enabled_));
109 }
110
SetEnableCurtaining(bool enable)111 void IpcDesktopEnvironmentFactory::SetEnableCurtaining(bool enable) {
112 DCHECK(caller_task_runner_->BelongsToCurrentThread());
113
114 curtain_enabled_ = enable;
115 }
116
SupportsAudioCapture() const117 bool IpcDesktopEnvironmentFactory::SupportsAudioCapture() const {
118 DCHECK(caller_task_runner_->BelongsToCurrentThread());
119
120 return AudioCapturer::IsSupported();
121 }
122
ConnectTerminal(DesktopSessionProxy * desktop_session_proxy,const ScreenResolution & resolution,bool virtual_terminal)123 void IpcDesktopEnvironmentFactory::ConnectTerminal(
124 DesktopSessionProxy* desktop_session_proxy,
125 const ScreenResolution& resolution,
126 bool virtual_terminal) {
127 DCHECK(caller_task_runner_->BelongsToCurrentThread());
128
129 int id = next_id_++;
130 bool inserted = active_connections_.insert(
131 std::make_pair(id, desktop_session_proxy)).second;
132 CHECK(inserted);
133
134 VLOG(1) << "Network: registered desktop environment " << id;
135
136 daemon_channel_->Send(new ChromotingNetworkHostMsg_ConnectTerminal(
137 id, resolution, virtual_terminal));
138 }
139
DisconnectTerminal(DesktopSessionProxy * desktop_session_proxy)140 void IpcDesktopEnvironmentFactory::DisconnectTerminal(
141 DesktopSessionProxy* desktop_session_proxy) {
142 DCHECK(caller_task_runner_->BelongsToCurrentThread());
143
144 ActiveConnectionsList::iterator i;
145 for (i = active_connections_.begin(); i != active_connections_.end(); ++i) {
146 if (i->second == desktop_session_proxy)
147 break;
148 }
149
150 if (i != active_connections_.end()) {
151 int id = i->first;
152 active_connections_.erase(i);
153
154 VLOG(1) << "Network: unregistered desktop environment " << id;
155 daemon_channel_->Send(new ChromotingNetworkHostMsg_DisconnectTerminal(id));
156 }
157 }
158
SetScreenResolution(DesktopSessionProxy * desktop_session_proxy,const ScreenResolution & resolution)159 void IpcDesktopEnvironmentFactory::SetScreenResolution(
160 DesktopSessionProxy* desktop_session_proxy,
161 const ScreenResolution& resolution) {
162 DCHECK(caller_task_runner_->BelongsToCurrentThread());
163
164 ActiveConnectionsList::iterator i;
165 for (i = active_connections_.begin(); i != active_connections_.end(); ++i) {
166 if (i->second == desktop_session_proxy)
167 break;
168 }
169
170 if (i != active_connections_.end()) {
171 daemon_channel_->Send(new ChromotingNetworkDaemonMsg_SetScreenResolution(
172 i->first, resolution));
173 }
174 }
175
OnDesktopSessionAgentAttached(int terminal_id,base::ProcessHandle desktop_process,IPC::PlatformFileForTransit desktop_pipe)176 void IpcDesktopEnvironmentFactory::OnDesktopSessionAgentAttached(
177 int terminal_id,
178 base::ProcessHandle desktop_process,
179 IPC::PlatformFileForTransit desktop_pipe) {
180 if (!caller_task_runner_->BelongsToCurrentThread()) {
181 caller_task_runner_->PostTask(FROM_HERE, base::Bind(
182 &IpcDesktopEnvironmentFactory::OnDesktopSessionAgentAttached,
183 base::Unretained(this), terminal_id, desktop_process, desktop_pipe));
184 return;
185 }
186
187 ActiveConnectionsList::iterator i = active_connections_.find(terminal_id);
188 if (i != active_connections_.end()) {
189 i->second->DetachFromDesktop();
190 i->second->AttachToDesktop(desktop_process, desktop_pipe);
191 } else {
192 base::CloseProcessHandle(desktop_process);
193
194 #if defined(OS_POSIX)
195 DCHECK(desktop_pipe.auto_close);
196 base::File pipe_closer(IPC::PlatformFileForTransitToFile(desktop_pipe));
197 #endif // defined(OS_POSIX)
198 }
199 }
200
OnTerminalDisconnected(int terminal_id)201 void IpcDesktopEnvironmentFactory::OnTerminalDisconnected(int terminal_id) {
202 if (!caller_task_runner_->BelongsToCurrentThread()) {
203 caller_task_runner_->PostTask(FROM_HERE, base::Bind(
204 &IpcDesktopEnvironmentFactory::OnTerminalDisconnected,
205 base::Unretained(this), terminal_id));
206 return;
207 }
208
209 ActiveConnectionsList::iterator i = active_connections_.find(terminal_id);
210 if (i != active_connections_.end()) {
211 DesktopSessionProxy* desktop_session_proxy = i->second;
212 active_connections_.erase(i);
213
214 // Disconnect the client session.
215 desktop_session_proxy->DisconnectSession();
216 }
217 }
218
219 } // namespace remoting
220