desktop_process.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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// This file implements the Windows service controlling Me2Me host processes 6// running within user sessions. 7 8#include "remoting/host/desktop_process.h" 9 10#include "base/bind.h" 11#include "base/bind_helpers.h" 12#include "base/debug/alias.h" 13#include "base/logging.h" 14#include "base/memory/ref_counted.h" 15#include "base/message_loop.h" 16#include "base/string_util.h" 17#include "ipc/ipc_channel_proxy.h" 18#include "remoting/base/auto_thread.h" 19#include "remoting/base/auto_thread_task_runner.h" 20#include "remoting/host/chromoting_messages.h" 21#include "remoting/host/desktop_environment.h" 22#include "remoting/host/desktop_session_agent.h" 23 24namespace remoting { 25 26DesktopProcess::DesktopProcess( 27 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, 28 scoped_refptr<AutoThreadTaskRunner> input_task_runner, 29 const std::string& daemon_channel_name) 30 : caller_task_runner_(caller_task_runner), 31 input_task_runner_(input_task_runner), 32 daemon_channel_name_(daemon_channel_name) { 33 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 34 DCHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_UI); 35} 36 37DesktopProcess::~DesktopProcess() { 38 DCHECK(!daemon_channel_); 39 DCHECK(!desktop_agent_); 40} 41 42DesktopEnvironmentFactory& DesktopProcess::desktop_environment_factory() { 43 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 44 45 return *desktop_environment_factory_; 46} 47 48void DesktopProcess::OnNetworkProcessDisconnected() { 49 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 50 51 OnChannelError(); 52} 53 54void DesktopProcess::InjectSas() { 55 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 56 57 daemon_channel_->Send(new ChromotingDesktopDaemonMsg_InjectSas()); 58} 59 60bool DesktopProcess::OnMessageReceived(const IPC::Message& message) { 61 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 62 63 bool handled = true; 64 IPC_BEGIN_MESSAGE_MAP(DesktopProcess, message) 65 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) 66 IPC_MESSAGE_UNHANDLED(handled = false) 67 IPC_END_MESSAGE_MAP() 68 69 CHECK(handled) << "Received unexpected IPC type: " << message.type(); 70 return handled; 71} 72 73void DesktopProcess::OnChannelConnected(int32 peer_pid) { 74 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 75 76 VLOG(1) << "IPC: desktop <- daemon (" << peer_pid << ")"; 77} 78 79void DesktopProcess::OnChannelError() { 80 // Shutdown the desktop process. 81 daemon_channel_.reset(); 82 if (desktop_agent_) { 83 desktop_agent_->Stop(); 84 desktop_agent_ = NULL; 85 } 86 87 caller_task_runner_ = NULL; 88 input_task_runner_ = NULL; 89 desktop_environment_factory_.reset(); 90} 91 92bool DesktopProcess::Start( 93 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory) { 94 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 95 DCHECK(!desktop_environment_factory_); 96 DCHECK(desktop_environment_factory); 97 98 desktop_environment_factory_ = desktop_environment_factory.Pass(); 99 100 // Launch the audio capturing thread. 101 scoped_refptr<AutoThreadTaskRunner> audio_task_runner; 102#if defined(OS_WIN) 103 // On Windows the AudioCapturer requires COM, so we run a single-threaded 104 // apartment, which requires a UI thread. 105 audio_task_runner = 106 AutoThread::CreateWithLoopAndComInitTypes("ChromotingAudioThread", 107 caller_task_runner_, 108 base::MessageLoop::TYPE_UI, 109 AutoThread::COM_INIT_STA); 110#else // !defined(OS_WIN) 111 audio_task_runner = AutoThread::CreateWithType( 112 "ChromotingAudioThread", caller_task_runner_, base::MessageLoop::TYPE_IO); 113#endif // !defined(OS_WIN) 114 115 // Launch the I/O thread. 116 scoped_refptr<AutoThreadTaskRunner> io_task_runner = 117 AutoThread::CreateWithType( 118 "I/O thread", caller_task_runner_, base::MessageLoop::TYPE_IO); 119 120 // Launch the video capture thread. 121 scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner = 122 AutoThread::Create("Video capture thread", caller_task_runner_); 123 124 // Create a desktop agent. 125 desktop_agent_ = new DesktopSessionAgent(audio_task_runner, 126 caller_task_runner_, 127 input_task_runner_, 128 io_task_runner, 129 video_capture_task_runner); 130 131 // Start the agent and create an IPC channel to talk to it. 132 IPC::PlatformFileForTransit desktop_pipe; 133 if (!desktop_agent_->Start(AsWeakPtr(), &desktop_pipe)) { 134 desktop_agent_ = NULL; 135 caller_task_runner_ = NULL; 136 input_task_runner_ = NULL; 137 desktop_environment_factory_.reset(); 138 return false; 139 } 140 141 // Connect to the daemon. 142 daemon_channel_.reset(new IPC::ChannelProxy(daemon_channel_name_, 143 IPC::Channel::MODE_CLIENT, 144 this, 145 io_task_runner)); 146 147 // Pass |desktop_pipe| to the daemon. 148 daemon_channel_->Send( 149 new ChromotingDesktopDaemonMsg_DesktopAttached(desktop_pipe)); 150 151 return true; 152} 153 154void DesktopProcess::OnCrash(const std::string& function_name, 155 const std::string& file_name, 156 const int& line_number) { 157 char message[1024]; 158 base::snprintf(message, sizeof(message), 159 "Requested by %s at %s, line %d.", 160 function_name.c_str(), file_name.c_str(), line_number); 161 base::debug::Alias(message); 162 163 // The daemon requested us to crash the process. 164 CHECK(false) << message; 165} 166 167} // namespace remoting 168