blob: 23d42b862e31fd3d23ed214510b9a0bd4e54fdb0 [file] [log] [blame]
[email protected]60ccc242012-10-17 21:06:241// 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/desktop_session_win.h"
6
[email protected]5b731f3e2013-03-15 07:28:227#include <limits>
8#include <sddl.h>
9
[email protected]9410c0a2013-02-23 06:07:2110#include "base/base_switches.h"
11#include "base/command_line.h"
[email protected]5b731f3e2013-03-15 07:28:2212#include "base/files/file_path.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
[email protected]60ccc242012-10-17 21:06:2416#include "base/path_service.h"
[email protected]eaf92532013-06-11 07:39:1917#include "base/strings/stringprintf.h"
[email protected]906265872013-06-07 22:40:4518#include "base/strings/utf_string_conversions.h"
[email protected]5b731f3e2013-03-15 07:28:2219#include "base/threading/thread_checker.h"
20#include "base/timer.h"
[email protected]5b731f3e2013-03-15 07:28:2221#include "base/win/scoped_comptr.h"
22#include "base/win/scoped_handle.h"
[email protected]85c7fda22013-05-18 01:35:4723#include "base/win/windows_version.h"
[email protected]12066cb2012-10-25 03:25:4324#include "ipc/ipc_message_macros.h"
[email protected]5b731f3e2013-03-15 07:28:2225#include "ipc/ipc_platform_file.h"
[email protected]e36460f2013-03-08 09:29:3226#include "net/base/ip_endpoint.h"
[email protected]12066cb2012-10-25 03:25:4327#include "remoting/base/auto_thread_task_runner.h"
[email protected]5b731f3e2013-03-15 07:28:2228// MIDL-generated declarations and definitions.
29#include "remoting/host/chromoting_lib.h"
[email protected]12066cb2012-10-25 03:25:4330#include "remoting/host/chromoting_messages.h"
[email protected]60ccc242012-10-17 21:06:2431#include "remoting/host/daemon_process.h"
[email protected]5b731f3e2013-03-15 07:28:2232#include "remoting/host/desktop_session.h"
[email protected]9410c0a2013-02-23 06:07:2133#include "remoting/host/host_main.h"
34#include "remoting/host/ipc_constants.h"
[email protected]0dffd552012-12-07 01:08:0935#include "remoting/host/sas_injector.h"
[email protected]739e2802013-03-18 01:03:4836#include "remoting/host/screen_resolution.h"
[email protected]5b731f3e2013-03-15 07:28:2237#include "remoting/host/win/host_service.h"
[email protected]60ccc242012-10-17 21:06:2438#include "remoting/host/win/worker_process_launcher.h"
[email protected]60ccc242012-10-17 21:06:2439#include "remoting/host/win/wts_session_process_delegate.h"
[email protected]3fd005e22013-02-28 20:11:2940#include "remoting/host/win/wts_terminal_monitor.h"
[email protected]5b731f3e2013-03-15 07:28:2241#include "remoting/host/win/wts_terminal_observer.h"
42#include "remoting/host/worker_process_ipc_delegate.h"
[email protected]60ccc242012-10-17 21:06:2443
[email protected]12066cb2012-10-25 03:25:4344using base::win::ScopedHandle;
45
[email protected]5b731f3e2013-03-15 07:28:2246namespace remoting {
47
[email protected]60ccc242012-10-17 21:06:2448namespace {
49
[email protected]60ccc242012-10-17 21:06:2450// The security descriptor of the daemon IPC endpoint. It gives full access
[email protected]6d65223d2013-03-05 20:32:4651// to SYSTEM and denies access by anyone else.
[email protected]5b731f3e2013-03-15 07:28:2252const wchar_t kDaemonIpcSecurityDescriptor[] =
53 SDDL_OWNER L":" SDDL_LOCAL_SYSTEM
54 SDDL_GROUP L":" SDDL_LOCAL_SYSTEM
55 SDDL_DACL L":("
56 SDDL_ACCESS_ALLOWED L";;" SDDL_GENERIC_ALL L";;;" SDDL_LOCAL_SYSTEM
57 L")";
[email protected]60ccc242012-10-17 21:06:2458
[email protected]9410c0a2013-02-23 06:07:2159// The command line parameters that should be copied from the service's command
60// line to the host process.
61const char* kCopiedSwitchNames[] = { switches::kV, switches::kVModule };
62
[email protected]3c6ae172013-03-18 08:50:5863// The default screen dimensions for an RDP session.
[email protected]792c4f42013-04-06 16:05:2164const int kDefaultRdpScreenWidth = 1280;
[email protected]3c6ae172013-03-18 08:50:5865const int kDefaultRdpScreenHeight = 768;
66
[email protected]5b731f3e2013-03-15 07:28:2267// RDC 6.1 (W2K8) supports dimensions of up to 4096x2048.
68const int kMaxRdpScreenWidth = 4096;
69const int kMaxRdpScreenHeight = 2048;
[email protected]60ccc242012-10-17 21:06:2470
[email protected]5b731f3e2013-03-15 07:28:2271// The minimum effective screen dimensions supported by Windows are 800x600.
72const int kMinRdpScreenWidth = 800;
73const int kMinRdpScreenHeight = 600;
[email protected]60ccc242012-10-17 21:06:2474
[email protected]739e2802013-03-18 01:03:4875// Default dots per inch used by RDP is 96 DPI.
76const int kDefaultRdpDpi = 96;
[email protected]5b731f3e2013-03-15 07:28:2277
78// The session attach notification should arrive within 30 seconds.
79const int kSessionAttachTimeoutSeconds = 30;
80
81// DesktopSession implementation which attaches to the host's physical console.
82// Receives IPC messages from the desktop process, running in the console
83// session, via |WorkerProcessIpcDelegate|, and monitors console session
84// attach/detach events via |WtsConsoleObserer|.
85class ConsoleSession : public DesktopSessionWin {
86 public:
87 // Same as DesktopSessionWin().
88 ConsoleSession(
89 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
[email protected]12066cb2012-10-25 03:25:4390 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
[email protected]60ccc242012-10-17 21:06:2491 DaemonProcess* daemon_process,
92 int id,
[email protected]5b731f3e2013-03-15 07:28:2293 WtsTerminalMonitor* monitor);
94 virtual ~ConsoleSession();
95
96 protected:
[email protected]6f526ce2013-03-18 04:38:5697 // DesktopSession overrides.
98 virtual void SetScreenResolution(const ScreenResolution& resolution) OVERRIDE;
99
[email protected]5b731f3e2013-03-15 07:28:22100 // DesktopSessionWin overrides.
101 virtual void InjectSas() OVERRIDE;
102
103 private:
104 scoped_ptr<SasInjector> sas_injector_;
105
106 DISALLOW_COPY_AND_ASSIGN(ConsoleSession);
107};
108
109// DesktopSession implementation which attaches to virtual RDP console.
110// Receives IPC messages from the desktop process, running in the console
111// session, via |WorkerProcessIpcDelegate|, and monitors console session
112// attach/detach events via |WtsConsoleObserer|.
113class RdpSession : public DesktopSessionWin {
114 public:
115 // Same as DesktopSessionWin().
116 RdpSession(
117 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
118 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
119 DaemonProcess* daemon_process,
120 int id,
121 WtsTerminalMonitor* monitor);
122 virtual ~RdpSession();
123
124 // Performs the part of initialization that can fail.
[email protected]739e2802013-03-18 01:03:48125 bool Initialize(const ScreenResolution& resolution);
[email protected]5b731f3e2013-03-15 07:28:22126
127 // Mirrors IRdpDesktopSessionEventHandler.
128 void OnRdpConnected(const net::IPEndPoint& client_endpoint);
129 void OnRdpClosed();
130
131 protected:
[email protected]6f526ce2013-03-18 04:38:56132 // DesktopSession overrides.
133 virtual void SetScreenResolution(const ScreenResolution& resolution) OVERRIDE;
134
[email protected]5b731f3e2013-03-15 07:28:22135 // DesktopSessionWin overrides.
136 virtual void InjectSas() OVERRIDE;
137
138 private:
139 // An implementation of IRdpDesktopSessionEventHandler interface that forwards
140 // notifications to the owning desktop session.
141 class EventHandler : public IRdpDesktopSessionEventHandler {
142 public:
143 explicit EventHandler(base::WeakPtr<RdpSession> desktop_session);
144 virtual ~EventHandler();
145
146 // IUnknown interface.
147 STDMETHOD_(ULONG, AddRef)() OVERRIDE;
148 STDMETHOD_(ULONG, Release)() OVERRIDE;
149 STDMETHOD(QueryInterface)(REFIID riid, void** ppv) OVERRIDE;
150
151 // IRdpDesktopSessionEventHandler interface.
152 STDMETHOD(OnRdpConnected)(byte* client_endpoint, long length) OVERRIDE;
153 STDMETHOD(OnRdpClosed)() OVERRIDE;
154
155 private:
156 ULONG ref_count_;
157
158 // Points to the desktop session object receiving OnRdpXxx() notifications.
159 base::WeakPtr<RdpSession> desktop_session_;
160
161 // This class must be used on a single thread.
162 base::ThreadChecker thread_checker_;
163
164 DISALLOW_COPY_AND_ASSIGN(EventHandler);
165 };
166
167 // Used to create an RDP desktop session.
168 base::win::ScopedComPtr<IRdpDesktopSession> rdp_desktop_session_;
169
170 base::WeakPtrFactory<RdpSession> weak_factory_;
171
172 DISALLOW_COPY_AND_ASSIGN(RdpSession);
173};
174
175ConsoleSession::ConsoleSession(
176 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
177 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
178 DaemonProcess* daemon_process,
179 int id,
180 WtsTerminalMonitor* monitor)
181 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id,
182 monitor) {
183 StartMonitoring(net::IPEndPoint());
184}
185
186ConsoleSession::~ConsoleSession() {
187}
188
[email protected]6f526ce2013-03-18 04:38:56189void ConsoleSession::SetScreenResolution(const ScreenResolution& resolution) {
190 // Do nothing. The screen resolution of the console session is controlled by
191 // the DesktopSessionAgent instance running in that session.
192 DCHECK(caller_task_runner()->BelongsToCurrentThread());
193}
194
[email protected]5b731f3e2013-03-15 07:28:22195void ConsoleSession::InjectSas() {
[email protected]dd81166082013-03-18 20:33:33196 DCHECK(caller_task_runner()->BelongsToCurrentThread());
197
[email protected]5b731f3e2013-03-15 07:28:22198 if (!sas_injector_)
199 sas_injector_ = SasInjector::Create();
200 if (!sas_injector_->InjectSas())
201 LOG(ERROR) << "Failed to inject Secure Attention Sequence.";
202}
203
204RdpSession::RdpSession(
205 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
206 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
207 DaemonProcess* daemon_process,
208 int id,
209 WtsTerminalMonitor* monitor)
210 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id,
211 monitor),
[email protected]aa46ba52013-04-27 00:00:44212 weak_factory_(this) {
[email protected]5b731f3e2013-03-15 07:28:22213}
214
215RdpSession::~RdpSession() {
216}
217
[email protected]739e2802013-03-18 01:03:48218bool RdpSession::Initialize(const ScreenResolution& resolution) {
[email protected]5b731f3e2013-03-15 07:28:22219 DCHECK(caller_task_runner()->BelongsToCurrentThread());
220
221 // Create the RDP wrapper object.
222 HRESULT result = rdp_desktop_session_.CreateInstance(
223 __uuidof(RdpDesktopSession));
224 if (FAILED(result)) {
225 LOG(ERROR) << "Failed to create RdpSession object, 0x"
226 << std::hex << result << std::dec << ".";
227 return false;
228 }
229
[email protected]3c6ae172013-03-18 08:50:58230 ScreenResolution local_resolution = resolution;
231
232 // If the screen resolution is not specified, use the default screen
233 // resolution.
234 if (local_resolution.IsEmpty()) {
[email protected]b9ed58f2013-05-16 10:45:24235 local_resolution = ScreenResolution(
236 webrtc::DesktopSize(kDefaultRdpScreenWidth, kDefaultRdpScreenHeight),
237 webrtc::DesktopVector(kDefaultRdpDpi, kDefaultRdpDpi));
[email protected]3c6ae172013-03-18 08:50:58238 }
239
[email protected]739e2802013-03-18 01:03:48240 // Get the screen dimensions assuming the default DPI.
[email protected]b9ed58f2013-05-16 10:45:24241 webrtc::DesktopSize host_size = local_resolution.ScaleDimensionsToDpi(
242 webrtc::DesktopVector(kDefaultRdpDpi, kDefaultRdpDpi));
[email protected]5b731f3e2013-03-15 07:28:22243
244 // Make sure that the host resolution is within the limits supported by RDP.
[email protected]b9ed58f2013-05-16 10:45:24245 host_size = webrtc::DesktopSize(
[email protected]5b731f3e2013-03-15 07:28:22246 std::min(kMaxRdpScreenWidth,
247 std::max(kMinRdpScreenWidth, host_size.width())),
248 std::min(kMaxRdpScreenHeight,
249 std::max(kMinRdpScreenHeight, host_size.height())));
250
251 // Create an RDP session.
252 base::win::ScopedComPtr<IRdpDesktopSessionEventHandler> event_handler(
253 new EventHandler(weak_factory_.GetWeakPtr()));
254 result = rdp_desktop_session_->Connect(host_size.width(),
255 host_size.height(),
256 event_handler);
257 if (FAILED(result)) {
258 LOG(ERROR) << "RdpSession::Create() failed, 0x"
259 << std::hex << result << std::dec << ".";
260 return false;
261 }
262
263 return true;
264}
265
266void RdpSession::OnRdpConnected(const net::IPEndPoint& client_endpoint) {
267 DCHECK(caller_task_runner()->BelongsToCurrentThread());
268
269 StopMonitoring();
270 StartMonitoring(client_endpoint);
271}
272
273void RdpSession::OnRdpClosed() {
274 DCHECK(caller_task_runner()->BelongsToCurrentThread());
275
276 OnPermanentError();
277}
278
[email protected]6f526ce2013-03-18 04:38:56279void RdpSession::SetScreenResolution(const ScreenResolution& resolution) {
280 DCHECK(caller_task_runner()->BelongsToCurrentThread());
281
282 // TODO(alexeypa): implement resize-to-client for RDP sessions here.
283 // See http://crbug.com/137696.
284 NOTIMPLEMENTED();
285}
286
[email protected]5b731f3e2013-03-15 07:28:22287void RdpSession::InjectSas() {
288 DCHECK(caller_task_runner()->BelongsToCurrentThread());
289
[email protected]97328ee2013-06-04 06:46:59290 rdp_desktop_session_->InjectSas();
[email protected]5b731f3e2013-03-15 07:28:22291}
292
293RdpSession::EventHandler::EventHandler(
294 base::WeakPtr<RdpSession> desktop_session)
295 : ref_count_(0),
296 desktop_session_(desktop_session) {
297}
298
299RdpSession::EventHandler::~EventHandler() {
300 DCHECK(thread_checker_.CalledOnValidThread());
301
[email protected]1bf06232013-06-07 13:50:24302 if (desktop_session_)
[email protected]5b731f3e2013-03-15 07:28:22303 desktop_session_->OnRdpClosed();
304}
305
306ULONG STDMETHODCALLTYPE RdpSession::EventHandler::AddRef() {
307 DCHECK(thread_checker_.CalledOnValidThread());
308
309 return ++ref_count_;
310}
311
312ULONG STDMETHODCALLTYPE RdpSession::EventHandler::Release() {
313 DCHECK(thread_checker_.CalledOnValidThread());
314
315 if (--ref_count_ == 0) {
316 delete this;
317 return 0;
318 }
319
320 return ref_count_;
321}
322
323STDMETHODIMP RdpSession::EventHandler::QueryInterface(REFIID riid, void** ppv) {
324 DCHECK(thread_checker_.CalledOnValidThread());
325
326 if (riid == IID_IUnknown ||
327 riid == IID_IRdpDesktopSessionEventHandler) {
328 *ppv = static_cast<IRdpDesktopSessionEventHandler*>(this);
329 AddRef();
330 return S_OK;
331 }
332
333 *ppv = NULL;
334 return E_NOINTERFACE;
335}
336
337STDMETHODIMP RdpSession::EventHandler::OnRdpConnected(
338 byte* client_endpoint,
339 long length) {
340 DCHECK(thread_checker_.CalledOnValidThread());
341
[email protected]1bf06232013-06-07 13:50:24342 if (!desktop_session_)
[email protected]5b731f3e2013-03-15 07:28:22343 return S_OK;
344
345 net::IPEndPoint endpoint;
346 if (!endpoint.FromSockAddr(reinterpret_cast<sockaddr*>(client_endpoint),
347 length)) {
348 LOG(ERROR) << "Failed to parse the endpoint passed to OnRdpConnected().";
349 OnRdpClosed();
350 return S_OK;
351 }
352
353 desktop_session_->OnRdpConnected(endpoint);
354 return S_OK;
355}
356
357STDMETHODIMP RdpSession::EventHandler::OnRdpClosed() {
358 DCHECK(thread_checker_.CalledOnValidThread());
359
[email protected]1bf06232013-06-07 13:50:24360 if (!desktop_session_)
[email protected]5b731f3e2013-03-15 07:28:22361 return S_OK;
362
363 base::WeakPtr<RdpSession> desktop_session = desktop_session_;
364 desktop_session_.reset();
365 desktop_session->OnRdpClosed();
366 return S_OK;
367}
368
369} // namespace
370
371// static
372scoped_ptr<DesktopSession> DesktopSessionWin::CreateForConsole(
373 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
374 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
375 DaemonProcess* daemon_process,
376 int id,
[email protected]739e2802013-03-18 01:03:48377 const ScreenResolution& resolution) {
[email protected]5b731f3e2013-03-15 07:28:22378 scoped_ptr<ConsoleSession> session(new ConsoleSession(
379 caller_task_runner, io_task_runner, daemon_process, id,
380 HostService::GetInstance()));
381
382 return session.PassAs<DesktopSession>();
383}
384
385// static
386scoped_ptr<DesktopSession> DesktopSessionWin::CreateForVirtualTerminal(
387 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
388 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
389 DaemonProcess* daemon_process,
390 int id,
[email protected]739e2802013-03-18 01:03:48391 const ScreenResolution& resolution) {
[email protected]5b731f3e2013-03-15 07:28:22392 scoped_ptr<RdpSession> session(new RdpSession(
393 caller_task_runner, io_task_runner, daemon_process, id,
394 HostService::GetInstance()));
[email protected]739e2802013-03-18 01:03:48395 if (!session->Initialize(resolution))
[email protected]5b731f3e2013-03-15 07:28:22396 return scoped_ptr<DesktopSession>();
397
398 return session.PassAs<DesktopSession>();
399}
400
401DesktopSessionWin::DesktopSessionWin(
402 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
403 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
404 DaemonProcess* daemon_process,
405 int id,
[email protected]3fd005e22013-02-28 20:11:29406 WtsTerminalMonitor* monitor)
[email protected]60ccc242012-10-17 21:06:24407 : DesktopSession(daemon_process, id),
[email protected]5b731f3e2013-03-15 07:28:22408 caller_task_runner_(caller_task_runner),
[email protected]60ccc242012-10-17 21:06:24409 io_task_runner_(io_task_runner),
[email protected]5b731f3e2013-03-15 07:28:22410 monitor_(monitor),
411 monitoring_notifications_(false) {
412 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]94618e72013-05-14 00:13:08413
414 ReportElapsedTime("created");
[email protected]60ccc242012-10-17 21:06:24415}
416
417DesktopSessionWin::~DesktopSessionWin() {
[email protected]5b731f3e2013-03-15 07:28:22418 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]60ccc242012-10-17 21:06:24419
[email protected]5b731f3e2013-03-15 07:28:22420 StopMonitoring();
421}
422
423void DesktopSessionWin::OnSessionAttachTimeout() {
424 DCHECK(caller_task_runner_->BelongsToCurrentThread());
425
426 LOG(ERROR) << "Session attach notification didn't arrived within "
427 << kSessionAttachTimeoutSeconds << " seconds.";
428 OnPermanentError();
429}
430
431void DesktopSessionWin::StartMonitoring(
432 const net::IPEndPoint& client_endpoint) {
433 DCHECK(caller_task_runner_->BelongsToCurrentThread());
434 DCHECK(!monitoring_notifications_);
435 DCHECK(!session_attach_timer_.IsRunning());
436
[email protected]94618e72013-05-14 00:13:08437 ReportElapsedTime("started monitoring");
438
[email protected]5b731f3e2013-03-15 07:28:22439 session_attach_timer_.Start(
440 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds),
441 this, &DesktopSessionWin::OnSessionAttachTimeout);
442
443 monitoring_notifications_ = true;
444 monitor_->AddWtsTerminalObserver(client_endpoint, this);
445}
446
447void DesktopSessionWin::StopMonitoring() {
448 DCHECK(caller_task_runner_->BelongsToCurrentThread());
449
450 if (monitoring_notifications_) {
[email protected]94618e72013-05-14 00:13:08451 ReportElapsedTime("stopped monitoring");
452
[email protected]5b731f3e2013-03-15 07:28:22453 monitoring_notifications_ = false;
454 monitor_->RemoveWtsTerminalObserver(this);
455 }
456
457 session_attach_timer_.Stop();
458 OnSessionDetached();
[email protected]60ccc242012-10-17 21:06:24459}
460
[email protected]b15c8702012-10-18 20:34:21461void DesktopSessionWin::OnChannelConnected(int32 peer_pid) {
[email protected]5b731f3e2013-03-15 07:28:22462 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]12066cb2012-10-25 03:25:43463
[email protected]94618e72013-05-14 00:13:08464 ReportElapsedTime("channel connected");
465
[email protected]12066cb2012-10-25 03:25:43466 // Obtain the handle of the desktop process. It will be passed to the network
[email protected]5b731f3e2013-03-15 07:28:22467 // process to use to duplicate handles of shared memory objects from
468 // the desktop process.
[email protected]12066cb2012-10-25 03:25:43469 desktop_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid));
470 if (!desktop_process_.IsValid()) {
[email protected]e9057a6f2013-03-08 22:37:55471 CrashDesktopProcess(FROM_HERE);
[email protected]12066cb2012-10-25 03:25:43472 return;
473 }
474
475 VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")";
[email protected]60ccc242012-10-17 21:06:24476}
477
478bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) {
[email protected]5b731f3e2013-03-15 07:28:22479 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]60ccc242012-10-17 21:06:24480
[email protected]12066cb2012-10-25 03:25:43481 bool handled = true;
482 IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message)
483 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
484 OnDesktopSessionAgentAttached)
[email protected]0dffd552012-12-07 01:08:09485 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas,
[email protected]5b731f3e2013-03-15 07:28:22486 InjectSas)
[email protected]12066cb2012-10-25 03:25:43487 IPC_MESSAGE_UNHANDLED(handled = false)
488 IPC_END_MESSAGE_MAP()
[email protected]f5f0f402013-03-05 22:46:38489
490 if (!handled) {
491 LOG(ERROR) << "Received unexpected IPC type: " << message.type();
[email protected]e9057a6f2013-03-08 22:37:55492 CrashDesktopProcess(FROM_HERE);
[email protected]f5f0f402013-03-05 22:46:38493 }
494
[email protected]12066cb2012-10-25 03:25:43495 return handled;
[email protected]60ccc242012-10-17 21:06:24496}
497
498void DesktopSessionWin::OnPermanentError() {
[email protected]5b731f3e2013-03-15 07:28:22499 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]60ccc242012-10-17 21:06:24500
[email protected]5b731f3e2013-03-15 07:28:22501 StopMonitoring();
[email protected]60ccc242012-10-17 21:06:24502
503 // This call will delete |this| so it should be at the very end of the method.
504 daemon_process()->CloseDesktopSession(id());
505}
506
507void DesktopSessionWin::OnSessionAttached(uint32 session_id) {
[email protected]5b731f3e2013-03-15 07:28:22508 DCHECK(caller_task_runner_->BelongsToCurrentThread());
509 DCHECK(!launcher_);
510 DCHECK(monitoring_notifications_);
[email protected]60ccc242012-10-17 21:06:24511
[email protected]94618e72013-05-14 00:13:08512 ReportElapsedTime("attached");
513
[email protected]85c7fda22013-05-18 01:35:47514 // Launch elevated on Win8 to be able to inject Alt+Tab.
515 bool launch_elevated = base::win::GetVersion() >= base::win::VERSION_WIN8;
516
517 // Get the name of the executable to run. |kDesktopBinaryName| specifies
518 // uiAccess="true" in it's manifest.
[email protected]9410c0a2013-02-23 06:07:21519 base::FilePath desktop_binary;
[email protected]85c7fda22013-05-18 01:35:47520 bool result;
521 if (launch_elevated) {
522 result = GetInstalledBinaryPath(kDesktopBinaryName, &desktop_binary);
523 } else {
524 result = GetInstalledBinaryPath(kHostBinaryName, &desktop_binary);
525 }
526
527 if (!result) {
[email protected]9410c0a2013-02-23 06:07:21528 OnPermanentError();
529 return;
[email protected]60ccc242012-10-17 21:06:24530 }
531
[email protected]5b731f3e2013-03-15 07:28:22532 session_attach_timer_.Stop();
533
[email protected]9410c0a2013-02-23 06:07:21534 scoped_ptr<CommandLine> target(new CommandLine(desktop_binary));
535 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeDesktop);
[email protected]5b731f3e2013-03-15 07:28:22536 // Copy the command line switches enabling verbose logging.
[email protected]9410c0a2013-02-23 06:07:21537 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
538 kCopiedSwitchNames,
539 arraysize(kCopiedSwitchNames));
540
[email protected]5b731f3e2013-03-15 07:28:22541 // Create a delegate capable of launching a process in a different session.
[email protected]60ccc242012-10-17 21:06:24542 scoped_ptr<WtsSessionProcessDelegate> delegate(
[email protected]85c7fda22013-05-18 01:35:47543 new WtsSessionProcessDelegate(io_task_runner_,
544 target.Pass(),
545 launch_elevated,
546 WideToUTF8(kDaemonIpcSecurityDescriptor)));
547 if (!delegate->Initialize(session_id)) {
548 OnPermanentError();
549 return;
550 }
[email protected]60ccc242012-10-17 21:06:24551
552 // Create a launcher for the desktop process, using the per-session delegate.
[email protected]85c7fda22013-05-18 01:35:47553 launcher_.reset(new WorkerProcessLauncher(delegate.Pass(), this));
[email protected]60ccc242012-10-17 21:06:24554}
555
556void DesktopSessionWin::OnSessionDetached() {
[email protected]5b731f3e2013-03-15 07:28:22557 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]60ccc242012-10-17 21:06:24558
559 launcher_.reset();
[email protected]5b731f3e2013-03-15 07:28:22560
561 if (monitoring_notifications_) {
[email protected]94618e72013-05-14 00:13:08562 ReportElapsedTime("detached");
563
[email protected]5b731f3e2013-03-15 07:28:22564 session_attach_timer_.Start(
565 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds),
566 this, &DesktopSessionWin::OnSessionAttachTimeout);
567 }
[email protected]60ccc242012-10-17 21:06:24568}
569
[email protected]12066cb2012-10-25 03:25:43570void DesktopSessionWin::OnDesktopSessionAgentAttached(
571 IPC::PlatformFileForTransit desktop_pipe) {
572 if (!daemon_process()->OnDesktopSessionAgentAttached(id(),
573 desktop_process_,
574 desktop_pipe)) {
[email protected]e9057a6f2013-03-08 22:37:55575 CrashDesktopProcess(FROM_HERE);
[email protected]12066cb2012-10-25 03:25:43576 }
577}
578
[email protected]e9057a6f2013-03-08 22:37:55579void DesktopSessionWin::CrashDesktopProcess(
[email protected]12066cb2012-10-25 03:25:43580 const tracked_objects::Location& location) {
[email protected]5b731f3e2013-03-15 07:28:22581 DCHECK(caller_task_runner_->BelongsToCurrentThread());
[email protected]12066cb2012-10-25 03:25:43582
[email protected]e9057a6f2013-03-08 22:37:55583 launcher_->Crash(location);
[email protected]12066cb2012-10-25 03:25:43584}
585
[email protected]94618e72013-05-14 00:13:08586void DesktopSessionWin::ReportElapsedTime(const std::string& event) {
587 base::Time now = base::Time::Now();
588
589 std::string passed;
590 if (!last_timestamp_.is_null()) {
591 passed = base::StringPrintf(", %.2fs passed",
592 (now - last_timestamp_).InSecondsF());
593 }
594
595 base::Time::Exploded exploded;
596 now.LocalExplode(&exploded);
597 VLOG(1) << base::StringPrintf("session(%d): %s at %02d:%02d:%02d.%03d%s",
598 id(),
599 event.c_str(),
600 exploded.hour,
601 exploded.minute,
602 exploded.second,
603 exploded.millisecond,
604 passed.c_str());
605
606 last_timestamp_ = now;
607}
608
[email protected]60ccc242012-10-17 21:06:24609} // namespace remoting