Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: remoting/host/desktop_session_win.cc

Issue 12544020: Remote RDP sessions, rather than the console, if curtain-mode is configured. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/desktop_session_win.h" 5 #include "remoting/host/desktop_session_win.h"
6 6
7 #include <limits>
8 #include <sddl.h>
9
7 #include "base/base_switches.h" 10 #include "base/base_switches.h"
8 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #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"
9 #include "base/path_service.h" 16 #include "base/path_service.h"
17 #include "base/threading/thread_checker.h"
18 #include "base/timer.h"
19 #include "base/utf_string_conversions.h"
20 #include "base/win/scoped_comptr.h"
21 #include "base/win/scoped_handle.h"
10 #include "ipc/ipc_message_macros.h" 22 #include "ipc/ipc_message_macros.h"
23 #include "ipc/ipc_platform_file.h"
11 #include "net/base/ip_endpoint.h" 24 #include "net/base/ip_endpoint.h"
12 #include "remoting/base/auto_thread_task_runner.h" 25 #include "remoting/base/auto_thread_task_runner.h"
26 // MIDL-generated declarations and definitions.
27 #include "remoting/host/chromoting_lib.h"
13 #include "remoting/host/chromoting_messages.h" 28 #include "remoting/host/chromoting_messages.h"
14 #include "remoting/host/daemon_process.h" 29 #include "remoting/host/daemon_process.h"
30 #include "remoting/host/desktop_session.h"
15 #include "remoting/host/host_main.h" 31 #include "remoting/host/host_main.h"
16 #include "remoting/host/ipc_constants.h" 32 #include "remoting/host/ipc_constants.h"
17 #include "remoting/host/sas_injector.h" 33 #include "remoting/host/sas_injector.h"
34 #include "remoting/host/win/host_service.h"
18 #include "remoting/host/win/worker_process_launcher.h" 35 #include "remoting/host/win/worker_process_launcher.h"
19 #include "remoting/host/win/wts_session_process_delegate.h" 36 #include "remoting/host/win/wts_session_process_delegate.h"
20 #include "remoting/host/win/wts_terminal_monitor.h" 37 #include "remoting/host/win/wts_terminal_monitor.h"
38 #include "remoting/host/win/wts_terminal_observer.h"
39 #include "remoting/host/worker_process_ipc_delegate.h"
21 40
22 using base::win::ScopedHandle; 41 using base::win::ScopedHandle;
23 42
43 namespace remoting {
44
24 namespace { 45 namespace {
25 46
26 // The security descriptor of the daemon IPC endpoint. It gives full access 47 // The security descriptor of the daemon IPC endpoint. It gives full access
27 // to SYSTEM and denies access by anyone else. 48 // to SYSTEM and denies access by anyone else.
28 const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)"; 49 const wchar_t kDaemonIpcSecurityDescriptor[] =
50 SDDL_OWNER L":" SDDL_LOCAL_SYSTEM
51 SDDL_GROUP L":" SDDL_LOCAL_SYSTEM
52 SDDL_DACL L":("
53 SDDL_ACCESS_ALLOWED L";;" SDDL_GENERIC_ALL L";;;" SDDL_LOCAL_SYSTEM
54 L")";
29 55
30 // The command line parameters that should be copied from the service's command 56 // The command line parameters that should be copied from the service's command
31 // line to the host process. 57 // line to the host process.
32 const char* kCopiedSwitchNames[] = { switches::kV, switches::kVModule }; 58 const char* kCopiedSwitchNames[] = { switches::kV, switches::kVModule };
33 59
34 } // namespace 60 // RDC 6.1 (W2K8) supports resolution up to 4096x2048.
Wez 2013/03/12 01:21:11 nit: resolution -> dimensions of
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
35 61 const int kMaxRdpScreenWidth = 4096;
36 namespace remoting { 62 const int kMaxRdpScreenHeight = 2048;
63 const int kMinRdpScreenWidth = 800;
64 const int kMinRdpScreenHeight = 600;
Wez 2013/03/12 01:21:11 nit: Comment on why we have a minimum.
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
65
66 const int kDefaultDpiX = 96;
67 const int kDefaultDpiY = 96;
Wez 2013/03/12 01:21:11 nit: Comment on what these are used for.
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
68
69 // The session attach notification should arrive within 30 seconds.
70 const int kSessionAttachTimeoutSeconds = 30;
71
72 // Implements functionality shared by ConsoleSession and RdpSession classes.
73 class DesktopSessionWin
74 : public DesktopSession,
75 public WorkerProcessIpcDelegate,
76 public WtsTerminalObserver {
77 public:
78 // Passes the owning |daemon_process|, a unique identifier of the desktop
79 // session |id| and the interface for monitoring console session attach/detach
Wez 2013/03/12 01:21:11 nit: console session -> session
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
80 // events. Both |daemon_process| and |monitor| must outlive |this|.
81 DesktopSessionWin(
82 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
83 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
84 DaemonProcess* daemon_process,
85 int id,
Wez 2013/03/12 01:21:11 nit: |session_id|? or |desktop_session_id|?
alexeypa (please no reviews) 2013/03/12 20:21:15 I prefer |id| without any prefix because this is t
86 WtsTerminalMonitor* monitor);
87 virtual ~DesktopSessionWin();
88
89 // WorkerProcessIpcDelegate implementation.
90 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
91 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
92 virtual void OnPermanentError() OVERRIDE;
Wez 2013/03/12 01:21:11 nit: Both of these interfaces can move to private,
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
93
94 // WtsTerminalObserver implementation.
95 virtual void OnSessionAttached(uint32 session_id) OVERRIDE;
96 virtual void OnSessionDetached() OVERRIDE;
97
98 protected:
99 const scoped_refptr<AutoThreadTaskRunner>& caller_task_runner() const {
100 return caller_task_runner_;
101 }
102
103 // Called when |session_attach_timer_| expires.
104 void OnSessionAttachTimeout();
105
106 // Start monitoring session attach/detach notification for the given endpoint.
Wez 2013/03/12 01:21:11 nit: Start -> Starts e.g. Starts monitoring for s
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
107 void StartMonitoring(const net::IPEndPoint& client_endpoint);
108
109 // Stop monitoring session attach/detach notifications.
110 void StopMonitoring();
111
112 // ChromotingDesktopDaemonMsg_InjectSas handler.
Wez 2013/03/12 01:21:11 nit: OnInjectSas() -> InjectSas() w/ comment "Inje
alexeypa (please no reviews) 2013/03/12 20:21:15 Done.
113 virtual void OnInjectSas() = 0;
114
115 private:
116 // ChromotingDesktopDaemonMsg_DesktopAttached handler.
117 void OnDesktopSessionAgentAttached(IPC::PlatformFileForTransit desktop_pipe);
118
119 // Restarts the desktop process.
120 void RestartDesktopProcess(const tracked_objects::Location& location);
121
122 // Task runner on which public methods of this class should be called.
123 scoped_refptr<AutoThreadTaskRunner> caller_task_runner_;
124
125 // Message loop used by the IPC channel.
Wez 2013/03/12 01:21:11 nit: Does the IPC channel use it, or do we use it
alexeypa (please no reviews) 2013/03/12 20:21:15 It is used by the IPC channel.
126 scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
127
128 // Handle of the desktop process.
Wez 2013/03/12 01:21:11 nit: Is the desktop process the DesktopSessionAgen
alexeypa (please no reviews) 2013/03/12 20:21:15 The desktop process is the process running in the
Wez 2013/03/13 22:30:27 What I'm really looking for is clarity as to what
129 base::win::ScopedHandle desktop_process_;
130
131 // Launches and monitors the desktop process.
132 scoped_ptr<WorkerProcessLauncher> launcher_;
133
134 // Pointer used to unsubscribe from session attach and detach events.
135 WtsTerminalMonitor* monitor_;
136
137 // True if |this| is subsribed to receive session attach/detach notifications.
138 bool monitoring_notifications_;
139
140 // Used to report an error if the session attach notification does not arrives
141 // for too long.
142 base::OneShotTimer<DesktopSessionWin> session_attach_timer_;
143
144 DISALLOW_COPY_AND_ASSIGN(DesktopSessionWin);
145 };
146
147 // DesktopSession implementation which attaches to the host's physical console.
148 // Receives IPC messages from the desktop process, running in the console
149 // session, via |WorkerProcessIpcDelegate|, and monitors console session
150 // attach/detach events via |WtsConsoleObserer|.
151 class ConsoleSession : public DesktopSessionWin {
152 public:
153 // Passes the owning |daemon_process|, a unique identifier of the desktop
154 // session |id| and the interface for monitoring console session attach/detach
155 // events. Both |daemon_process| and |monitor| must outlive |this|.
156 ConsoleSession(
157 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
158 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
159 DaemonProcess* daemon_process,
160 int id,
161 WtsTerminalMonitor* monitor);
162 virtual ~ConsoleSession();
163
164 protected:
165 // DesktopSessionWin overrides.
166 virtual void OnInjectSas() OVERRIDE;
167
168 private:
169 scoped_ptr<SasInjector> sas_injector_;
170
171 DISALLOW_COPY_AND_ASSIGN(ConsoleSession);
172 };
173
174 // DesktopSession implementation which attaches to virtual RDP console.
175 // Receives IPC messages from the desktop process, running in the console
176 // session, via |WorkerProcessIpcDelegate|, and monitors console session
177 // attach/detach events via |WtsConsoleObserer|.
178 class RdpSession : public DesktopSessionWin {
179 public:
180 // Passes the owning |daemon_process|, a unique identifier of the desktop
181 // session |id| and the interface for monitoring console session attach/detach
182 // events. Both |daemon_process| and |monitor| must outlive |this|.
183 RdpSession(
184 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
185 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
186 DaemonProcess* daemon_process,
187 int id,
188 WtsTerminalMonitor* monitor);
189 virtual ~RdpSession();
190
191 // Performs the part of initialization that can fail.
192 bool Initialize(const DesktopSessionParams& params);
193
194 // Mirrors IRdpDesktopSessionEventHandler.
195 void OnRdpConnected(const net::IPEndPoint& client_endpoint);
196 void OnRdpClosed();
197
198 protected:
199 // DesktopSessionWin overrides.
200 virtual void OnInjectSas() OVERRIDE;
201
202 private:
203 // An implementation of IRdpDesktopSessionEventHandler interface that forwards
204 // notifications to the owning desktop session.
205 class EventHandler : public IRdpDesktopSessionEventHandler {
206 public:
207 explicit EventHandler(base::WeakPtr<RdpSession> desktop_session);
208 virtual ~EventHandler();
209
210 // IUnknown interface.
211 STDMETHOD_(ULONG, AddRef)() OVERRIDE;
212 STDMETHOD_(ULONG, Release)() OVERRIDE;
213 STDMETHOD(QueryInterface)(REFIID riid, void** ppv) OVERRIDE;
214
215 // IRdpDesktopSessionEventHandler interface.
216 STDMETHOD(OnRdpConnected)(byte* client_endpoint, long length) OVERRIDE;
217 STDMETHOD(OnRdpClosed)() OVERRIDE;
218
219 private:
220 ULONG ref_count_;
221
222 // Points to the desktop session object receiving OnRdpXxx() notifications.
223 base::WeakPtr<RdpSession> desktop_session_;
224
225 // This class must be used on a single thread.
226 base::ThreadChecker thread_checker_;
227
228 DISALLOW_COPY_AND_ASSIGN(EventHandler);
229 };
230
231 // Used to create an RDP desktop session.
232 base::win::ScopedComPtr<IRdpDesktopSession> rdp_desktop_session_;
233
234 base::WeakPtrFactory<RdpSession> weak_factory_;
235
236 DISALLOW_COPY_AND_ASSIGN(RdpSession);
237 };
37 238
38 DesktopSessionWin::DesktopSessionWin( 239 DesktopSessionWin::DesktopSessionWin(
39 scoped_refptr<AutoThreadTaskRunner> main_task_runner, 240 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
40 scoped_refptr<AutoThreadTaskRunner> io_task_runner, 241 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
41 DaemonProcess* daemon_process, 242 DaemonProcess* daemon_process,
42 int id, 243 int id,
43 const DesktopSessionParams& params,
44 bool virtual_terminal,
45 WtsTerminalMonitor* monitor) 244 WtsTerminalMonitor* monitor)
46 : DesktopSession(daemon_process, id), 245 : DesktopSession(daemon_process, id),
47 main_task_runner_(main_task_runner), 246 caller_task_runner_(caller_task_runner),
48 io_task_runner_(io_task_runner), 247 io_task_runner_(io_task_runner),
49 monitor_(monitor) { 248 monitor_(monitor),
50 DCHECK(main_task_runner_->BelongsToCurrentThread()); 249 monitoring_notifications_(false) {
51 250 DCHECK(caller_task_runner_->BelongsToCurrentThread());
52 monitor_->AddWtsTerminalObserver(net::IPEndPoint(), this);
53 } 251 }
54 252
55 DesktopSessionWin::~DesktopSessionWin() { 253 DesktopSessionWin::~DesktopSessionWin() {
56 DCHECK(main_task_runner_->BelongsToCurrentThread()); 254 DCHECK(caller_task_runner_->BelongsToCurrentThread());
57 255
58 launcher_.reset(); 256 StopMonitoring();
59 monitor_->RemoveWtsTerminalObserver(this);
60 } 257 }
61 258
62 void DesktopSessionWin::OnChannelConnected(int32 peer_pid) { 259 void DesktopSessionWin::OnChannelConnected(int32 peer_pid) {
63 DCHECK(main_task_runner_->BelongsToCurrentThread()); 260 DCHECK(caller_task_runner_->BelongsToCurrentThread());
64 261
65 // Obtain the handle of the desktop process. It will be passed to the network 262 // Obtain the handle of the desktop process. It will be passed to the network
66 // process so it would be able to duplicate handles of shared memory objects 263 // process so it would be able to duplicate handles of shared memory objects
67 // from the desktop process. 264 // from the desktop process.
68 desktop_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid)); 265 desktop_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid));
69 if (!desktop_process_.IsValid()) { 266 if (!desktop_process_.IsValid()) {
70 RestartDesktopProcess(FROM_HERE); 267 RestartDesktopProcess(FROM_HERE);
71 return; 268 return;
72 } 269 }
73 270
74 VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")"; 271 VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")";
75 } 272 }
76 273
77 bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) { 274 bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) {
78 DCHECK(main_task_runner_->BelongsToCurrentThread()); 275 DCHECK(caller_task_runner_->BelongsToCurrentThread());
79 276
80 bool handled = true; 277 bool handled = true;
81 IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message) 278 IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message)
82 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, 279 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
83 OnDesktopSessionAgentAttached) 280 OnDesktopSessionAgentAttached)
84 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas, 281 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas,
85 OnInjectSas) 282 OnInjectSas)
86 IPC_MESSAGE_UNHANDLED(handled = false) 283 IPC_MESSAGE_UNHANDLED(handled = false)
87 IPC_END_MESSAGE_MAP() 284 IPC_END_MESSAGE_MAP()
88 285
89 if (!handled) { 286 if (!handled) {
90 LOG(ERROR) << "Received unexpected IPC type: " << message.type(); 287 LOG(ERROR) << "Received unexpected IPC type: " << message.type();
91 RestartDesktopProcess(FROM_HERE); 288 RestartDesktopProcess(FROM_HERE);
92 } 289 }
93 290
94 return handled; 291 return handled;
95 } 292 }
96 293
97 void DesktopSessionWin::OnPermanentError() { 294 void DesktopSessionWin::OnPermanentError() {
98 DCHECK(main_task_runner_->BelongsToCurrentThread()); 295 DCHECK(caller_task_runner_->BelongsToCurrentThread());
99 296
100 launcher_.reset(); 297 StopMonitoring();
101 298
102 // This call will delete |this| so it should be at the very end of the method. 299 // This call will delete |this| so it should be at the very end of the method.
103 daemon_process()->CloseDesktopSession(id()); 300 daemon_process()->CloseDesktopSession(id());
104 } 301 }
105 302
106 void DesktopSessionWin::OnSessionAttached(uint32 session_id) { 303 void DesktopSessionWin::OnSessionAttached(uint32 session_id) {
107 DCHECK(main_task_runner_->BelongsToCurrentThread()); 304 DCHECK(caller_task_runner_->BelongsToCurrentThread());
108 DCHECK(launcher_.get() == NULL); 305 DCHECK(!launcher_);
306 DCHECK(monitoring_notifications_);
109 307
110 // Get the desktop binary name. 308 // Get the desktop binary name.
111 base::FilePath desktop_binary; 309 base::FilePath desktop_binary;
112 if (!GetInstalledBinaryPath(kDesktopBinaryName, &desktop_binary)) { 310 if (!GetInstalledBinaryPath(kDesktopBinaryName, &desktop_binary)) {
113 OnPermanentError(); 311 OnPermanentError();
114 return; 312 return;
115 } 313 }
116 314
315 session_attach_timer_.Stop();
316
117 scoped_ptr<CommandLine> target(new CommandLine(desktop_binary)); 317 scoped_ptr<CommandLine> target(new CommandLine(desktop_binary));
118 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeDesktop); 318 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeDesktop);
119 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 319 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
120 kCopiedSwitchNames, 320 kCopiedSwitchNames,
121 arraysize(kCopiedSwitchNames)); 321 arraysize(kCopiedSwitchNames));
122 322
123 // Create a delegate to launch a process into the session. 323 // Create a delegate to launch a process into the session.
124 scoped_ptr<WtsSessionProcessDelegate> delegate( 324 scoped_ptr<WtsSessionProcessDelegate> delegate(
125 new WtsSessionProcessDelegate(main_task_runner_, io_task_runner_, 325 new WtsSessionProcessDelegate(
126 target.Pass(), session_id, 326 caller_task_runner_, io_task_runner_, target.Pass(), session_id, true,
127 true, kDaemonIpcSecurityDescriptor)); 327 WideToUTF8(kDaemonIpcSecurityDescriptor)));
128 328
129 // Create a launcher for the desktop process, using the per-session delegate. 329 // Create a launcher for the desktop process, using the per-session delegate.
130 launcher_.reset(new WorkerProcessLauncher( 330 launcher_.reset(new WorkerProcessLauncher(
131 main_task_runner_, delegate.Pass(), this)); 331 caller_task_runner_, delegate.Pass(), this));
132 } 332 }
133 333
134 void DesktopSessionWin::OnSessionDetached() { 334 void DesktopSessionWin::OnSessionDetached() {
135 DCHECK(main_task_runner_->BelongsToCurrentThread()); 335 DCHECK(caller_task_runner_->BelongsToCurrentThread());
136 DCHECK(launcher_.get() != NULL);
137 336
138 launcher_.reset(); 337 launcher_.reset();
338
339 if (monitoring_notifications_) {
340 session_attach_timer_.Start(
341 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds),
342 this, &DesktopSessionWin::OnSessionAttachTimeout);
343 }
344 }
345
346 void DesktopSessionWin::OnSessionAttachTimeout() {
347 DCHECK(caller_task_runner_->BelongsToCurrentThread());
348
349 LOG(ERROR) << "Session attach notification hasn't arrived within "
350 << kSessionAttachTimeoutSeconds << " seconds.";
351 OnPermanentError();
352 }
353
354 void DesktopSessionWin::StartMonitoring(
355 const net::IPEndPoint& client_endpoint) {
356 DCHECK(caller_task_runner_->BelongsToCurrentThread());
357 DCHECK(!monitoring_notifications_);
358 DCHECK(!session_attach_timer_.IsRunning());
359
360 session_attach_timer_.Start(
361 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds),
362 this, &DesktopSessionWin::OnSessionAttachTimeout);
363
364 monitoring_notifications_ = true;
365 monitor_->AddWtsTerminalObserver(client_endpoint, this);
366 }
367
368 void DesktopSessionWin::StopMonitoring() {
369 DCHECK(caller_task_runner_->BelongsToCurrentThread());
370
371 if (monitoring_notifications_) {
372 monitoring_notifications_ = false;
373 monitor_->RemoveWtsTerminalObserver(this);
374 }
375
376 session_attach_timer_.Stop();
377 OnSessionDetached();
139 } 378 }
140 379
141 void DesktopSessionWin::OnDesktopSessionAgentAttached( 380 void DesktopSessionWin::OnDesktopSessionAgentAttached(
142 IPC::PlatformFileForTransit desktop_pipe) { 381 IPC::PlatformFileForTransit desktop_pipe) {
143 if (!daemon_process()->OnDesktopSessionAgentAttached(id(), 382 if (!daemon_process()->OnDesktopSessionAgentAttached(id(),
144 desktop_process_, 383 desktop_process_,
145 desktop_pipe)) { 384 desktop_pipe)) {
146 RestartDesktopProcess(FROM_HERE); 385 RestartDesktopProcess(FROM_HERE);
147 } 386 }
148 } 387 }
149 388
150 void DesktopSessionWin::OnInjectSas() { 389 void DesktopSessionWin::RestartDesktopProcess(
151 DCHECK(main_task_runner_->BelongsToCurrentThread()); 390 const tracked_objects::Location& location) {
152 391 DCHECK(caller_task_runner_->BelongsToCurrentThread());
153 // Do not try to inject SAS if the desktop process is not running. This can 392
154 // happen when the session has detached from the console for instance. 393 launcher_->Send(new ChromotingDaemonDesktopMsg_Crash(
155 if (!launcher_) 394 location.function_name(), location.file_name(), location.line_number()));
156 return; 395 }
157 396
397 ConsoleSession::ConsoleSession(
398 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
399 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
400 DaemonProcess* daemon_process,
401 int id,
402 WtsTerminalMonitor* monitor)
403 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id,
404 monitor) {
405 StartMonitoring(net::IPEndPoint());
406 }
407
408 ConsoleSession::~ConsoleSession() {
409 }
410
411 void ConsoleSession::OnInjectSas() {
158 if (!sas_injector_) 412 if (!sas_injector_)
159 sas_injector_ = SasInjector::Create(); 413 sas_injector_ = SasInjector::Create();
160 if (!sas_injector_->InjectSas()) 414 if (!sas_injector_->InjectSas())
161 LOG(ERROR) << "Failed to inject Secure Attention Sequence."; 415 LOG(ERROR) << "Failed to inject Secure Attention Sequence.";
162 } 416 }
163 417
164 void DesktopSessionWin::RestartDesktopProcess( 418 RdpSession::RdpSession(
165 const tracked_objects::Location& location) { 419 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
166 DCHECK(main_task_runner_->BelongsToCurrentThread()); 420 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
167 421 DaemonProcess* daemon_process,
168 launcher_->Send(new ChromotingDaemonDesktopMsg_Crash( 422 int id,
169 location.function_name(), location.file_name(), location.line_number())); 423 WtsTerminalMonitor* monitor)
424 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id,
425 monitor),
426 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
427 }
428
429 RdpSession::~RdpSession() {
430 }
431
432 bool RdpSession::Initialize(const DesktopSessionParams& params) {
433 DCHECK(caller_task_runner()->BelongsToCurrentThread());
434
435 // Create the RDP wrapper object.
436 HRESULT result = rdp_desktop_session_.CreateInstance(
437 __uuidof(RdpDesktopSession));
438 if (FAILED(result)) {
439 LOG(ERROR) << "Failed to create RdpSession object, 0x"
440 << std::hex << result << std::dec << ".";
441 return false;
442 }
443
444 // DaemonProcess::CreateDesktopSession() varifies that |client_dpi_| and
445 // |client_size_| are positive.
446 DCHECK(params.client_dpi_.x() >= 0 && params.client_dpi_.y() >= 0);
447 DCHECK(params.client_size_.width() >= 0 && params.client_size_.height() >= 0);
448
449 // Handle the default DPI.
450 SkIPoint client_dpi = params.client_dpi_;
451 if (!client_dpi.x())
452 client_dpi.setX(kDefaultDpiX);
453 if (!client_dpi.y())
454 client_dpi.setY(kDefaultDpiY);
455
456 // Make sure there will be no integer overflow while scaling the client
457 // resolution.
458 SkISize client_size = SkISize::Make(
459 std::min(params.client_size_.width(),
460 std::numeric_limits<int32_t>::max() / kDefaultDpiX),
461 std::min(params.client_size_.height(),
462 std::numeric_limits<int32_t>::max() / kDefaultDpiY));
463
464 // Scale the client resolution assiming RDP gives us the default 96 DPI.
465 SkISize host_size = SkISize::Make(
466 client_size.width() * kDefaultDpiX / client_dpi.x(),
467 client_size.height() * kDefaultDpiY / client_dpi.y());
468
469 // Make sure that the host resolution is within the limits supported by RDP.
470 host_size = SkISize::Make(
471 std::min(kMaxRdpScreenWidth,
472 std::max(kMinRdpScreenWidth, host_size.width())),
473 std::min(kMaxRdpScreenHeight,
474 std::max(kMinRdpScreenHeight, host_size.height())));
475
476 // Create an RDP session.
477 base::win::ScopedComPtr<IRdpDesktopSessionEventHandler> event_handler(
478 new EventHandler(weak_factory_.GetWeakPtr()));
479 result = rdp_desktop_session_->Connect(host_size.width(),
480 host_size.height(),
481 event_handler);
482 if (FAILED(result)) {
483 LOG(ERROR) << "RdpSession::Create() failed, 0x"
484 << std::hex << result << std::dec << ".";
485 return false;
486 }
487
488 return true;
489 }
490
491 void RdpSession::OnRdpConnected(const net::IPEndPoint& client_endpoint) {
492 DCHECK(caller_task_runner()->BelongsToCurrentThread());
493
494 StopMonitoring();
495 StartMonitoring(client_endpoint);
496 }
497
498 void RdpSession::OnRdpClosed() {
499 DCHECK(caller_task_runner()->BelongsToCurrentThread());
500
501 OnPermanentError();
502 }
503
504 void RdpSession::OnInjectSas() {
505 DCHECK(caller_task_runner()->BelongsToCurrentThread());
506
507 NOTIMPLEMENTED();
508 }
509
510 RdpSession::EventHandler::EventHandler(
511 base::WeakPtr<RdpSession> desktop_session)
512 : ref_count_(0),
513 desktop_session_(desktop_session) {
514 }
515
516 RdpSession::EventHandler::~EventHandler() {
517 DCHECK(thread_checker_.CalledOnValidThread());
518
519 if (desktop_session_)
520 desktop_session_->OnRdpClosed();
521 }
522
523 ULONG STDMETHODCALLTYPE RdpSession::EventHandler::AddRef() {
524 DCHECK(thread_checker_.CalledOnValidThread());
525
526 return ++ref_count_;
527 }
528
529 ULONG STDMETHODCALLTYPE RdpSession::EventHandler::Release() {
530 DCHECK(thread_checker_.CalledOnValidThread());
531
532 if (--ref_count_ == 0) {
533 delete this;
534 return 0;
535 }
536
537 return ref_count_;
538 }
539
540 STDMETHODIMP RdpSession::EventHandler::QueryInterface(REFIID riid, void** ppv) {
541 DCHECK(thread_checker_.CalledOnValidThread());
542
543 if (riid == IID_IUnknown ||
544 riid == IID_IRdpDesktopSessionEventHandler) {
545 *ppv = static_cast<IRdpDesktopSessionEventHandler*>(this);
546 AddRef();
547 return S_OK;
548 }
549
550 *ppv = NULL;
551 return E_NOINTERFACE;
552 }
553
554 STDMETHODIMP RdpSession::EventHandler::OnRdpConnected(
555 byte* client_endpoint,
556 long length) {
557 DCHECK(thread_checker_.CalledOnValidThread());
558
559 if (!desktop_session_)
560 return S_OK;
561
562 net::IPEndPoint endpoint;
563 if (!endpoint.FromSockAddr(reinterpret_cast<sockaddr*>(client_endpoint),
564 length)) {
565 LOG(ERROR) << "Failed to parse the endpoint passed to OnRdpConnected().";
566 OnRdpClosed();
567 return S_OK;
568 }
569
570 desktop_session_->OnRdpConnected(endpoint);
571 return S_OK;
572 }
573
574 STDMETHODIMP RdpSession::EventHandler::OnRdpClosed() {
575 DCHECK(thread_checker_.CalledOnValidThread());
576
577 if (!desktop_session_)
578 return S_OK;
579
580 base::WeakPtr<RdpSession> desktop_session = desktop_session_;
581 desktop_session_.reset();
582 desktop_session->OnRdpClosed();
583 return S_OK;
584 }
585
586 } // namespace
587
588 scoped_ptr<DesktopSession> CreateDesktopSessionWin(
589 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
590 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
591 DaemonProcess* daemon_process,
592 int id,
593 const DesktopSessionParams& params,
594 bool virtual_terminal) {
595 if (virtual_terminal) {
596 scoped_ptr<RdpSession> session(new RdpSession(
597 caller_task_runner, io_task_runner, daemon_process, id,
598 HostService::GetInstance()));
599
600 if (!session->Initialize(params))
601 return scoped_ptr<DesktopSession>();
602
603 return session.PassAs<DesktopSession>();
604 } else {
605 scoped_ptr<ConsoleSession> session(new ConsoleSession(
606 caller_task_runner, io_task_runner, daemon_process, id,
607 HostService::GetInstance()));
608
609 return session.PassAs<DesktopSession>();
610 }
170 } 611 }
171 612
172 } // namespace remoting 613 } // namespace remoting
OLDNEW
« remoting/host/desktop_session_win.h ('K') | « remoting/host/desktop_session_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698