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

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

Issue 10048003: The Chromoting service should not start automatically unless it was configured from the webapp to d… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback Created 8 years, 8 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 // This file implements the Windows service controlling Me2Me host processes 5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions. 6 // running within user sessions.
7 7
8 #include "remoting/host/wts_session_process_launcher_win.h" 8 #include "remoting/host/wts_session_process_launcher_win.h"
9 9
10 #include <windows.h> 10 #include <windows.h>
11 #include <sddl.h> 11 #include <sddl.h>
12 #include <limits> 12 #include <limits>
13 13
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
14 #include "base/command_line.h" 16 #include "base/command_line.h"
15 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/message_loop_proxy.h"
16 #include "base/process_util.h" 19 #include "base/process_util.h"
17 #include "base/rand_util.h" 20 #include "base/rand_util.h"
18 #include "base/string16.h" 21 #include "base/string16.h"
19 #include "base/stringprintf.h" 22 #include "base/stringprintf.h"
20 #include "base/threading/thread.h"
21 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
22 #include "base/win/scoped_handle.h" 24 #include "base/win/scoped_handle.h"
23 #include "base/win/scoped_process_information.h" 25 #include "base/win/scoped_process_information.h"
24 #include "ipc/ipc_channel_proxy.h" 26 #include "ipc/ipc_channel_proxy.h"
25 #include "ipc/ipc_message.h" 27 #include "ipc/ipc_message.h"
26 #include "ipc/ipc_message_macros.h" 28 #include "ipc/ipc_message_macros.h"
27 29
28 #include "remoting/host/chromoting_messages.h" 30 #include "remoting/host/chromoting_messages.h"
29 #include "remoting/host/sas_injector.h" 31 #include "remoting/host/sas_injector.h"
30 #include "remoting/host/wts_console_monitor_win.h" 32 #include "remoting/host/wts_console_monitor_win.h"
31 33
32 using base::win::ScopedHandle; 34 using base::win::ScopedHandle;
33 using base::TimeDelta; 35 using base::TimeDelta;
34 36
35 namespace { 37 namespace {
36 38
39 // The exit code returned by the host process when its configuration is not
40 // valid.
41 const int kInvalidHostConfigurationExitCode = 1;
42
37 // The minimum and maximum delays between attempts to inject host process into 43 // The minimum and maximum delays between attempts to inject host process into
38 // a session. 44 // a session.
39 const int kMaxLaunchDelaySeconds = 60; 45 const int kMaxLaunchDelaySeconds = 60;
40 const int kMinLaunchDelaySeconds = 1; 46 const int kMinLaunchDelaySeconds = 1;
41 47
42 // Name of the default session desktop. 48 // Name of the default session desktop.
43 const char kDefaultDesktopName[] = "winsta0\\default"; 49 const char kDefaultDesktopName[] = "winsta0\\default";
44 50
45 // Match the pipe name prefix used by Chrome IPC channels. 51 // Match the pipe name prefix used by Chrome IPC channels.
46 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome."; 52 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 return true; 246 return true;
241 } 247 }
242 248
243 } // namespace 249 } // namespace
244 250
245 namespace remoting { 251 namespace remoting {
246 252
247 WtsSessionProcessLauncher::WtsSessionProcessLauncher( 253 WtsSessionProcessLauncher::WtsSessionProcessLauncher(
248 WtsConsoleMonitor* monitor, 254 WtsConsoleMonitor* monitor,
249 const FilePath& host_binary, 255 const FilePath& host_binary,
250 base::Thread* io_thread) 256 scoped_refptr<base::MessageLoopProxy> main_message_loop,
257 scoped_refptr<base::MessageLoopProxy> ipc_message_loop)
251 : host_binary_(host_binary), 258 : host_binary_(host_binary),
252 io_thread_(io_thread), 259 main_message_loop_(main_message_loop),
260 ipc_message_loop_(ipc_message_loop),
253 monitor_(monitor), 261 monitor_(monitor),
254 state_(StateDetached) { 262 state_(StateDetached) {
255 monitor_->AddWtsConsoleObserver(this); 263 monitor_->AddWtsConsoleObserver(this);
256 } 264 }
257 265
258 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { 266 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() {
259 DCHECK(state_ == StateDetached); 267 DCHECK(state_ == StateDetached);
260 DCHECK(!timer_.IsRunning()); 268 DCHECK(!timer_.IsRunning());
261 DCHECK(process_.handle() == NULL); 269 DCHECK(process_.handle() == NULL);
262 DCHECK(process_watcher_.GetWatchedObject() == NULL); 270 DCHECK(process_watcher_.GetWatchedObject() == NULL);
263 DCHECK(chromoting_channel_.get() == NULL); 271 DCHECK(chromoting_channel_.get() == NULL);
264 272
265 monitor_->RemoveWtsConsoleObserver(this); 273 monitor_->RemoveWtsConsoleObserver(this);
266 } 274 }
267 275
268 void WtsSessionProcessLauncher::LaunchProcess() { 276 void WtsSessionProcessLauncher::LaunchProcess() {
277 DCHECK(main_message_loop_->BelongsToCurrentThread());
269 DCHECK(state_ == StateStarting); 278 DCHECK(state_ == StateStarting);
270 DCHECK(!timer_.IsRunning()); 279 DCHECK(!timer_.IsRunning());
271 DCHECK(process_.handle() == NULL); 280 DCHECK(process_.handle() == NULL);
272 DCHECK(process_watcher_.GetWatchedObject() == NULL); 281 DCHECK(process_watcher_.GetWatchedObject() == NULL);
273 DCHECK(chromoting_channel_.get() == NULL); 282 DCHECK(chromoting_channel_.get() == NULL);
274 283
275 launch_time_ = base::Time::Now(); 284 launch_time_ = base::Time::Now();
276 285
277 string16 channel_name; 286 string16 channel_name;
278 ScopedHandle pipe; 287 ScopedHandle pipe;
279 if (CreatePipeForIpcChannel(this, &channel_name, &pipe)) { 288 if (CreatePipeForIpcChannel(this, &channel_name, &pipe)) {
280 // Wrap the pipe into an IPC channel. 289 // Wrap the pipe into an IPC channel.
281 chromoting_channel_.reset(new IPC::ChannelProxy( 290 chromoting_channel_.reset(new IPC::ChannelProxy(
282 IPC::ChannelHandle(pipe.Get()), 291 IPC::ChannelHandle(pipe.Get()),
283 IPC::Channel::MODE_SERVER, 292 IPC::Channel::MODE_SERVER,
284 this, 293 this,
285 io_thread_->message_loop_proxy().get())); 294 ipc_message_loop_));
286 295
287 // Create the host process command line passing the name of the IPC channel 296 // Create the host process command line passing the name of the IPC channel
288 // to use and copying known switches from the service's command line. 297 // to use and copying known switches from the service's command line.
289 CommandLine command_line(host_binary_); 298 CommandLine command_line(host_binary_);
290 command_line.AppendSwitchNative(kChromotingIpcSwitchName, channel_name); 299 command_line.AppendSwitchNative(kChromotingIpcSwitchName, channel_name);
291 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 300 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
292 kCopiedSwitchNames, 301 kCopiedSwitchNames,
293 _countof(kCopiedSwitchNames)); 302 _countof(kCopiedSwitchNames));
294 303
295 // Try to launch the process and attach an object watcher to the returned 304 // Try to launch the process and attach an object watcher to the returned
(...skipping 17 matching lines...) Expand all
313 // is limited by exponential backoff. 322 // is limited by exponential backoff.
314 launch_backoff_ = std::max(launch_backoff_ * 2, 323 launch_backoff_ = std::max(launch_backoff_ * 2,
315 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 324 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
316 launch_backoff_ = std::min(launch_backoff_, 325 launch_backoff_ = std::min(launch_backoff_,
317 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 326 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
318 timer_.Start(FROM_HERE, launch_backoff_, 327 timer_.Start(FROM_HERE, launch_backoff_,
319 this, &WtsSessionProcessLauncher::LaunchProcess); 328 this, &WtsSessionProcessLauncher::LaunchProcess);
320 } 329 }
321 330
322 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { 331 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) {
323 DCHECK(state_ == StateAttached); 332 if (!main_message_loop_->BelongsToCurrentThread()) {
333 main_message_loop_->PostTask(
334 FROM_HERE, base::Bind(&WtsSessionProcessLauncher::OnObjectSignaled,
335 base::Unretained(this), object));
336 return;
337 }
338
339 // It is possible that OnObjectSignaled() task will be queued by another
340 // thread right before |process_watcher_| was stopped. It such a case it is
341 // safe to ignore this notiifcation.
Wez 2012/04/11 01:01:23 typo: notiification
alexeypa (please no reviews) 2012/04/11 17:39:39 Done.
342 if (state_ != StateAttached) {
343 return;
344 }
345
324 DCHECK(!timer_.IsRunning()); 346 DCHECK(!timer_.IsRunning());
325 DCHECK(process_.handle() != NULL); 347 DCHECK(process_.handle() != NULL);
326 DCHECK(process_watcher_.GetWatchedObject() == NULL); 348 DCHECK(process_watcher_.GetWatchedObject() == NULL);
327 DCHECK(chromoting_channel_.get() != NULL); 349 DCHECK(chromoting_channel_.get() != NULL);
328 350
351 // Stop trying to restart the host if its process exited due misconfiguration.
Wez 2012/04/11 01:01:23 typo: ... due to misconfiguration.
alexeypa (please no reviews) 2012/04/11 17:39:39 Done.
352 DWORD exit_code;
353 bool stop_trying = GetExitCodeProcess(process_.handle(), &exit_code) &&
354 exit_code == kInvalidHostConfigurationExitCode;
355
329 // The host process has been terminated for some reason. The handle can now be 356 // The host process has been terminated for some reason. The handle can now be
330 // closed. 357 // closed.
331 process_.Close(); 358 process_.Close();
332 chromoting_channel_.reset(); 359 chromoting_channel_.reset();
333 360
361 if (stop_trying) {
362 // N.B. The service will stop once the last observer is removed from
363 // the list.
364 monitor_->RequestRemoveWtsConsoleObserver(this);
365 return;
366 }
367
334 // Expand the backoff interval if the process has died quickly or reset it if 368 // Expand the backoff interval if the process has died quickly or reset it if
335 // it was up longer than the maximum backoff delay. 369 // it was up longer than the maximum backoff delay.
336 base::TimeDelta delta = base::Time::Now() - launch_time_; 370 base::TimeDelta delta = base::Time::Now() - launch_time_;
337 if (delta < base::TimeDelta() || 371 if (delta < base::TimeDelta() ||
338 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) { 372 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) {
339 launch_backoff_ = base::TimeDelta(); 373 launch_backoff_ = base::TimeDelta();
340 } else { 374 } else {
341 launch_backoff_ = std::max(launch_backoff_ * 2, 375 launch_backoff_ = std::max(launch_backoff_ * 2,
342 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 376 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
343 launch_backoff_ = std::min(launch_backoff_, 377 launch_backoff_ = std::min(launch_backoff_,
(...skipping 10 matching lines...) Expand all
354 bool handled = true; 388 bool handled = true;
355 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message) 389 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message)
356 IPC_MESSAGE_HANDLER(ChromotingHostMsg_SendSasToConsole, 390 IPC_MESSAGE_HANDLER(ChromotingHostMsg_SendSasToConsole,
357 OnSendSasToConsole) 391 OnSendSasToConsole)
358 IPC_MESSAGE_UNHANDLED(handled = false) 392 IPC_MESSAGE_UNHANDLED(handled = false)
359 IPC_END_MESSAGE_MAP() 393 IPC_END_MESSAGE_MAP()
360 return handled; 394 return handled;
361 } 395 }
362 396
363 void WtsSessionProcessLauncher::OnSendSasToConsole() { 397 void WtsSessionProcessLauncher::OnSendSasToConsole() {
398 if (!main_message_loop_->BelongsToCurrentThread()) {
399 main_message_loop_->PostTask(
400 FROM_HERE, base::Bind(&WtsSessionProcessLauncher::OnSendSasToConsole,
401 base::Unretained(this)));
402 return;
403 }
404
364 if (state_ == StateAttached) { 405 if (state_ == StateAttached) {
365 if (sas_injector_.get() == NULL) { 406 if (sas_injector_.get() == NULL) {
366 sas_injector_ = SasInjector::Create(); 407 sas_injector_ = SasInjector::Create();
367 } 408 }
368 409
369 if (sas_injector_.get() != NULL) { 410 if (sas_injector_.get() != NULL) {
370 sas_injector_->InjectSas(); 411 sas_injector_->InjectSas();
371 } 412 }
372 } 413 }
373 } 414 }
374 415
375 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { 416 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
417 DCHECK(main_message_loop_->BelongsToCurrentThread());
376 DCHECK(state_ == StateDetached); 418 DCHECK(state_ == StateDetached);
377 DCHECK(!timer_.IsRunning()); 419 DCHECK(!timer_.IsRunning());
378 DCHECK(process_.handle() == NULL); 420 DCHECK(process_.handle() == NULL);
379 DCHECK(process_watcher_.GetWatchedObject() == NULL); 421 DCHECK(process_watcher_.GetWatchedObject() == NULL);
380 DCHECK(chromoting_channel_.get() == NULL); 422 DCHECK(chromoting_channel_.get() == NULL);
381 423
382 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is 424 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is
383 // created as needed and kept for later reuse. 425 // created as needed and kept for later reuse.
384 if (privileged_token_.Get() == NULL) { 426 if (privileged_token_.Get() == NULL) {
385 if (!CreatePrivilegedToken(&privileged_token_)) { 427 if (!CreatePrivilegedToken(&privileged_token_)) {
(...skipping 17 matching lines...) Expand all
403 445
404 if (!result) 446 if (!result)
405 return; 447 return;
406 448
407 // Now try to launch the host. 449 // Now try to launch the host.
408 state_ = StateStarting; 450 state_ = StateStarting;
409 LaunchProcess(); 451 LaunchProcess();
410 } 452 }
411 453
412 void WtsSessionProcessLauncher::OnSessionDetached() { 454 void WtsSessionProcessLauncher::OnSessionDetached() {
455 DCHECK(main_message_loop_->BelongsToCurrentThread());
413 DCHECK(state_ == StateDetached || 456 DCHECK(state_ == StateDetached ||
414 state_ == StateStarting || 457 state_ == StateStarting ||
415 state_ == StateAttached); 458 state_ == StateAttached);
416 459
417 switch (state_) { 460 switch (state_) {
418 case StateDetached: 461 case StateDetached:
419 DCHECK(!timer_.IsRunning()); 462 DCHECK(!timer_.IsRunning());
420 DCHECK(process_.handle() == NULL); 463 DCHECK(process_.handle() == NULL);
421 DCHECK(process_watcher_.GetWatchedObject() == NULL); 464 DCHECK(process_watcher_.GetWatchedObject() == NULL);
422 DCHECK(chromoting_channel_.get() == NULL); 465 DCHECK(chromoting_channel_.get() == NULL);
(...skipping 19 matching lines...) Expand all
442 process_watcher_.StopWatching(); 485 process_watcher_.StopWatching();
443 process_.Terminate(0); 486 process_.Terminate(0);
444 process_.Close(); 487 process_.Close();
445 chromoting_channel_.reset(); 488 chromoting_channel_.reset();
446 state_ = StateDetached; 489 state_ = StateDetached;
447 break; 490 break;
448 } 491 }
449 } 492 }
450 493
451 } // namespace remoting 494 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698