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.
5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions.
8 #include "remoting/host/desktop_process.h"
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/message_loop.h"
16 #include "base/strings/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"
26 DesktopProcess::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
);
37 DesktopProcess::~DesktopProcess() {
38 DCHECK(!daemon_channel_
);
39 DCHECK(!desktop_agent_
.get());
42 DesktopEnvironmentFactory
& DesktopProcess::desktop_environment_factory() {
43 DCHECK(caller_task_runner_
->BelongsToCurrentThread());
45 return *desktop_environment_factory_
;
48 void DesktopProcess::OnNetworkProcessDisconnected() {
49 DCHECK(caller_task_runner_
->BelongsToCurrentThread());
54 void DesktopProcess::InjectSas() {
55 DCHECK(caller_task_runner_
->BelongsToCurrentThread());
57 daemon_channel_
->Send(new ChromotingDesktopDaemonMsg_InjectSas());
60 bool DesktopProcess::OnMessageReceived(const IPC::Message
& message
) {
61 DCHECK(caller_task_runner_
->BelongsToCurrentThread());
64 IPC_BEGIN_MESSAGE_MAP(DesktopProcess
, message
)
65 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash
, OnCrash
)
66 IPC_MESSAGE_UNHANDLED(handled
= false)
69 CHECK(handled
) << "Received unexpected IPC type: " << message
.type();
73 void DesktopProcess::OnChannelConnected(int32 peer_pid
) {
74 DCHECK(caller_task_runner_
->BelongsToCurrentThread());
76 VLOG(1) << "IPC: desktop <- daemon (" << peer_pid
<< ")";
79 void DesktopProcess::OnChannelError() {
80 // Shutdown the desktop process.
81 daemon_channel_
.reset();
82 if (desktop_agent_
.get()) {
83 desktop_agent_
->Stop();
84 desktop_agent_
= NULL
;
87 caller_task_runner_
= NULL
;
88 input_task_runner_
= NULL
;
89 desktop_environment_factory_
.reset();
92 bool 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
);
98 desktop_environment_factory_
= desktop_environment_factory
.Pass();
100 // Launch the audio capturing thread.
101 scoped_refptr
<AutoThreadTaskRunner
> audio_task_runner
;
103 // On Windows the AudioCapturer requires COM, so we run a single-threaded
104 // apartment, which requires a UI thread.
106 AutoThread::CreateWithLoopAndComInitTypes("ChromotingAudioThread",
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)
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
);
120 // Launch the video capture thread.
121 scoped_refptr
<AutoThreadTaskRunner
> video_capture_task_runner
=
122 AutoThread::Create("Video capture thread", caller_task_runner_
);
124 // Create a desktop agent.
125 desktop_agent_
= new DesktopSessionAgent(audio_task_runner
,
129 video_capture_task_runner
);
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();
141 // Connect to the daemon.
142 daemon_channel_
.reset(new IPC::ChannelProxy(daemon_channel_name_
,
143 IPC::Channel::MODE_CLIENT
,
145 io_task_runner
.get()));
147 // Pass |desktop_pipe| to the daemon.
148 daemon_channel_
->Send(
149 new ChromotingDesktopDaemonMsg_DesktopAttached(desktop_pipe
));
154 void DesktopProcess::OnCrash(const std::string
& function_name
,
155 const std::string
& file_name
,
156 const int& line_number
) {
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
);
163 // The daemon requested us to crash the process.
164 CHECK(false) << message
;
167 } // namespace remoting