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