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