Index: remoting/host/worker_process_launcher.cc |
diff --git a/remoting/host/worker_process_launcher.cc b/remoting/host/worker_process_launcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0b008dd96f050189abb0964d2d539da05f5cf27f |
--- /dev/null |
+++ b/remoting/host/worker_process_launcher.cc |
@@ -0,0 +1,122 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "remoting/host/worker_process_launcher.h" |
+ |
+#include <limits> |
+ |
+#include "base/logging.h" |
+#include "base/process_util.h" |
+#include "base/rand_util.h" |
+#include "base/stringprintf.h" |
+#include "base/threading/thread.h" |
+#include "base/utf_string_conversions.h" |
+#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_message.h" |
+#include "ipc/ipc_message_macros.h" |
+ |
+namespace remoting { |
+ |
+WorkerProcessLauncherWin::WorkerProcessLauncherWin( |
+ scoped_refptr<base::MessageLoopProxy> ipc_message_loop) |
+ : ipc_message_loop_(ipc_message_loop), |
+ listener_(NULL) { |
+} |
+ |
+WorkerProcessLauncherWin::~WorkerProcessLauncherWin() { |
+ Stop(); |
+} |
+ |
+bool WorkerProcessLauncherWin::Start( |
+ IPC::Channel::Listener* listener, |
+ const CreateChannelHandleCallback& create_channel_handle, |
+ const LaunchWorkerCallback& launch_worker) { |
+ DCHECK(ipc_channel_.get() == NULL); |
+ DCHECK(listener_ == NULL); |
+ DCHECK(process_.handle() == NULL); |
+ DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ |
+ std::string channel_name = GenerateRandomChannelId(); |
+ |
+ // Create the IPC channel. Details of channel handle creation are offloaded to |
+ // the callback. |
+ IPC::ChannelHandle channel_handle; |
+ if (create_channel_handle.Run(channel_name, &channel_handle)) { |
+ ipc_channel_.reset(new IPC::ChannelProxy(channel_handle, |
+ IPC::Channel::MODE_SERVER, |
+ this, |
+ ipc_message_loop_)); |
+ |
+ // Launch the process and attach an object watcher to the returned process |
+ // handle so that we get notified if the process terminates. |
+ if (launch_worker.Run(channel_name, &process_)) { |
+ if (process_watcher_.StartWatching(get_process().handle(), this)) { |
+ listener_ = listener; |
+ return true; |
+ } |
+ |
+ process_.Terminate(0); |
+ process_.Close(); |
+ } |
+ |
+ ipc_channel_.reset(); |
+ } |
+ |
+ return false; |
+} |
+ |
+void WorkerProcessLauncherWin::Stop() { |
+ ipc_channel_.reset(); |
+ listener_ = NULL; |
+ process_watcher_.StopWatching(); |
+ process_.Terminate(0); |
+ process_.Close(); |
+} |
+ |
+void WorkerProcessLauncherWin::Send(IPC::Message* message) { |
+ ipc_channel_->Send(message); |
+} |
+ |
+void WorkerProcessLauncherWin::OnObjectSignaled(HANDLE object) { |
+ DCHECK(process_watcher_.GetWatchedObject() == NULL); |
+ |
+ if (listener_) { |
+ listener_->OnChannelError(); |
+ Stop(); |
+ } |
+} |
+ |
+bool WorkerProcessLauncherWin::OnMessageReceived(const IPC::Message& message) { |
+ DCHECK(ipc_channel_.get() != NULL); |
+ DCHECK(process_.handle() != NULL); |
+ |
+ return listener_->OnMessageReceived(message); |
+} |
+ |
+void WorkerProcessLauncherWin::OnChannelConnected(int32 peer_pid) { |
+ DCHECK(ipc_channel_.get() != NULL); |
+ DCHECK(process_.handle() != NULL); |
+ |
+ listener_->OnChannelConnected(peer_pid); |
+} |
+ |
+void WorkerProcessLauncherWin::OnChannelError() { |
+ DCHECK(ipc_channel_.get() != NULL); |
+ |
+ listener_->OnChannelError(); |
+ Stop(); |
+} |
+ |
+// N.B. Stolen from src/content/common/child_process_host_impl.cc |
+std::string WorkerProcessLauncherWin::GenerateRandomChannelId() { |
+ return base::StringPrintf("%d.%p.%d", |
+ base::GetCurrentProcId(), this, |
Wez
2012/03/27 16:45:45
Do we really want to include the in-memory address
|
+ base::RandInt(0, std::numeric_limits<int>::max())); |
+} |
+ |
+base::Process& WorkerProcessLauncherWin::get_process() { |
Wez
2012/03/27 16:45:45
nit: Prefer to keep methods defined in the order t
|
+ return process_; |
+} |
+ |
+} // namespace remoting |