// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/host/ipc_desktop_environment.h" #include #include "base/compiler_specific.h" #include "base/logging.h" #include "base/process/process_handle.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" #include "ipc/ipc_sender.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_messages.h" #include "remoting/host/client_session_control.h" #include "remoting/host/desktop_session.h" #include "remoting/host/desktop_session_proxy.h" #include "remoting/host/input_injector.h" #include "remoting/host/screen_controls.h" #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" namespace remoting { IpcDesktopEnvironment::IpcDesktopEnvironment( scoped_refptr audio_task_runner, scoped_refptr caller_task_runner, scoped_refptr io_task_runner, base::WeakPtr client_session_control, base::WeakPtr desktop_session_connector, bool virtual_terminal, bool supports_touch_events) { DCHECK(caller_task_runner->BelongsToCurrentThread()); desktop_session_proxy_ = new DesktopSessionProxy( audio_task_runner, caller_task_runner, io_task_runner, client_session_control, desktop_session_connector, virtual_terminal, supports_touch_events); } IpcDesktopEnvironment::~IpcDesktopEnvironment() {} scoped_ptr IpcDesktopEnvironment::CreateAudioCapturer() { return desktop_session_proxy_->CreateAudioCapturer(); } scoped_ptr IpcDesktopEnvironment::CreateInputInjector() { return desktop_session_proxy_->CreateInputInjector(); } scoped_ptr IpcDesktopEnvironment::CreateScreenControls() { return desktop_session_proxy_->CreateScreenControls(); } scoped_ptr IpcDesktopEnvironment::CreateMouseCursorMonitor() { return desktop_session_proxy_->CreateMouseCursorMonitor(); } scoped_ptr IpcDesktopEnvironment::CreateVideoCapturer() { return desktop_session_proxy_->CreateVideoCapturer(); } std::string IpcDesktopEnvironment::GetCapabilities() const { return desktop_session_proxy_->GetCapabilities(); } void IpcDesktopEnvironment::SetCapabilities(const std::string& capabilities) { return desktop_session_proxy_->SetCapabilities(capabilities); } IpcDesktopEnvironmentFactory::IpcDesktopEnvironmentFactory( scoped_refptr audio_task_runner, scoped_refptr caller_task_runner, scoped_refptr io_task_runner, IPC::Sender* daemon_channel) : audio_task_runner_(audio_task_runner), caller_task_runner_(caller_task_runner), io_task_runner_(io_task_runner), daemon_channel_(daemon_channel), connector_factory_(this) {} IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() {} scoped_ptr IpcDesktopEnvironmentFactory::Create( base::WeakPtr client_session_control) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); return make_scoped_ptr(new IpcDesktopEnvironment( audio_task_runner_, caller_task_runner_, io_task_runner_, client_session_control, connector_factory_.GetWeakPtr(), curtain_enabled_, supports_touch_events_)); } void IpcDesktopEnvironmentFactory::SetEnableCurtaining(bool enable) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); curtain_enabled_ = enable; } bool IpcDesktopEnvironmentFactory::SupportsAudioCapture() const { DCHECK(caller_task_runner_->BelongsToCurrentThread()); return AudioCapturer::IsSupported(); } void IpcDesktopEnvironmentFactory::ConnectTerminal( DesktopSessionProxy* desktop_session_proxy, const ScreenResolution& resolution, bool virtual_terminal) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); int id = next_id_++; bool inserted = active_connections_.insert( std::make_pair(id, desktop_session_proxy)).second; CHECK(inserted); VLOG(1) << "Network: registered desktop environment " << id; daemon_channel_->Send(new ChromotingNetworkHostMsg_ConnectTerminal( id, resolution, virtual_terminal)); } void IpcDesktopEnvironmentFactory::DisconnectTerminal( DesktopSessionProxy* desktop_session_proxy) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); ActiveConnectionsList::iterator i; for (i = active_connections_.begin(); i != active_connections_.end(); ++i) { if (i->second == desktop_session_proxy) break; } if (i != active_connections_.end()) { int id = i->first; active_connections_.erase(i); VLOG(1) << "Network: unregistered desktop environment " << id; daemon_channel_->Send(new ChromotingNetworkHostMsg_DisconnectTerminal(id)); } } void IpcDesktopEnvironmentFactory::SetScreenResolution( DesktopSessionProxy* desktop_session_proxy, const ScreenResolution& resolution) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); ActiveConnectionsList::iterator i; for (i = active_connections_.begin(); i != active_connections_.end(); ++i) { if (i->second == desktop_session_proxy) break; } if (i != active_connections_.end()) { daemon_channel_->Send(new ChromotingNetworkDaemonMsg_SetScreenResolution( i->first, resolution)); } } void IpcDesktopEnvironmentFactory::OnDesktopSessionAgentAttached( int terminal_id, base::ProcessHandle desktop_process_handle, IPC::PlatformFileForTransit desktop_pipe) { if (!caller_task_runner_->BelongsToCurrentThread()) { caller_task_runner_->PostTask(FROM_HERE, base::Bind( &IpcDesktopEnvironmentFactory::OnDesktopSessionAgentAttached, base::Unretained(this), terminal_id, desktop_process_handle, desktop_pipe)); return; } base::Process desktop_process(desktop_process_handle); ActiveConnectionsList::iterator i = active_connections_.find(terminal_id); if (i != active_connections_.end()) { i->second->DetachFromDesktop(); i->second->AttachToDesktop(std::move(desktop_process), desktop_pipe); } else { #if defined(OS_POSIX) DCHECK(desktop_pipe.auto_close); base::File pipe_closer(IPC::PlatformFileForTransitToFile(desktop_pipe)); #endif // defined(OS_POSIX) } } void IpcDesktopEnvironmentFactory::OnTerminalDisconnected(int terminal_id) { if (!caller_task_runner_->BelongsToCurrentThread()) { caller_task_runner_->PostTask(FROM_HERE, base::Bind( &IpcDesktopEnvironmentFactory::OnTerminalDisconnected, base::Unretained(this), terminal_id)); return; } ActiveConnectionsList::iterator i = active_connections_.find(terminal_id); if (i != active_connections_.end()) { DesktopSessionProxy* desktop_session_proxy = i->second; active_connections_.erase(i); // Disconnect the client session. desktop_session_proxy->DisconnectSession(protocol::OK); } } } // namespace remoting