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