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 25namespace remoting { 26 27IpcDesktopEnvironment::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 46IpcDesktopEnvironment::~IpcDesktopEnvironment() { 47} 48 49scoped_ptr<AudioCapturer> IpcDesktopEnvironment::CreateAudioCapturer() { 50 return desktop_session_proxy_->CreateAudioCapturer(); 51} 52 53scoped_ptr<InputInjector> IpcDesktopEnvironment::CreateInputInjector() { 54 return desktop_session_proxy_->CreateInputInjector(); 55} 56 57scoped_ptr<ScreenControls> IpcDesktopEnvironment::CreateScreenControls() { 58 return desktop_session_proxy_->CreateScreenControls(); 59} 60 61scoped_ptr<webrtc::MouseCursorMonitor> 62IpcDesktopEnvironment::CreateMouseCursorMonitor() { 63 return desktop_session_proxy_->CreateMouseCursorMonitor(); 64} 65 66scoped_ptr<webrtc::DesktopCapturer> 67IpcDesktopEnvironment::CreateVideoCapturer() { 68 return desktop_session_proxy_->CreateVideoCapturer(); 69} 70 71std::string IpcDesktopEnvironment::GetCapabilities() const { 72 return desktop_session_proxy_->GetCapabilities(); 73} 74 75void IpcDesktopEnvironment::SetCapabilities(const std::string& capabilities) { 76 return desktop_session_proxy_->SetCapabilities(capabilities); 77} 78 79scoped_ptr<GnubbyAuthHandler> IpcDesktopEnvironment::CreateGnubbyAuthHandler( 80 protocol::ClientStub* client_stub) { 81 return scoped_ptr<GnubbyAuthHandler>(); 82} 83 84IpcDesktopEnvironmentFactory::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 100IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() { 101} 102 103scoped_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 117void IpcDesktopEnvironmentFactory::SetEnableCurtaining(bool enable) { 118 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 119 120 curtain_enabled_ = enable; 121} 122 123bool IpcDesktopEnvironmentFactory::SupportsAudioCapture() const { 124 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 125 126 return AudioCapturer::IsSupported(); 127} 128 129void 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 146void 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 165void 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 182void 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 207void 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