OLD | NEW |
---|---|
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 |
60 // RDC 6.1 (W2K8) supports dimensions of up to 4096x2048. | |
61 const int kMaxRdpScreenWidth = 4096; | |
62 const int kMaxRdpScreenHeight = 2048; | |
63 | |
64 // The minimum effective screen resolution supported by Windows is 800x600. | |
Wez
2013/03/13 22:30:27
nit: resolution -> dimensions
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
BTW, that was a quote directly from an MSDN
Wez
2013/03/13 22:56:39
Understood. Elsewhere resolution gets used interc
| |
65 const int kMinRdpScreenWidth = 800; | |
66 const int kMinRdpScreenHeight = 600; | |
67 | |
68 // Default dots per inch setting is 96 DPI. | |
Wez
2013/03/13 22:30:27
nit: No need for "setting" here.
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
69 const int kDefaultDpiX = 96; | |
70 const int kDefaultDpiY = 96; | |
71 | |
72 // The session attach notification should arrive within 30 seconds. | |
73 const int kSessionAttachTimeoutSeconds = 30; | |
74 | |
75 // DesktopSession implementation which attaches to the host's physical console. | |
76 // Receives IPC messages from the desktop process, running in the console | |
77 // session, via |WorkerProcessIpcDelegate|, and monitors console session | |
78 // attach/detach events via |WtsConsoleObserer|. | |
79 class ConsoleSession : public DesktopSessionWin { | |
80 public: | |
81 // Same as DesktopSessionWin(). | |
82 ConsoleSession( | |
83 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
84 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
85 DaemonProcess* daemon_process, | |
86 int id, | |
87 WtsTerminalMonitor* monitor); | |
88 virtual ~ConsoleSession(); | |
89 | |
90 protected: | |
91 // DesktopSessionWin overrides. | |
92 virtual void InjectSas() OVERRIDE; | |
93 | |
94 private: | |
95 scoped_ptr<SasInjector> sas_injector_; | |
96 | |
97 DISALLOW_COPY_AND_ASSIGN(ConsoleSession); | |
98 }; | |
99 | |
100 // DesktopSession implementation which attaches to virtual RDP console. | |
101 // Receives IPC messages from the desktop process, running in the console | |
102 // session, via |WorkerProcessIpcDelegate|, and monitors console session | |
103 // attach/detach events via |WtsConsoleObserer|. | |
104 class RdpSession : public DesktopSessionWin { | |
105 public: | |
106 // Same as DesktopSessionWin(). | |
107 RdpSession( | |
108 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
109 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
110 DaemonProcess* daemon_process, | |
111 int id, | |
112 WtsTerminalMonitor* monitor); | |
113 virtual ~RdpSession(); | |
114 | |
115 // Performs the part of initialization that can fail. | |
116 bool Initialize(const DesktopSessionParams& params); | |
117 | |
118 // Mirrors IRdpDesktopSessionEventHandler. | |
119 void OnRdpConnected(const net::IPEndPoint& client_endpoint); | |
120 void OnRdpClosed(); | |
121 | |
122 protected: | |
123 // DesktopSessionWin overrides. | |
124 virtual void InjectSas() OVERRIDE; | |
125 | |
126 private: | |
127 // An implementation of IRdpDesktopSessionEventHandler interface that forwards | |
128 // notifications to the owning desktop session. | |
129 class EventHandler : public IRdpDesktopSessionEventHandler { | |
130 public: | |
131 explicit EventHandler(base::WeakPtr<RdpSession> desktop_session); | |
132 virtual ~EventHandler(); | |
133 | |
134 // IUnknown interface. | |
135 STDMETHOD_(ULONG, AddRef)() OVERRIDE; | |
136 STDMETHOD_(ULONG, Release)() OVERRIDE; | |
137 STDMETHOD(QueryInterface)(REFIID riid, void** ppv) OVERRIDE; | |
138 | |
139 // IRdpDesktopSessionEventHandler interface. | |
140 STDMETHOD(OnRdpConnected)(byte* client_endpoint, long length) OVERRIDE; | |
141 STDMETHOD(OnRdpClosed)() OVERRIDE; | |
142 | |
143 private: | |
144 ULONG ref_count_; | |
145 | |
146 // Points to the desktop session object receiving OnRdpXxx() notifications. | |
147 base::WeakPtr<RdpSession> desktop_session_; | |
148 | |
149 // This class must be used on a single thread. | |
150 base::ThreadChecker thread_checker_; | |
151 | |
152 DISALLOW_COPY_AND_ASSIGN(EventHandler); | |
153 }; | |
154 | |
155 // Used to create an RDP desktop session. | |
156 base::win::ScopedComPtr<IRdpDesktopSession> rdp_desktop_session_; | |
157 | |
158 base::WeakPtrFactory<RdpSession> weak_factory_; | |
159 | |
160 DISALLOW_COPY_AND_ASSIGN(RdpSession); | |
161 }; | |
162 | |
163 ConsoleSession::ConsoleSession( | |
164 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
165 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
166 DaemonProcess* daemon_process, | |
167 int id, | |
168 WtsTerminalMonitor* monitor) | |
169 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id, | |
170 monitor) { | |
171 StartMonitoring(net::IPEndPoint()); | |
172 } | |
173 | |
174 ConsoleSession::~ConsoleSession() { | |
175 } | |
176 | |
177 void ConsoleSession::InjectSas() { | |
178 if (!sas_injector_) | |
179 sas_injector_ = SasInjector::Create(); | |
180 if (!sas_injector_->InjectSas()) | |
181 LOG(ERROR) << "Failed to inject Secure Attention Sequence."; | |
182 } | |
183 | |
184 RdpSession::RdpSession( | |
185 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
186 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
187 DaemonProcess* daemon_process, | |
188 int id, | |
189 WtsTerminalMonitor* monitor) | |
190 : DesktopSessionWin(caller_task_runner, io_task_runner, daemon_process, id, | |
191 monitor), | |
192 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | |
193 } | |
194 | |
195 RdpSession::~RdpSession() { | |
196 } | |
197 | |
198 bool RdpSession::Initialize(const DesktopSessionParams& params) { | |
199 DCHECK(caller_task_runner()->BelongsToCurrentThread()); | |
200 | |
201 // Create the RDP wrapper object. | |
202 HRESULT result = rdp_desktop_session_.CreateInstance( | |
203 __uuidof(RdpDesktopSession)); | |
204 if (FAILED(result)) { | |
205 LOG(ERROR) << "Failed to create RdpSession object, 0x" | |
206 << std::hex << result << std::dec << "."; | |
207 return false; | |
208 } | |
209 | |
210 // DaemonProcess::CreateDesktopSession() varifies that |client_dpi_| and | |
211 // |client_size_| are positive. | |
212 DCHECK(params.client_dpi_.x() >= 0 && params.client_dpi_.y() >= 0); | |
213 DCHECK(params.client_size_.width() >= 0 && params.client_size_.height() >= 0); | |
214 | |
215 // Handle the default DPI. | |
216 SkIPoint client_dpi = params.client_dpi_; | |
217 if (!client_dpi.x()) | |
218 client_dpi.setX(kDefaultDpiX); | |
219 if (!client_dpi.y()) | |
220 client_dpi.setY(kDefaultDpiY); | |
221 | |
222 // Make sure there will be no integer overflow while scaling the client | |
223 // resolution. | |
224 SkISize client_size = SkISize::Make( | |
225 std::min(params.client_size_.width(), | |
226 std::numeric_limits<int32_t>::max() / kDefaultDpiX), | |
227 std::min(params.client_size_.height(), | |
228 std::numeric_limits<int32_t>::max() / kDefaultDpiY)); | |
229 | |
230 // Scale the client resolution assiming RDP gives us the default 96 DPI. | |
231 SkISize host_size = SkISize::Make( | |
232 client_size.width() * kDefaultDpiX / client_dpi.x(), | |
233 client_size.height() * kDefaultDpiY / client_dpi.y()); | |
234 | |
235 // Make sure that the host resolution is within the limits supported by RDP. | |
236 host_size = SkISize::Make( | |
237 std::min(kMaxRdpScreenWidth, | |
238 std::max(kMinRdpScreenWidth, host_size.width())), | |
239 std::min(kMaxRdpScreenHeight, | |
240 std::max(kMinRdpScreenHeight, host_size.height()))); | |
241 | |
242 // Create an RDP session. | |
243 base::win::ScopedComPtr<IRdpDesktopSessionEventHandler> event_handler( | |
244 new EventHandler(weak_factory_.GetWeakPtr())); | |
245 result = rdp_desktop_session_->Connect(host_size.width(), | |
246 host_size.height(), | |
247 event_handler); | |
248 if (FAILED(result)) { | |
249 LOG(ERROR) << "RdpSession::Create() failed, 0x" | |
250 << std::hex << result << std::dec << "."; | |
251 return false; | |
252 } | |
253 | |
254 return true; | |
255 } | |
256 | |
257 void RdpSession::OnRdpConnected(const net::IPEndPoint& client_endpoint) { | |
258 DCHECK(caller_task_runner()->BelongsToCurrentThread()); | |
259 | |
260 StopMonitoring(); | |
261 StartMonitoring(client_endpoint); | |
262 } | |
263 | |
264 void RdpSession::OnRdpClosed() { | |
265 DCHECK(caller_task_runner()->BelongsToCurrentThread()); | |
266 | |
267 OnPermanentError(); | |
268 } | |
269 | |
270 void RdpSession::InjectSas() { | |
271 DCHECK(caller_task_runner()->BelongsToCurrentThread()); | |
272 | |
273 NOTIMPLEMENTED(); | |
274 } | |
275 | |
276 RdpSession::EventHandler::EventHandler( | |
277 base::WeakPtr<RdpSession> desktop_session) | |
278 : ref_count_(0), | |
279 desktop_session_(desktop_session) { | |
280 } | |
281 | |
282 RdpSession::EventHandler::~EventHandler() { | |
283 DCHECK(thread_checker_.CalledOnValidThread()); | |
284 | |
285 if (desktop_session_) | |
286 desktop_session_->OnRdpClosed(); | |
287 } | |
288 | |
289 ULONG STDMETHODCALLTYPE RdpSession::EventHandler::AddRef() { | |
290 DCHECK(thread_checker_.CalledOnValidThread()); | |
291 | |
292 return ++ref_count_; | |
293 } | |
294 | |
295 ULONG STDMETHODCALLTYPE RdpSession::EventHandler::Release() { | |
296 DCHECK(thread_checker_.CalledOnValidThread()); | |
297 | |
298 if (--ref_count_ == 0) { | |
299 delete this; | |
300 return 0; | |
301 } | |
302 | |
303 return ref_count_; | |
304 } | |
305 | |
306 STDMETHODIMP RdpSession::EventHandler::QueryInterface(REFIID riid, void** ppv) { | |
307 DCHECK(thread_checker_.CalledOnValidThread()); | |
308 | |
309 if (riid == IID_IUnknown || | |
310 riid == IID_IRdpDesktopSessionEventHandler) { | |
311 *ppv = static_cast<IRdpDesktopSessionEventHandler*>(this); | |
312 AddRef(); | |
313 return S_OK; | |
314 } | |
315 | |
316 *ppv = NULL; | |
317 return E_NOINTERFACE; | |
318 } | |
319 | |
320 STDMETHODIMP RdpSession::EventHandler::OnRdpConnected( | |
321 byte* client_endpoint, | |
322 long length) { | |
323 DCHECK(thread_checker_.CalledOnValidThread()); | |
324 | |
325 if (!desktop_session_) | |
326 return S_OK; | |
327 | |
328 net::IPEndPoint endpoint; | |
329 if (!endpoint.FromSockAddr(reinterpret_cast<sockaddr*>(client_endpoint), | |
330 length)) { | |
331 LOG(ERROR) << "Failed to parse the endpoint passed to OnRdpConnected()."; | |
332 OnRdpClosed(); | |
333 return S_OK; | |
334 } | |
335 | |
336 desktop_session_->OnRdpConnected(endpoint); | |
337 return S_OK; | |
338 } | |
339 | |
340 STDMETHODIMP RdpSession::EventHandler::OnRdpClosed() { | |
341 DCHECK(thread_checker_.CalledOnValidThread()); | |
342 | |
343 if (!desktop_session_) | |
344 return S_OK; | |
345 | |
346 base::WeakPtr<RdpSession> desktop_session = desktop_session_; | |
347 desktop_session_.reset(); | |
348 desktop_session->OnRdpClosed(); | |
349 return S_OK; | |
350 } | |
351 | |
34 } // namespace | 352 } // namespace |
35 | 353 |
36 namespace remoting { | 354 // static |
355 scoped_ptr<DesktopSession> DesktopSessionWin::CreateForConsole( | |
356 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
357 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
358 DaemonProcess* daemon_process, | |
359 int id, | |
360 const DesktopSessionParams& params) { | |
361 scoped_ptr<ConsoleSession> session(new ConsoleSession( | |
362 caller_task_runner, io_task_runner, daemon_process, id, | |
363 HostService::GetInstance())); | |
364 | |
365 return session.PassAs<DesktopSession>(); | |
366 } | |
367 | |
368 // static | |
369 scoped_ptr<DesktopSession> DesktopSessionWin::CreateForVirtualTerminal( | |
370 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, | |
371 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | |
372 DaemonProcess* daemon_process, | |
373 int id, | |
374 const DesktopSessionParams& params) { | |
375 scoped_ptr<RdpSession> session(new RdpSession( | |
376 caller_task_runner, io_task_runner, daemon_process, id, | |
377 HostService::GetInstance())); | |
378 if (!session->Initialize(params)) | |
379 return scoped_ptr<DesktopSession>(); | |
380 | |
381 return session.PassAs<DesktopSession>(); | |
382 } | |
37 | 383 |
38 DesktopSessionWin::DesktopSessionWin( | 384 DesktopSessionWin::DesktopSessionWin( |
39 scoped_refptr<AutoThreadTaskRunner> main_task_runner, | 385 scoped_refptr<AutoThreadTaskRunner> caller_task_runner, |
40 scoped_refptr<AutoThreadTaskRunner> io_task_runner, | 386 scoped_refptr<AutoThreadTaskRunner> io_task_runner, |
41 DaemonProcess* daemon_process, | 387 DaemonProcess* daemon_process, |
42 int id, | 388 int id, |
43 const DesktopSessionParams& params, | |
44 bool virtual_terminal, | |
45 WtsTerminalMonitor* monitor) | 389 WtsTerminalMonitor* monitor) |
46 : DesktopSession(daemon_process, id), | 390 : DesktopSession(daemon_process, id), |
47 main_task_runner_(main_task_runner), | 391 caller_task_runner_(caller_task_runner), |
48 io_task_runner_(io_task_runner), | 392 io_task_runner_(io_task_runner), |
49 monitor_(monitor) { | 393 monitor_(monitor), |
50 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 394 monitoring_notifications_(false) { |
51 | 395 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
52 monitor_->AddWtsTerminalObserver(net::IPEndPoint(), this); | |
53 } | 396 } |
54 | 397 |
55 DesktopSessionWin::~DesktopSessionWin() { | 398 DesktopSessionWin::~DesktopSessionWin() { |
56 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 399 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
57 | 400 |
58 launcher_.reset(); | 401 StopMonitoring(); |
59 monitor_->RemoveWtsTerminalObserver(this); | 402 } |
403 | |
404 void DesktopSessionWin::OnSessionAttachTimeout() { | |
405 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
406 | |
407 LOG(ERROR) << "Session attach notification hasn't arrived within " | |
Wez
2013/03/13 22:30:27
nit: "didn't arrive within" or "hasn't arrived aft
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
408 << kSessionAttachTimeoutSeconds << " seconds."; | |
409 OnPermanentError(); | |
410 } | |
411 | |
412 void DesktopSessionWin::StartMonitoring( | |
413 const net::IPEndPoint& client_endpoint) { | |
414 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
415 DCHECK(!monitoring_notifications_); | |
416 DCHECK(!session_attach_timer_.IsRunning()); | |
417 | |
418 session_attach_timer_.Start( | |
419 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds), | |
420 this, &DesktopSessionWin::OnSessionAttachTimeout); | |
421 | |
422 monitoring_notifications_ = true; | |
423 monitor_->AddWtsTerminalObserver(client_endpoint, this); | |
424 } | |
425 | |
426 void DesktopSessionWin::StopMonitoring() { | |
427 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
428 | |
429 if (monitoring_notifications_) { | |
430 monitoring_notifications_ = false; | |
431 monitor_->RemoveWtsTerminalObserver(this); | |
432 } | |
433 | |
434 session_attach_timer_.Stop(); | |
435 OnSessionDetached(); | |
60 } | 436 } |
61 | 437 |
62 void DesktopSessionWin::OnChannelConnected(int32 peer_pid) { | 438 void DesktopSessionWin::OnChannelConnected(int32 peer_pid) { |
63 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 439 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
64 | 440 |
65 // Obtain the handle of the desktop process. It will be passed to the network | 441 // 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 | 442 // process so it would be able to duplicate handles of shared memory objects |
Wez
2013/03/13 22:30:27
nit: "so it would be able to" -> "to use to"
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
67 // from the desktop process. | 443 // from the desktop process. |
68 desktop_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid)); | 444 desktop_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid)); |
69 if (!desktop_process_.IsValid()) { | 445 if (!desktop_process_.IsValid()) { |
70 RestartDesktopProcess(FROM_HERE); | 446 RestartDesktopProcess(FROM_HERE); |
71 return; | 447 return; |
72 } | 448 } |
73 | 449 |
74 VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")"; | 450 VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")"; |
75 } | 451 } |
76 | 452 |
77 bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) { | 453 bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) { |
78 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 454 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
79 | 455 |
80 bool handled = true; | 456 bool handled = true; |
81 IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message) | 457 IPC_BEGIN_MESSAGE_MAP(DesktopSessionWin, message) |
82 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, | 458 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, |
83 OnDesktopSessionAgentAttached) | 459 OnDesktopSessionAgentAttached) |
84 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas, | 460 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_InjectSas, |
85 OnInjectSas) | 461 InjectSas) |
86 IPC_MESSAGE_UNHANDLED(handled = false) | 462 IPC_MESSAGE_UNHANDLED(handled = false) |
87 IPC_END_MESSAGE_MAP() | 463 IPC_END_MESSAGE_MAP() |
88 | 464 |
89 if (!handled) { | 465 if (!handled) { |
90 LOG(ERROR) << "Received unexpected IPC type: " << message.type(); | 466 LOG(ERROR) << "Received unexpected IPC type: " << message.type(); |
91 RestartDesktopProcess(FROM_HERE); | 467 RestartDesktopProcess(FROM_HERE); |
92 } | 468 } |
93 | 469 |
94 return handled; | 470 return handled; |
95 } | 471 } |
96 | 472 |
97 void DesktopSessionWin::OnPermanentError() { | 473 void DesktopSessionWin::OnPermanentError() { |
98 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 474 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
99 | 475 |
100 launcher_.reset(); | 476 StopMonitoring(); |
101 | 477 |
102 // This call will delete |this| so it should be at the very end of the method. | 478 // This call will delete |this| so it should be at the very end of the method. |
103 daemon_process()->CloseDesktopSession(id()); | 479 daemon_process()->CloseDesktopSession(id()); |
104 } | 480 } |
105 | 481 |
106 void DesktopSessionWin::OnSessionAttached(uint32 session_id) { | 482 void DesktopSessionWin::OnSessionAttached(uint32 session_id) { |
107 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 483 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
108 DCHECK(launcher_.get() == NULL); | 484 DCHECK(!launcher_); |
485 DCHECK(monitoring_notifications_); | |
109 | 486 |
110 // Get the desktop binary name. | 487 // Get the desktop binary name. |
Wez
2013/03/13 22:30:27
nit: Suggest "Get the name of the executable the d
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
111 base::FilePath desktop_binary; | 488 base::FilePath desktop_binary; |
112 if (!GetInstalledBinaryPath(kDesktopBinaryName, &desktop_binary)) { | 489 if (!GetInstalledBinaryPath(kDesktopBinaryName, &desktop_binary)) { |
113 OnPermanentError(); | 490 OnPermanentError(); |
114 return; | 491 return; |
115 } | 492 } |
116 | 493 |
494 session_attach_timer_.Stop(); | |
495 | |
117 scoped_ptr<CommandLine> target(new CommandLine(desktop_binary)); | 496 scoped_ptr<CommandLine> target(new CommandLine(desktop_binary)); |
Wez
2013/03/13 22:30:27
nit: Add a comment to explain why we're copying sw
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
118 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeDesktop); | 497 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeDesktop); |
119 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), | 498 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), |
120 kCopiedSwitchNames, | 499 kCopiedSwitchNames, |
121 arraysize(kCopiedSwitchNames)); | 500 arraysize(kCopiedSwitchNames)); |
122 | 501 |
123 // Create a delegate to launch a process into the session. | 502 // Create a delegate to launch a process into the session. |
Wez
2013/03/13 22:30:27
nit: "to launch the process into the session" ?
alexeypa (please no reviews)
2013/03/13 22:51:50
Done.
| |
124 scoped_ptr<WtsSessionProcessDelegate> delegate( | 503 scoped_ptr<WtsSessionProcessDelegate> delegate( |
125 new WtsSessionProcessDelegate(main_task_runner_, io_task_runner_, | 504 new WtsSessionProcessDelegate( |
126 target.Pass(), session_id, | 505 caller_task_runner_, io_task_runner_, target.Pass(), session_id, true, |
127 true, kDaemonIpcSecurityDescriptor)); | 506 WideToUTF8(kDaemonIpcSecurityDescriptor))); |
128 | 507 |
129 // Create a launcher for the desktop process, using the per-session delegate. | 508 // Create a launcher for the desktop process, using the per-session delegate. |
130 launcher_.reset(new WorkerProcessLauncher( | 509 launcher_.reset(new WorkerProcessLauncher( |
131 main_task_runner_, delegate.Pass(), this)); | 510 caller_task_runner_, delegate.Pass(), this)); |
132 } | 511 } |
133 | 512 |
134 void DesktopSessionWin::OnSessionDetached() { | 513 void DesktopSessionWin::OnSessionDetached() { |
135 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 514 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
136 DCHECK(launcher_.get() != NULL); | |
137 | 515 |
138 launcher_.reset(); | 516 launcher_.reset(); |
517 | |
518 if (monitoring_notifications_) { | |
519 session_attach_timer_.Start( | |
520 FROM_HERE, base::TimeDelta::FromSeconds(kSessionAttachTimeoutSeconds), | |
521 this, &DesktopSessionWin::OnSessionAttachTimeout); | |
522 } | |
139 } | 523 } |
140 | 524 |
141 void DesktopSessionWin::OnDesktopSessionAgentAttached( | 525 void DesktopSessionWin::OnDesktopSessionAgentAttached( |
142 IPC::PlatformFileForTransit desktop_pipe) { | 526 IPC::PlatformFileForTransit desktop_pipe) { |
143 if (!daemon_process()->OnDesktopSessionAgentAttached(id(), | 527 if (!daemon_process()->OnDesktopSessionAgentAttached(id(), |
144 desktop_process_, | 528 desktop_process_, |
145 desktop_pipe)) { | 529 desktop_pipe)) { |
146 RestartDesktopProcess(FROM_HERE); | 530 RestartDesktopProcess(FROM_HERE); |
147 } | 531 } |
148 } | 532 } |
149 | 533 |
150 void DesktopSessionWin::OnInjectSas() { | |
151 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
152 | |
153 // Do not try to inject SAS if the desktop process is not running. This can | |
154 // happen when the session has detached from the console for instance. | |
155 if (!launcher_) | |
156 return; | |
157 | |
158 if (!sas_injector_) | |
159 sas_injector_ = SasInjector::Create(); | |
160 if (!sas_injector_->InjectSas()) | |
161 LOG(ERROR) << "Failed to inject Secure Attention Sequence."; | |
162 } | |
163 | |
164 void DesktopSessionWin::RestartDesktopProcess( | 534 void DesktopSessionWin::RestartDesktopProcess( |
165 const tracked_objects::Location& location) { | 535 const tracked_objects::Location& location) { |
166 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 536 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
167 | 537 |
168 launcher_->Send(new ChromotingDaemonDesktopMsg_Crash( | 538 launcher_->Send(new ChromotingDaemonDesktopMsg_Crash( |
169 location.function_name(), location.file_name(), location.line_number())); | 539 location.function_name(), location.file_name(), location.line_number())); |
170 } | 540 } |
171 | 541 |
172 } // namespace remoting | 542 } // namespace remoting |
OLD | NEW |