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/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
    215