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 24namespace remoting { 25 26IpcDesktopEnvironment::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 45IpcDesktopEnvironment::~IpcDesktopEnvironment() { 46} 47 48scoped_ptr<AudioCapturer> IpcDesktopEnvironment::CreateAudioCapturer() { 49 return desktop_session_proxy_->CreateAudioCapturer(); 50} 51 52scoped_ptr<InputInjector> IpcDesktopEnvironment::CreateInputInjector() { 53 return desktop_session_proxy_->CreateInputInjector(); 54} 55 56scoped_ptr<ScreenControls> IpcDesktopEnvironment::CreateScreenControls() { 57 return desktop_session_proxy_->CreateScreenControls(); 58} 59 60scoped_ptr<webrtc::ScreenCapturer> 61IpcDesktopEnvironment::CreateVideoCapturer() { 62 return desktop_session_proxy_->CreateVideoCapturer(); 63} 64 65std::string IpcDesktopEnvironment::GetCapabilities() const { 66 return desktop_session_proxy_->GetCapabilities(); 67} 68 69void IpcDesktopEnvironment::SetCapabilities(const std::string& capabilities) { 70 return desktop_session_proxy_->SetCapabilities(capabilities); 71} 72 73scoped_ptr<GnubbyAuthHandler> IpcDesktopEnvironment::CreateGnubbyAuthHandler( 74 protocol::ClientStub* client_stub) { 75 return scoped_ptr<GnubbyAuthHandler>(); 76} 77 78IpcDesktopEnvironmentFactory::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 94IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() { 95} 96 97scoped_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 111void IpcDesktopEnvironmentFactory::SetEnableCurtaining(bool enable) { 112 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 113 114 curtain_enabled_ = enable; 115} 116 117bool IpcDesktopEnvironmentFactory::SupportsAudioCapture() const { 118 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 119 120 return AudioCapturer::IsSupported(); 121} 122 123void 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 140void 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 159void 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 176void 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 201void 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