15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implements the Windows service controlling Me2Me host processes 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running within user sessions. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_process.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/alias.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_proxy.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/auto_thread.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/auto_thread_task_runner.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/chromoting_messages.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/desktop_environment.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_session_agent.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopProcess::DesktopProcess( 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> caller_task_runner, 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> input_task_runner, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& daemon_channel_name) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : caller_task_runner_(caller_task_runner), 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_task_runner_(input_task_runner), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) daemon_channel_name_(daemon_channel_name) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(base::MessageLoopForUI::IsCurrent()); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopProcess::~DesktopProcess() { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!daemon_channel_); 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!desktop_agent_.get()); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopEnvironmentFactory& DesktopProcess::desktop_environment_factory() { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *desktop_environment_factory_; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopProcess::OnNetworkProcessDisconnected() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnChannelError(); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopProcess::InjectSas() { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) daemon_channel_->Send(new ChromotingDesktopDaemonMsg_InjectSas()); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopProcess::OnMessageReceived(const IPC::Message& message) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(DesktopProcess, message) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(handled) << "Received unexpected IPC type: " << message.type(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopProcess::OnChannelConnected(int32 peer_pid) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "IPC: desktop <- daemon (" << peer_pid << ")"; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopProcess::OnChannelError() { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown the desktop process. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) daemon_channel_.reset(); 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (desktop_agent_.get()) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_agent_->Stop(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_agent_ = NULL; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caller_task_runner_ = NULL; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_task_runner_ = NULL; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_factory_.reset(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DesktopProcess::Start( 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner_->BelongsToCurrentThread()); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!desktop_environment_factory_); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(desktop_environment_factory); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_factory_ = desktop_environment_factory.Pass(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Launch the audio capturing thread. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> audio_task_runner; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // On Windows the AudioCapturer requires COM, so we run a single-threaded 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // apartment, which requires a UI thread. 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_task_runner = 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::CreateWithLoopAndComInitTypes("ChromotingAudioThread", 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) caller_task_runner_, 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::TYPE_UI, 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::COM_INIT_STA); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else // !defined(OS_WIN) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_task_runner = AutoThread::CreateWithType( 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "ChromotingAudioThread", caller_task_runner_, base::MessageLoop::TYPE_IO); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // !defined(OS_WIN) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the I/O thread. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> io_task_runner = 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::CreateWithType( 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "I/O thread", caller_task_runner_, base::MessageLoop::TYPE_IO); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Launch the video capture thread. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner = 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AutoThread::Create("Video capture thread", caller_task_runner_); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a desktop agent. 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) desktop_agent_ = new DesktopSessionAgent(audio_task_runner, 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) caller_task_runner_, 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) input_task_runner_, 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) io_task_runner, 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) video_capture_task_runner); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start the agent and create an IPC channel to talk to it. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::PlatformFileForTransit desktop_pipe; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!desktop_agent_->Start(AsWeakPtr(), &desktop_pipe)) { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_agent_ = NULL; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) caller_task_runner_ = NULL; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_task_runner_ = NULL; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_factory_.reset(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connect to the daemon. 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) daemon_channel_ = IPC::ChannelProxy::Create(daemon_channel_name_, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Channel::MODE_CLIENT, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) io_task_runner.get()); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass |desktop_pipe| to the daemon. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) daemon_channel_->Send( 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromotingDesktopDaemonMsg_DesktopAttached(desktop_pipe)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopProcess::OnCrash(const std::string& function_name, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& file_name, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int& line_number) { 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char message[1024]; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::snprintf(message, sizeof(message), 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Requested by %s at %s, line %d.", 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) function_name.c_str(), file_name.c_str(), line_number); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::debug::Alias(message); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The daemon requested us to crash the process. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(false) << message; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 168