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

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: rebased. 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
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (monitor_ != NULL) {
265 monitor_->RemoveWtsConsoleObserver(this); 273 monitor_->RemoveWtsConsoleObserver(this);
274 }
266 } 275 }
267 276
268 void WtsSessionProcessLauncher::LaunchProcess() { 277 void WtsSessionProcessLauncher::LaunchProcess() {
278 DCHECK(main_message_loop_->BelongsToCurrentThread());
269 DCHECK(state_ == StateStarting); 279 DCHECK(state_ == StateStarting);
270 DCHECK(!timer_.IsRunning()); 280 DCHECK(!timer_.IsRunning());
271 DCHECK(process_.handle() == NULL); 281 DCHECK(process_.handle() == NULL);
272 DCHECK(process_watcher_.GetWatchedObject() == NULL); 282 DCHECK(process_watcher_.GetWatchedObject() == NULL);
273 DCHECK(chromoting_channel_.get() == NULL); 283 DCHECK(chromoting_channel_.get() == NULL);
274 284
275 launch_time_ = base::Time::Now(); 285 launch_time_ = base::Time::Now();
276 286
277 string16 channel_name; 287 string16 channel_name;
278 ScopedHandle pipe; 288 ScopedHandle pipe;
279 if (CreatePipeForIpcChannel(this, &channel_name, &pipe)) { 289 if (CreatePipeForIpcChannel(this, &channel_name, &pipe)) {
280 // Wrap the pipe into an IPC channel. 290 // Wrap the pipe into an IPC channel.
281 chromoting_channel_.reset(new IPC::ChannelProxy( 291 chromoting_channel_.reset(new IPC::ChannelProxy(
282 IPC::ChannelHandle(pipe.Get()), 292 IPC::ChannelHandle(pipe.Get()),
283 IPC::Channel::MODE_SERVER, 293 IPC::Channel::MODE_SERVER,
284 this, 294 this,
285 io_thread_->message_loop_proxy().get())); 295 ipc_message_loop_));
286 296
287 // Create the host process command line passing the name of the IPC channel 297 // 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. 298 // to use and copying known switches from the service's command line.
289 CommandLine command_line(host_binary_); 299 CommandLine command_line(host_binary_);
290 command_line.AppendSwitchNative(kChromotingIpcSwitchName, channel_name); 300 command_line.AppendSwitchNative(kChromotingIpcSwitchName, channel_name);
291 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 301 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
292 kCopiedSwitchNames, 302 kCopiedSwitchNames,
293 _countof(kCopiedSwitchNames)); 303 _countof(kCopiedSwitchNames));
294 304
295 // Try to launch the process and attach an object watcher to the returned 305 // 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. 323 // is limited by exponential backoff.
314 launch_backoff_ = std::max(launch_backoff_ * 2, 324 launch_backoff_ = std::max(launch_backoff_ * 2,
315 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 325 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
316 launch_backoff_ = std::min(launch_backoff_, 326 launch_backoff_ = std::min(launch_backoff_,
317 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 327 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
318 timer_.Start(FROM_HERE, launch_backoff_, 328 timer_.Start(FROM_HERE, launch_backoff_,
319 this, &WtsSessionProcessLauncher::LaunchProcess); 329 this, &WtsSessionProcessLauncher::LaunchProcess);
320 } 330 }
321 331
322 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { 332 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) {
323 DCHECK(state_ == StateAttached); 333 if (!main_message_loop_->BelongsToCurrentThread()) {
334 main_message_loop_->PostTask(
335 FROM_HERE, base::Bind(&WtsSessionProcessLauncher::OnObjectSignaled,
336 base::Unretained(this), object));
337 return;
338 }
339
340 // It is possible that OnObjectSignaled() task will be queued by another
341 // thread right before |process_watcher_| was stopped. It such a case it is
342 // safe to ignore this notification.
343 if (state_ != StateAttached) {
344 return;
345 }
346
324 DCHECK(!timer_.IsRunning()); 347 DCHECK(!timer_.IsRunning());
325 DCHECK(process_.handle() != NULL); 348 DCHECK(process_.handle() != NULL);
326 DCHECK(process_watcher_.GetWatchedObject() == NULL); 349 DCHECK(process_watcher_.GetWatchedObject() == NULL);
327 DCHECK(chromoting_channel_.get() != NULL); 350 DCHECK(chromoting_channel_.get() != NULL);
328 351
352 // Stop trying to restart the host if its process exited due to
353 // misconfiguration.
354 DWORD exit_code;
355 bool stop_trying = GetExitCodeProcess(process_.handle(), &exit_code) &&
356 exit_code == kInvalidHostConfigurationExitCode;
357
329 // The host process has been terminated for some reason. The handle can now be 358 // The host process has been terminated for some reason. The handle can now be
330 // closed. 359 // closed.
331 process_.Close(); 360 process_.Close();
332 chromoting_channel_.reset(); 361 chromoting_channel_.reset();
362 state_ = StateStarting;
363
364 if (stop_trying) {
365 OnSessionDetached();
366
367 // N.B. The service will stop once the last observer is removed from
368 // the list.
369 monitor_->RemoveWtsConsoleObserver(this);
370 monitor_ = NULL;
371 return;
372 }
333 373
334 // Expand the backoff interval if the process has died quickly or reset it if 374 // Expand the backoff interval if the process has died quickly or reset it if
335 // it was up longer than the maximum backoff delay. 375 // it was up longer than the maximum backoff delay.
336 base::TimeDelta delta = base::Time::Now() - launch_time_; 376 base::TimeDelta delta = base::Time::Now() - launch_time_;
337 if (delta < base::TimeDelta() || 377 if (delta < base::TimeDelta() ||
338 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) { 378 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) {
339 launch_backoff_ = base::TimeDelta(); 379 launch_backoff_ = base::TimeDelta();
340 } else { 380 } else {
341 launch_backoff_ = std::max(launch_backoff_ * 2, 381 launch_backoff_ = std::max(launch_backoff_ * 2,
342 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 382 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
343 launch_backoff_ = std::min(launch_backoff_, 383 launch_backoff_ = std::min(launch_backoff_,
344 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 384 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
345 } 385 }
346 386
347 // Try to restart the host. 387 // Try to restart the host.
348 state_ = StateStarting;
349 timer_.Start(FROM_HERE, launch_backoff_, 388 timer_.Start(FROM_HERE, launch_backoff_,
350 this, &WtsSessionProcessLauncher::LaunchProcess); 389 this, &WtsSessionProcessLauncher::LaunchProcess);
351 } 390 }
352 391
353 bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) { 392 bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) {
354 bool handled = true; 393 bool handled = true;
355 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message) 394 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message)
356 IPC_MESSAGE_HANDLER(ChromotingHostMsg_SendSasToConsole, 395 IPC_MESSAGE_HANDLER(ChromotingHostMsg_SendSasToConsole,
357 OnSendSasToConsole) 396 OnSendSasToConsole)
358 IPC_MESSAGE_UNHANDLED(handled = false) 397 IPC_MESSAGE_UNHANDLED(handled = false)
359 IPC_END_MESSAGE_MAP() 398 IPC_END_MESSAGE_MAP()
360 return handled; 399 return handled;
361 } 400 }
362 401
363 void WtsSessionProcessLauncher::OnSendSasToConsole() { 402 void WtsSessionProcessLauncher::OnSendSasToConsole() {
403 if (!main_message_loop_->BelongsToCurrentThread()) {
404 main_message_loop_->PostTask(
405 FROM_HERE, base::Bind(&WtsSessionProcessLauncher::OnSendSasToConsole,
406 base::Unretained(this)));
407 return;
408 }
409
364 if (state_ == StateAttached) { 410 if (state_ == StateAttached) {
365 if (sas_injector_.get() == NULL) { 411 if (sas_injector_.get() == NULL) {
366 sas_injector_ = SasInjector::Create(); 412 sas_injector_ = SasInjector::Create();
367 } 413 }
368 414
369 if (sas_injector_.get() != NULL) { 415 if (sas_injector_.get() != NULL) {
370 sas_injector_->InjectSas(); 416 sas_injector_->InjectSas();
371 } 417 }
372 } 418 }
373 } 419 }
374 420
375 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { 421 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
422 DCHECK(main_message_loop_->BelongsToCurrentThread());
376 DCHECK(state_ == StateDetached); 423 DCHECK(state_ == StateDetached);
377 DCHECK(!timer_.IsRunning()); 424 DCHECK(!timer_.IsRunning());
378 DCHECK(process_.handle() == NULL); 425 DCHECK(process_.handle() == NULL);
379 DCHECK(process_watcher_.GetWatchedObject() == NULL); 426 DCHECK(process_watcher_.GetWatchedObject() == NULL);
380 DCHECK(chromoting_channel_.get() == NULL); 427 DCHECK(chromoting_channel_.get() == NULL);
381 428
382 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is 429 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is
383 // created as needed and kept for later reuse. 430 // created as needed and kept for later reuse.
384 if (privileged_token_.Get() == NULL) { 431 if (privileged_token_.Get() == NULL) {
385 if (!CreatePrivilegedToken(&privileged_token_)) { 432 if (!CreatePrivilegedToken(&privileged_token_)) {
(...skipping 17 matching lines...) Expand all
403 450
404 if (!result) 451 if (!result)
405 return; 452 return;
406 453
407 // Now try to launch the host. 454 // Now try to launch the host.
408 state_ = StateStarting; 455 state_ = StateStarting;
409 LaunchProcess(); 456 LaunchProcess();
410 } 457 }
411 458
412 void WtsSessionProcessLauncher::OnSessionDetached() { 459 void WtsSessionProcessLauncher::OnSessionDetached() {
460 DCHECK(main_message_loop_->BelongsToCurrentThread());
413 DCHECK(state_ == StateDetached || 461 DCHECK(state_ == StateDetached ||
414 state_ == StateStarting || 462 state_ == StateStarting ||
415 state_ == StateAttached); 463 state_ == StateAttached);
416 464
417 switch (state_) { 465 switch (state_) {
418 case StateDetached: 466 case StateDetached:
419 DCHECK(!timer_.IsRunning()); 467 DCHECK(!timer_.IsRunning());
420 DCHECK(process_.handle() == NULL); 468 DCHECK(process_.handle() == NULL);
421 DCHECK(process_watcher_.GetWatchedObject() == NULL); 469 DCHECK(process_watcher_.GetWatchedObject() == NULL);
422 DCHECK(chromoting_channel_.get() == NULL); 470 DCHECK(chromoting_channel_.get() == NULL);
423 break; 471 break;
424 472
425 case StateStarting: 473 case StateStarting:
426 DCHECK(timer_.IsRunning());
427 DCHECK(process_.handle() == NULL); 474 DCHECK(process_.handle() == NULL);
428 DCHECK(process_watcher_.GetWatchedObject() == NULL); 475 DCHECK(process_watcher_.GetWatchedObject() == NULL);
429 DCHECK(chromoting_channel_.get() == NULL); 476 DCHECK(chromoting_channel_.get() == NULL);
430 477
431 timer_.Stop(); 478 timer_.Stop();
432 launch_backoff_ = base::TimeDelta(); 479 launch_backoff_ = base::TimeDelta();
433 state_ = StateDetached; 480 state_ = StateDetached;
434 break; 481 break;
435 482
436 case StateAttached: 483 case StateAttached:
437 DCHECK(!timer_.IsRunning()); 484 DCHECK(!timer_.IsRunning());
438 DCHECK(process_.handle() != NULL); 485 DCHECK(process_.handle() != NULL);
439 DCHECK(process_watcher_.GetWatchedObject() != NULL); 486 DCHECK(process_watcher_.GetWatchedObject() != NULL);
440 DCHECK(chromoting_channel_.get() != NULL); 487 DCHECK(chromoting_channel_.get() != NULL);
441 488
442 process_watcher_.StopWatching(); 489 process_watcher_.StopWatching();
443 process_.Terminate(0); 490 process_.Terminate(0);
444 process_.Close(); 491 process_.Close();
445 chromoting_channel_.reset(); 492 chromoting_channel_.reset();
446 state_ = StateDetached; 493 state_ = StateDetached;
447 break; 494 break;
448 } 495 }
449 } 496 }
450 497
451 } // namespace remoting 498 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698