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