Index: remoting/host/win/worker_process_launcher.cc |
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc |
index b06b4a39813fb99382aa80d0fe005389ae003a4e..e8b698ac5d9fe0dee6a1f2c7176704ee6c0445d2 100644 |
--- a/remoting/host/win/worker_process_launcher.cc |
+++ b/remoting/host/win/worker_process_launcher.cc |
@@ -4,39 +4,19 @@ |
#include "remoting/host/win/worker_process_launcher.h" |
-#include <sddl.h> |
-#include <limits> |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
#include "base/logging.h" |
#include "base/single_thread_task_runner.h" |
-#include "base/process_util.h" |
-#include "base/rand_util.h" |
-#include "base/stringprintf.h" |
#include "base/time.h" |
#include "base/timer.h" |
-#include "base/utf_string_conversions.h" |
#include "base/win/object_watcher.h" |
-#include "base/win/scoped_handle.h" |
-#include "ipc/ipc_channel.h" |
-#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_listener.h" |
#include "ipc/ipc_message.h" |
#include "net/base/backoff_entry.h" |
#include "remoting/host/host_exit_codes.h" |
#include "remoting/host/worker_process_ipc_delegate.h" |
-using base::win::ScopedHandle; |
using base::TimeDelta; |
- |
-// Match the pipe name prefix used by Chrome IPC channels so that the client |
-// could use Chrome IPC APIs instead of connecting manually. |
-const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome."; |
- |
-// The minimum and maximum delays between attempts to inject host process into |
-// a session. |
-const int kMaxLaunchDelaySeconds = 60; |
-const int kMinLaunchDelaySeconds = 1; |
+using base::win::ScopedHandle; |
const net::BackoffEntry::Policy kDefaultBackoffPolicy = { |
// Number of initial errors (in sequence) to ignore before applying |
@@ -83,13 +63,10 @@ class WorkerProcessLauncher::Core |
// |
// The caller should call all the methods on this class on |
// the |caller_task_runner| thread. Methods of both delegate interfaces are |
- // called on the |caller_task_runner| thread as well. |io_task_runner| is used |
- // to perform background IPC I/O. |
+ // called on the |caller_task_runner| thread as well. |
Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
- WorkerProcessIpcDelegate* worker_delegate, |
- const std::string& pipe_security_descriptor); |
+ WorkerProcessIpcDelegate* worker_delegate); |
// Launches the worker process. |
void Start(); |
@@ -115,20 +92,12 @@ class WorkerProcessLauncher::Core |
friend class base::RefCountedThreadSafe<Core>; |
virtual ~Core(); |
- // Creates the server end of the Chromoting IPC channel. |
- bool CreatePipeForIpcChannel(const std::string& channel_name, |
- const std::string& pipe_security_descriptor, |
- base::win::ScopedHandle* pipe_out); |
- |
- // Generates random channel ID. |
- std::string GenerateRandomChannelId(); |
- |
// Attempts to launch the worker process. Schedules next launch attempt if |
// creation of the process fails. |
void LaunchWorker(); |
- // Records a successfull launch attempt. |
- void RecordSuccessfullLaunch(); |
+ // Records a successful launch attempt. |
+ void RecordSuccessfulLaunch(); |
// Stops the worker process asynchronously and schedules next launch attempt |
// unless Stop() has been called already. |
@@ -137,17 +106,14 @@ class WorkerProcessLauncher::Core |
// All public methods are called on the |caller_task_runner| thread. |
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
- // The task runner is used perform background IPC I/O. |
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
- |
// Implements specifics of launching a worker process. |
scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; |
// Handles IPC messages sent by the worker process. |
WorkerProcessIpcDelegate* worker_delegate_; |
- // The IPC channel connecting to the launched process. |
- scoped_ptr<IPC::ChannelProxy> ipc_channel_; |
+ // True if IPC messages should be passed to |worker_delegate_|. |
+ bool ipc_enabled_; |
// The timer used to delay termination of the process in the case of an IPC |
// error. |
@@ -167,13 +133,7 @@ class WorkerProcessLauncher::Core |
// A waiting handle that becomes signalled once the launched process has |
// been terminated. |
- base::win::ScopedHandle process_exit_event_; |
- |
- // The server end of the pipe. |
- base::win::ScopedHandle pipe_; |
- |
- // The security descriptor (as SDDL) of the server end of the pipe. |
- std::string pipe_security_descriptor_; |
+ ScopedHandle process_exit_event_; |
// Self reference to keep the object alive while the worker process is being |
// terminated. |
@@ -190,16 +150,13 @@ WorkerProcessLauncher::Delegate::~Delegate() { |
WorkerProcessLauncher::Core::Core( |
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
- WorkerProcessIpcDelegate* worker_delegate, |
- const std::string& pipe_security_descriptor) |
+ WorkerProcessIpcDelegate* worker_delegate) |
: caller_task_runner_(caller_task_runner), |
- io_task_runner_(io_task_runner), |
launcher_delegate_(launcher_delegate.Pass()), |
worker_delegate_(worker_delegate), |
+ ipc_enabled_(false), |
launch_backoff_(&kDefaultBackoffPolicy), |
- pipe_security_descriptor_(pipe_security_descriptor), |
stopping_(false) { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
@@ -229,11 +186,7 @@ void WorkerProcessLauncher::Core::Stop() { |
void WorkerProcessLauncher::Core::Send(IPC::Message* message) { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
- if (ipc_channel_.get()) { |
- ipc_channel_->Send(message); |
- } else { |
- delete message; |
- } |
+ launcher_delegate_->Send(message); |
} |
void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { |
@@ -246,14 +199,15 @@ void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { |
bool WorkerProcessLauncher::Core::OnMessageReceived( |
const IPC::Message& message) { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
- DCHECK(ipc_channel_.get() != NULL); |
+ |
+ if (!ipc_enabled_) |
+ return false; |
return worker_delegate_->OnMessageReceived(message); |
} |
void WorkerProcessLauncher::Core::OnChannelConnected(int32 peer_pid) { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
- DCHECK(ipc_channel_.get() != NULL); |
// |peer_pid| is send by the client and cannot be trusted. |
// GetNamedPipeClientProcessId() is not available on XP. The pipe's security |
@@ -263,12 +217,12 @@ void WorkerProcessLauncher::Core::OnChannelConnected(int32 peer_pid) { |
// If we'd like to be able to launch low-privileged workers and let them |
// connect back, the pipe handle should be passed to the worker instead of |
// the pipe name. |
- worker_delegate_->OnChannelConnected(); |
+ if (ipc_enabled_) |
+ worker_delegate_->OnChannelConnected(); |
} |
void WorkerProcessLauncher::Core::OnChannelError() { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
- DCHECK(ipc_channel_.get() != NULL); |
// Schedule a delayed termination of the worker process. Usually, the pipe is |
// disconnected when the worker process is about to exit. Waiting a little bit |
@@ -283,103 +237,34 @@ WorkerProcessLauncher::Core::~Core() { |
DCHECK(stopping_); |
} |
-// Creates the server end of the Chromoting IPC channel. |
-bool WorkerProcessLauncher::Core::CreatePipeForIpcChannel( |
- const std::string& channel_name, |
- const std::string& pipe_security_descriptor, |
- ScopedHandle* pipe_out) { |
- // Create security descriptor for the channel. |
- SECURITY_ATTRIBUTES security_attributes; |
- security_attributes.nLength = sizeof(security_attributes); |
- security_attributes.bInheritHandle = FALSE; |
- |
- ULONG security_descriptor_length = 0; |
- if (!ConvertStringSecurityDescriptorToSecurityDescriptor( |
- UTF8ToUTF16(pipe_security_descriptor).c_str(), |
- SDDL_REVISION_1, |
- reinterpret_cast<PSECURITY_DESCRIPTOR*>( |
- &security_attributes.lpSecurityDescriptor), |
- &security_descriptor_length)) { |
- LOG_GETLASTERROR(ERROR) << |
- "Failed to create a security descriptor for the Chromoting IPC channel"; |
- return false; |
- } |
- |
- // Convert the channel name to the pipe name. |
- std::string pipe_name(kChromePipeNamePrefix); |
- pipe_name.append(channel_name); |
- |
- // Create the server end of the pipe. This code should match the code in |
- // IPC::Channel with exception of passing a non-default security descriptor. |
- base::win::ScopedHandle pipe; |
- pipe.Set(CreateNamedPipe( |
- UTF8ToUTF16(pipe_name).c_str(), |
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, |
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
- 1, |
- IPC::Channel::kReadBufferSize, |
- IPC::Channel::kReadBufferSize, |
- 5000, |
- &security_attributes)); |
- if (!pipe.IsValid()) { |
- LOG_GETLASTERROR(ERROR) << |
- "Failed to create the server end of the Chromoting IPC channel"; |
- LocalFree(security_attributes.lpSecurityDescriptor); |
- return false; |
- } |
- |
- LocalFree(security_attributes.lpSecurityDescriptor); |
- |
- *pipe_out = pipe.Pass(); |
- return true; |
-} |
- |
-// N.B. Copied from src/content/common/child_process_host_impl.cc |
-std::string WorkerProcessLauncher::Core::GenerateRandomChannelId() { |
- return base::StringPrintf("%d.%p.%d", |
- base::GetCurrentProcId(), this, |
- base::RandInt(0, std::numeric_limits<int>::max())); |
-} |
- |
void WorkerProcessLauncher::Core::LaunchWorker() { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
- DCHECK(ipc_channel_.get() == NULL); |
+ DCHECK(!ipc_enabled_); |
DCHECK(!launch_success_timer_->IsRunning()); |
DCHECK(!launch_timer_->IsRunning()); |
- DCHECK(!pipe_.IsValid()); |
DCHECK(!process_exit_event_.IsValid()); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
- std::string channel_name = GenerateRandomChannelId(); |
- if (CreatePipeForIpcChannel(channel_name, pipe_security_descriptor_, |
- &pipe_)) { |
- // Wrap the pipe into an IPC channel. |
- ipc_channel_.reset(new IPC::ChannelProxy( |
- IPC::ChannelHandle(pipe_), |
- IPC::Channel::MODE_SERVER, |
- this, |
- io_task_runner_)); |
- |
- // Launch the process and attach an object watcher to the returned process |
- // handle so that we get notified if the process terminates. |
- if (launcher_delegate_->LaunchProcess(channel_name, &process_exit_event_)) { |
- if (process_watcher_.StartWatching(process_exit_event_, this)) { |
- // Record a successful launch once the process has been running for at |
- // least two seconds. |
- launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), |
- this, &Core::RecordSuccessfullLaunch); |
- return; |
- } |
- |
- launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
+ // Launch the process and attach an object watcher to the returned process |
+ // handle so that we get notified if the process terminates. |
+ if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { |
+ if (process_watcher_.StartWatching(process_exit_event_, this)) { |
+ ipc_enabled_ = true; |
+ // Record a successful launch once the process has been running for at |
+ // least two seconds. |
+ launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), |
+ this, &Core::RecordSuccessfulLaunch); |
+ return; |
} |
+ |
+ launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
} |
launch_backoff_.InformOfRequest(false); |
StopWorker(); |
} |
-void WorkerProcessLauncher::Core::RecordSuccessfullLaunch() { |
+void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { |
DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
launch_backoff_.InformOfRequest(true); |
@@ -397,8 +282,8 @@ void WorkerProcessLauncher::Core::StopWorker() { |
// Keep |this| alive until the worker process is terminated. |
self_ = this; |
- ipc_channel_.reset(); |
- pipe_.Close(); |
+ // Ignore any remaining IPC messages. |
+ ipc_enabled_ = false; |
// Kill the process if it has been started already. |
if (process_watcher_.GetWatchedObject() != NULL) { |
@@ -406,12 +291,9 @@ void WorkerProcessLauncher::Core::StopWorker() { |
return; |
} |
- ipc_error_timer_->Stop(); |
- |
- DCHECK(ipc_channel_.get() == NULL); |
- DCHECK(!pipe_.IsValid()); |
DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ ipc_error_timer_->Stop(); |
process_exit_event_.Close(); |
// Do not relaunch the worker process if the caller has asked us to stop. |
@@ -443,12 +325,10 @@ void WorkerProcessLauncher::Core::StopWorker() { |
WorkerProcessLauncher::WorkerProcessLauncher( |
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
scoped_ptr<Delegate> launcher_delegate, |
- WorkerProcessIpcDelegate* worker_delegate, |
- const std::string& pipe_security_descriptor) { |
- core_ = new Core(caller_task_runner, io_task_runner, launcher_delegate.Pass(), |
- worker_delegate, pipe_security_descriptor); |
+ WorkerProcessIpcDelegate* worker_delegate) { |
+ core_ = new Core(caller_task_runner, launcher_delegate.Pass(), |
+ worker_delegate); |
core_->Start(); |
} |