summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-02 20:24:49 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-02 20:24:49 +0000
commit4cb4310995f3b92adceb1e44b792726f7fc8249c (patch)
tree1b8217ee615f97dee3e42aa5794488fb6e31f058
parent9d43955551544e2954c4e085c8b34c866543f38e (diff)
downloadchromium_src-4cb4310995f3b92adceb1e44b792726f7fc8249c.zip
chromium_src-4cb4310995f3b92adceb1e44b792726f7fc8249c.tar.gz
chromium_src-4cb4310995f3b92adceb1e44b792726f7fc8249c.tar.bz2
Don't make classes derive from ChildProcessHost, and instead have them use it through composition. This cleans up the code and makes it easier to understand (as well as more closely conform to the Google C++ style guide). It also makes it possible to add an interface around ChildProcessHost in a future change.
BUG=98716 Review URL: http://codereview.chromium.org/8774040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112769 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc1
-rw-r--r--chrome/browser/nacl_host/nacl_broker_host_win.cc6
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.cc54
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.h3
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/service/service_child_process_host.cc45
-rw-r--r--chrome/service/service_child_process_host.h40
-rw-r--r--chrome/service/service_utility_process_host.cc56
-rw-r--r--chrome/service/service_utility_process_host.h36
-rw-r--r--content/browser/browser_child_process_host.cc32
-rw-r--r--content/browser/browser_child_process_host.h30
-rw-r--r--content/browser/gpu/gpu_process_host.cc58
-rw-r--r--content/browser/gpu/gpu_process_host.h2
-rw-r--r--content/browser/plugin_data_remover_impl.cc1
-rw-r--r--content/browser/plugin_loader_posix.cc1
-rw-r--r--content/browser/plugin_process_host.cc21
-rw-r--r--content/browser/plugin_process_host.h6
-rw-r--r--content/browser/ppapi_plugin_process_host.cc14
-rw-r--r--content/browser/ppapi_plugin_process_host.h1
-rw-r--r--content/browser/renderer_host/render_message_filter.cc3
-rw-r--r--content/browser/utility_process_host.cc16
-rw-r--r--content/browser/utility_process_host.h1
-rw-r--r--content/browser/worker_host/worker_process_host.cc33
-rw-r--r--content/common/child_process_host.cc107
-rw-r--r--content/common/child_process_host.h72
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/public/common/child_process_host_delegate.h36
27 files changed, 308 insertions, 370 deletions
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index e4d5776..c2aa4ec 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -117,6 +117,7 @@
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/interstitial_page.h"
+#include "content/common/child_process_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/common_param_traits.h"
diff --git a/chrome/browser/nacl_host/nacl_broker_host_win.cc b/chrome/browser/nacl_host/nacl_broker_host_win.cc
index 8bd6077..0c05a8d 100644
--- a/chrome/browser/nacl_host/nacl_broker_host_win.cc
+++ b/chrome/browser/nacl_host/nacl_broker_host_win.cc
@@ -14,6 +14,7 @@
#include "chrome/common/logging_chrome.h"
#include "chrome/common/nacl_cmd_line.h"
#include "chrome/common/nacl_messages.h"
+#include "content/common/child_process_host.h"
NaClBrokerHost::NaClBrokerHost()
: BrowserChildProcessHost(content::PROCESS_TYPE_NACL_BROKER),
@@ -25,7 +26,7 @@ NaClBrokerHost::~NaClBrokerHost() {
bool NaClBrokerHost::Init() {
// Create the channel that will be used for communicating with the broker.
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
// Create the path to the nacl broker/loader executable.
@@ -39,7 +40,8 @@ bool NaClBrokerHost::Init() {
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kNaClBrokerProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
if (logging::DialogsAreSuppressed())
cmd_line->AppendSwitch(switches::kNoErrorDialogs);
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index c84f416..46a030c 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -23,6 +23,7 @@
#include "chrome/common/nacl_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
+#include "content/common/child_process_host.h"
#include "ipc/ipc_switches.h"
#include "native_client/src/shared/imc/nacl_imc.h"
@@ -116,6 +117,21 @@ NaClProcessHost::NaClProcessHost(const std::wstring& url)
}
NaClProcessHost::~NaClProcessHost() {
+ int exit_code;
+ GetChildTerminationStatus(&exit_code);
+ std::string message =
+ base::StringPrintf("NaCl process exited with status %i (0x%x)",
+ exit_code, exit_code);
+ if (exit_code == 0) {
+ LOG(INFO) << message;
+ } else {
+ LOG(ERROR) << message;
+ }
+
+#if defined(OS_WIN)
+ NaClBrokerService::GetInstance()->OnLoaderDied();
+#endif
+
for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) {
if (nacl::Close(internal_->sockets_for_renderer[i]) != 0) {
LOG(ERROR) << "nacl::Close() failed";
@@ -212,7 +228,7 @@ bool NaClProcessHost::Launch(
}
bool NaClProcessHost::LaunchSelLdr() {
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
CommandLine::StringType nacl_loader_prefix;
@@ -230,14 +246,15 @@ bool NaClProcessHost::LaunchSelLdr() {
// to accomodate this request will exist in the child process' address
// space. Disable PIE for NaCl processes. See http://crbug.com/90221 and
// http://code.google.com/p/nativeclient/issues/detail?id=2043.
- int flags = CHILD_NO_PIE;
+ int flags = ChildProcessHost::CHILD_NO_PIE;
#elif defined(OS_LINUX)
- int flags = nacl_loader_prefix.empty() ? CHILD_ALLOW_SELF : CHILD_NORMAL;
+ int flags = nacl_loader_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
+ ChildProcessHost::CHILD_NORMAL;
#else
- int flags = CHILD_NORMAL;
+ int flags = ChildProcessHost::CHILD_NORMAL;
#endif
- FilePath exe_path = GetChildPath(flags);
+ FilePath exe_path = ChildProcessHost::GetChildPath(flags);
if (exe_path.empty())
return false;
@@ -246,7 +263,8 @@ bool NaClProcessHost::LaunchSelLdr() {
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kNaClLoaderProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
if (logging::DialogsAreSuppressed())
cmd_line->AppendSwitch(switches::kNoErrorDialogs);
@@ -257,7 +275,7 @@ bool NaClProcessHost::LaunchSelLdr() {
#if defined(OS_WIN)
if (RunningOnWOW64()) {
return NaClBrokerService::GetInstance()->LaunchLoader(
- this, ASCIIToWide(channel_id()));
+ this, ASCIIToWide(child_process_host()->channel_id()));
} else {
BrowserChildProcessHost::Launch(FilePath(), cmd_line);
}
@@ -282,24 +300,6 @@ base::TerminationStatus NaClProcessHost::GetChildTerminationStatus(
return BrowserChildProcessHost::GetChildTerminationStatus(exit_code);
}
-void NaClProcessHost::OnChildDied() {
- int exit_code;
- GetChildTerminationStatus(&exit_code);
- std::string message =
- base::StringPrintf("NaCl process exited with status %i (0x%x)",
- exit_code, exit_code);
- if (exit_code == 0) {
- LOG(INFO) << message;
- } else {
- LOG(ERROR) << message;
- }
-
-#if defined(OS_WIN)
- NaClBrokerService::GetInstance()->OnLoaderDied();
-#endif
- BrowserChildProcessHost::OnChildDied();
-}
-
// This only ever runs on the BrowserThread::FILE thread.
// If multiple tasks are posted, the later ones are no-ops.
void NaClBrowser::OpenIrtLibraryFile() {
@@ -519,7 +519,3 @@ bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
NOTREACHED() << "Invalid message with type = " << msg.type();
return false;
}
-
-bool NaClProcessHost::CanShutdown() {
- return true;
-}
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index 1ccb0f8..c2d8d8f 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -43,7 +43,6 @@ class NaClProcessHost : public BrowserChildProcessHost {
protected:
virtual base::TerminationStatus GetChildTerminationStatus(
int* exit_code) OVERRIDE;
- virtual void OnChildDied() OVERRIDE;
private:
// Internal class that holds the nacl::Handle objecs so that
@@ -59,8 +58,6 @@ class NaClProcessHost : public BrowserChildProcessHost {
void IrtReady();
void SendStart(base::PlatformFile irt_file);
- virtual bool CanShutdown() OVERRIDE;
-
private:
// The ChromeRenderMessageFilter that requested this NaCl process. We use
// this for sending the reply once the process has started.
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 854a235..f8d1793 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -604,8 +604,6 @@
'sources': [
'service/chrome_service_application_mac.h',
'service/chrome_service_application_mac.mm',
- 'service/service_child_process_host.cc',
- 'service/service_child_process_host.h',
'service/service_ipc_server.cc',
'service/service_ipc_server.h',
'service/service_main.cc',
diff --git a/chrome/service/service_child_process_host.cc b/chrome/service/service_child_process_host.cc
deleted file mode 100644
index 234b899..0000000
--- a/chrome/service/service_child_process_host.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2011 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 "chrome/service/service_child_process_host.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/process_util.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/public/common/result_codes.h"
-
-#if defined(OS_WIN)
-#include "base/file_path.h"
-#include "content/common/sandbox_policy.h"
-#endif // defined(OS_WIN)
-
-ServiceChildProcessHost::ServiceChildProcessHost()
- : handle_(base::kNullProcessHandle) {
-}
-
-ServiceChildProcessHost::~ServiceChildProcessHost() {
- // We need to kill the child process when the host dies.
- base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false);
-}
-
-bool ServiceChildProcessHost::Launch(CommandLine* cmd_line,
- bool no_sandbox,
- const FilePath& exposed_dir) {
-#if !defined(OS_WIN)
- // TODO(sanjeevr): Implement for non-Windows OSes.
- NOTIMPLEMENTED();
- return false;
-#else // !defined(OS_WIN)
-
- if (no_sandbox) {
- base::ProcessHandle process = base::kNullProcessHandle;
- cmd_line->AppendSwitch(switches::kNoSandbox);
- base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
- } else {
- handle_ = sandbox::StartProcessWithAccess(cmd_line, exposed_dir);
- }
- return (handle_ != base::kNullProcessHandle);
-#endif // !defined(OS_WIN)
-}
diff --git a/chrome/service/service_child_process_host.h b/chrome/service/service_child_process_host.h
deleted file mode 100644
index 44337be..0000000
--- a/chrome/service/service_child_process_host.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
-#define CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
-#pragma once
-
-#include "base/process.h"
-#include "content/common/child_process_host.h"
-
-class CommandLine;
-
-// Plugins/workers and other child processes that live on the IO thread should
-// derive from this class.
-//
-class ServiceChildProcessHost : public ChildProcessHost {
- public:
- virtual ~ServiceChildProcessHost();
-
- protected:
- ServiceChildProcessHost();
-
- // Derived classes call this to launch the child process synchronously.
- // TODO(sanjeevr): Determine whether we need to make the launch asynchronous.
- // |exposed_dir| is the path to tbe exposed to the sandbox. This is ignored
- // if |no_sandbox| is true.
- bool Launch(CommandLine* cmd_line,
- bool no_sandbox,
- const FilePath& exposed_dir);
-
- base::ProcessHandle handle() const { return handle_; }
-
- private:
- base::ProcessHandle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceChildProcessHost);
-};
-
-#endif // CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index 8352526..d82007a 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -7,31 +7,41 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/logging.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
+#include "base/process_util.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_utility_messages.h"
+#include "content/common/child_process_host.h"
+#include "content/public/common/result_codes.h"
#include "ipc/ipc_switches.h"
#include "printing/page_range.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/rect.h"
#if defined(OS_WIN)
+#include "base/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_handle.h"
+#include "content/common/sandbox_policy.h"
#include "printing/emf_win.h"
#endif
ServiceUtilityProcessHost::ServiceUtilityProcessHost(
Client* client, base::MessageLoopProxy* client_message_loop_proxy)
- : client_(client),
+ : handle_(base::kNullProcessHandle),
+ client_(client),
client_message_loop_proxy_(client_message_loop_proxy),
waiting_for_reply_(false) {
+ child_process_host_.reset(new ChildProcessHost(this));
}
ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
+ // We need to kill the child process when the host dies.
+ base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false);
}
bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
@@ -72,7 +82,7 @@ bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
if (!pdf_file_in_utility_process)
return false;
waiting_for_reply_ = true;
- return Send(
+ return child_process_host_->Send(
new ChromeUtilityMsg_RenderPDFPagesToMetafile(
pdf_file_in_utility_process,
metafile_path_,
@@ -87,12 +97,13 @@ bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
if (!StartProcess(true, exposed_path))
return false;
waiting_for_reply_ = true;
- return Send(new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
+ return child_process_host_->Send(
+ new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
}
bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox,
const FilePath& exposed_dir) {
- if (!CreateChannel())
+ if (!child_process_host_->CreateChannel())
return false;
FilePath exe_path = GetUtilityProcessCmd();
@@ -103,34 +114,57 @@ bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox,
CommandLine cmd_line(exe_path);
cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess);
- cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line.AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host_->channel_id());
cmd_line.AppendSwitch(switches::kLang);
return Launch(&cmd_line, no_sandbox, exposed_dir);
}
+bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line,
+ bool no_sandbox,
+ const FilePath& exposed_dir) {
+#if !defined(OS_WIN)
+ // TODO(sanjeevr): Implement for non-Windows OSes.
+ NOTIMPLEMENTED();
+ return false;
+#else // !defined(OS_WIN)
+
+ if (no_sandbox) {
+ base::ProcessHandle process = base::kNullProcessHandle;
+ cmd_line->AppendSwitch(switches::kNoSandbox);
+ base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
+ } else {
+ handle_ = sandbox::StartProcessWithAccess(cmd_line, exposed_dir);
+ }
+ return (handle_ != base::kNullProcessHandle);
+#endif // !defined(OS_WIN)
+}
+
FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
#if defined(OS_LINUX)
- int flags = CHILD_ALLOW_SELF;
+ int flags = ChildProcessHost::CHILD_ALLOW_SELF;
#else
- int flags = CHILD_NORMAL;
+ int flags = ChildProcessHost::CHILD_NORMAL;
#endif
- return GetChildPath(flags);
+ return ChildProcessHost::GetChildPath(flags);
}
bool ServiceUtilityProcessHost::CanShutdown() {
return true;
}
-void ServiceUtilityProcessHost::OnChildDied() {
+void ServiceUtilityProcessHost::OnChildDisconnected() {
if (waiting_for_reply_) {
// If we are yet to receive a reply then notify the client that the
// child died.
client_message_loop_proxy_->PostTask(
FROM_HERE, base::Bind(&Client::OnChildDied, client_.get()));
}
- // The base class implementation will delete |this|.
- ServiceChildProcessHost::OnChildDied();
+ delete this;
+}
+
+void ServiceUtilityProcessHost::ShutdownStarted() {
}
bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h
index 49e2450..77cb2f7 100644
--- a/chrome/service/service_utility_process_host.h
+++ b/chrome/service/service_utility_process_host.h
@@ -14,11 +14,15 @@
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process.h"
#include "base/task.h"
#include "ipc/ipc_channel.h"
-#include "chrome/service/service_child_process_host.h"
+#include "content/public/common/child_process_host_delegate.h"
#include "printing/pdf_render_settings.h"
+class ChildProcessHost;
+class CommandLine;
class ScopedTempDir;
namespace base {
@@ -34,7 +38,7 @@ struct PrinterCapsAndDefaults;
// Acts as the service-side host to a utility child process. A
// utility process is a short-lived sandboxed process that is created to run
// a specific task.
-class ServiceUtilityProcessHost : public ServiceChildProcessHost {
+class ServiceUtilityProcessHost : public content::ChildProcessHostDelegate {
public:
// Consumers of ServiceUtilityProcessHost must implement this interface to
// get results back. All functions are called on the thread passed along
@@ -101,9 +105,11 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost {
// Allows this method to be overridden for tests.
virtual FilePath GetUtilityProcessCmd();
- // ChildProcessHost implementation.
+ // ChildProcessHostDelegate implementation:
virtual bool CanShutdown() OVERRIDE;
- virtual void OnChildDied() OVERRIDE;
+ virtual void OnChildDisconnected() OVERRIDE;
+ virtual void ShutdownStarted() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
private:
// Starts a process. Returns true iff it succeeded. |exposed_dir| is the
@@ -111,22 +117,26 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost {
// true.
bool StartProcess(bool no_sandbox, const FilePath& exposed_dir);
- // IPC messages:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // Called when at least one page in the specified PDF has been rendered
- // successfully into metafile_path_;
+ // Launch the child process synchronously.
+ // TODO(sanjeevr): Determine whether we need to make the launch asynchronous.
+ // |exposed_dir| is the path to tbe exposed to the sandbox. This is ignored
+ // if |no_sandbox| is true.
+ bool Launch(CommandLine* cmd_line,
+ bool no_sandbox,
+ const FilePath& exposed_dir);
+
+ base::ProcessHandle handle() const { return handle_; }
+
+ // Messages handlers:
void OnRenderPDFPagesToMetafileSucceeded(int highest_rendered_page_number);
- // Called when PDF rendering failed.
void OnRenderPDFPagesToMetafileFailed();
- // Called when the printer capabilities and defaults have been
- // retrieved successfully.
void OnGetPrinterCapsAndDefaultsSucceeded(
const std::string& printer_name,
const printing::PrinterCapsAndDefaults& caps_and_defaults);
- // Called when the printer capabilities and defaults could not be
- // retrieved successfully.
void OnGetPrinterCapsAndDefaultsFailed(const std::string& printer_name);
+ scoped_ptr<ChildProcessHost> child_process_host_;
+ base::ProcessHandle handle_;
// A pointer to our client interface, who will be informed of progress.
scoped_refptr<Client> client_;
scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy_;
diff --git a/content/browser/browser_child_process_host.cc b/content/browser/browser_child_process_host.cc
index 508dade..3e56b6e 100644
--- a/content/browser/browser_child_process_host.cc
+++ b/content/browser/browser_child_process_host.cc
@@ -17,6 +17,7 @@
#include "content/browser/profiler_message_filter.h"
#include "content/browser/renderer_host/resource_message_filter.h"
#include "content/browser/trace_message_filter.h"
+#include "content/common/child_process_host.h"
#include "content/common/plugin_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
@@ -59,10 +60,11 @@ BrowserChildProcessHost::BrowserChildProcessHost(
#endif
disconnect_was_alive_(false) {
data_.type = type;
- data_.id = GenerateChildProcessUniqueId();
+ data_.id = ChildProcessHost::GenerateChildProcessUniqueId();
- AddFilter(new TraceMessageFilter);
- AddFilter(new ProfilerMessageFilter);
+ child_process_host_.reset(new ChildProcessHost(this));
+ child_process_host_->AddFilter(new TraceMessageFilter);
+ child_process_host_->AddFilter(new ProfilerMessageFilter);
g_child_process_list.Get().push_back(this);
}
@@ -96,7 +98,7 @@ void BrowserChildProcessHost::Launch(
#elif defined(OS_POSIX)
use_zygote,
environ,
- channel()->TakeClientFileDescriptor(),
+ child_process_host()->channel()->TakeClientFileDescriptor(),
#endif
cmd_line,
&client_));
@@ -112,7 +114,7 @@ base::ProcessHandle BrowserChildProcessHost::GetChildProcessHandle() const {
void BrowserChildProcessHost::ForceShutdown() {
g_child_process_list.Get().remove(this);
- ChildProcessHost::ForceShutdown();
+ child_process_host_->ForceShutdown();
}
void BrowserChildProcessHost::SetTerminateChildOnShutdown(
@@ -132,11 +134,19 @@ base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
return child_process_->GetChildTerminationStatus(exit_code);
}
+bool BrowserChildProcessHost::OnMessageReceived(const IPC::Message& message) {
+ return false;
+}
+
void BrowserChildProcessHost::OnChannelConnected(int32 peer_pid) {
Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_CONNECTED);
}
-// The ChildProcessHost default implementation calls OnChildDied() always but at
+bool BrowserChildProcessHost::CanShutdown() {
+ return true;
+}
+
+// Normally a ChildProcessHostDelegate deletes itself from this callback, but at
// this layer and below we need to have the final child process exit code to
// properly bucket crashes vs kills. On Windows we can do this if we wait until
// the process handle is signaled; on the rest of the platforms, we schedule a
@@ -212,7 +222,7 @@ void BrowserChildProcessHost::OnChildDisconnected() {
content::PROCESS_TYPE_MAX);
// Notify in the main loop of the disconnection.
Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED);
- OnChildDied();
+ delete this;
}
// The child process handle has been signaled so the exit code is finally
@@ -226,13 +236,17 @@ void BrowserChildProcessHost::OnWaitableEventSignaled(
GetExitCodeProcess(waitable_event->Release(), &exit_code);
delete waitable_event;
if (exit_code == STILL_ACTIVE) {
- OnChildDied();
+ delete this;
} else {
BrowserChildProcessHost::OnChildDisconnected();
}
#endif
}
+bool BrowserChildProcessHost::Send(IPC::Message* message) {
+ return child_process_host_->Send(message);
+}
+
void BrowserChildProcessHost::ShutdownStarted() {
// Must remove the process from the list now, in case it gets used for a
// new instance before our watcher tells us that the process terminated.
@@ -245,7 +259,7 @@ BrowserChildProcessHost::ClientHook::ClientHook(BrowserChildProcessHost* host)
void BrowserChildProcessHost::ClientHook::OnProcessLaunched() {
if (!host_->child_process_->GetHandle()) {
- host_->OnChildDied();
+ delete host_;
return;
}
host_->data_.handle = host_->child_process_->GetHandle();
diff --git a/content/browser/browser_child_process_host.h b/content/browser/browser_child_process_host.h
index a201c30..561d84e 100644
--- a/content/browser/browser_child_process_host.h
+++ b/content/browser/browser_child_process_host.h
@@ -8,13 +8,17 @@
#include <list>
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "content/browser/child_process_launcher.h"
-#include "content/common/child_process_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/child_process_data.h"
+#include "content/public/common/child_process_host_delegate.h"
+#include "ipc/ipc_message.h"
+
+class ChildProcessHost;
namespace base {
class WaitableEvent;
@@ -26,9 +30,10 @@ class WaitableEvent;
// [Browser]RenderProcessHost is the main exception that doesn't derive from
// this class. That project lives on the UI thread.
class CONTENT_EXPORT BrowserChildProcessHost :
- public ChildProcessHost,
+ public content::ChildProcessHostDelegate,
public ChildProcessLauncher::Client,
- public base::WaitableEventWatcher::Delegate {
+ public base::WaitableEventWatcher::Delegate,
+ public IPC::Message::Sender {
public:
virtual ~BrowserChildProcessHost();
@@ -58,6 +63,9 @@ class CONTENT_EXPORT BrowserChildProcessHost :
std::list<BrowserChildProcessHost*>::iterator iterator_;
};
+ // IPC::Message::Sender override
+ virtual bool Send(IPC::Message* message) OVERRIDE;
+
const content::ChildProcessData& data() const { return data_; }
content::ProcessType type() const { return data_.type; }
const string16& name() const { return data_.name; }
@@ -102,13 +110,15 @@ class CONTENT_EXPORT BrowserChildProcessHost :
// GetExitCodeProcess()). |exit_code| may be NULL.
virtual base::TerminationStatus GetChildTerminationStatus(int* exit_code);
- // Overrides from ChildProcessHost
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ // ChildProcessHostDelegate implementation:
+ virtual bool CanShutdown() OVERRIDE;
virtual void OnChildDisconnected() OVERRIDE;
virtual void ShutdownStarted() OVERRIDE;
- // Extends the base class implementation and removes this host from
- // the host list. Calls ChildProcessHost::ForceShutdown
- virtual void ForceShutdown() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+
+ // Removes this host from the host list. Calls ChildProcessHost::ForceShutdown
+ void ForceShutdown();
// Controls whether the child process should be terminated on browser
// shutdown. Default is to always terminate.
@@ -117,6 +127,9 @@ class CONTENT_EXPORT BrowserChildProcessHost :
// Sends the given notification on the UI thread.
void Notify(int type);
+ ChildProcessHost* child_process_host() const {
+ return child_process_host_.get();
+ }
void set_name(const string16& name) { data_.name = name; }
void set_handle(base::ProcessHandle handle) { data_.handle = handle; }
@@ -133,6 +146,7 @@ class CONTENT_EXPORT BrowserChildProcessHost :
};
content::ChildProcessData data_;
+ scoped_ptr<ChildProcessHost> child_process_host_;
ClientHook client_;
scoped_ptr<ChildProcessLauncher> child_process_;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index cdaac3e..3b18d38 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -17,6 +17,7 @@
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/browser/renderer_host/render_widget_host_view.h"
+#include "content/common/child_process_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
@@ -279,6 +280,25 @@ GpuProcessHost::GpuProcessHost(int host_id)
GpuProcessHost::~GpuProcessHost() {
DCHECK(CalledOnValidThread());
+
+ SendOutstandingReplies();
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
+ DIED_FIRST_TIME + g_gpu_crash_count,
+ GPU_PROCESS_LIFETIME_EVENT_MAX);
+
+ int exit_code;
+ base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
+ status,
+ base::TERMINATION_STATUS_MAX_ENUM);
+
+ if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
+ status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode",
+ exit_code,
+ content::RESULT_CODE_LAST_CODE);
+ }
+
#if defined(OS_WIN)
if (gpu_process_)
CloseHandle(gpu_process_);
@@ -299,14 +319,15 @@ GpuProcessHost::~GpuProcessHost() {
}
bool GpuProcessHost::Init() {
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
if (in_process_) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableGpuWatchdog);
- in_process_gpu_thread_.reset(new GpuMainThread(channel_id()));
+ in_process_gpu_thread_.reset(new GpuMainThread(
+ child_process_host()->channel_id()));
base::Thread::Options options;
#if defined(OS_WIN)
@@ -337,7 +358,7 @@ void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
bool GpuProcessHost::Send(IPC::Message* msg) {
DCHECK(CalledOnValidThread());
- if (opening_channel()) {
+ if (child_process_host()->opening_channel()) {
queued_messages_.push(msg);
return true;
}
@@ -488,10 +509,6 @@ void GpuProcessHost::OnGraphicsInfoCollected(const content::GPUInfo& gpu_info) {
GpuDataManager::GetInstance()->UpdateGpuInfo(gpu_info);
}
-bool GpuProcessHost::CanShutdown() {
- return true;
-}
-
void GpuProcessHost::OnProcessLaunched() {
// Send the GPU process handle to the UI thread before it has to
// respond to any requests to establish a GPU channel. The response
@@ -513,30 +530,6 @@ void GpuProcessHost::OnProcessLaunched() {
#endif
}
-void GpuProcessHost::OnChildDied() {
- SendOutstandingReplies();
- // Located in OnChildDied because OnProcessCrashed suffers from a race
- // condition on Linux.
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
- DIED_FIRST_TIME + g_gpu_crash_count,
- GPU_PROCESS_LIFETIME_EVENT_MAX);
-
- int exit_code;
- base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
- status,
- base::TERMINATION_STATUS_MAX_ENUM);
-
- if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
- status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode",
- exit_code,
- content::RESULT_CODE_LAST_CODE);
- }
-
- ChildProcessHost::OnChildDied();
-}
-
void GpuProcessHost::OnProcessCrashed(int exit_code) {
SendOutstandingReplies();
if (++g_gpu_crash_count >= kGpuMaxCrashCount) {
@@ -575,7 +568,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
CommandLine* cmd_line = new CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
// Propagate relevant command line switches.
static const char* const kSwitchNames[] = {
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index e6ba2c0..073e8fd 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -92,9 +92,7 @@ class GpuProcessHost : public BrowserChildProcessHost,
// Post an IPC message to the UI shim's message handler on the UI thread.
void RouteOnUIThread(const IPC::Message& message);
- virtual bool CanShutdown() OVERRIDE;
virtual void OnProcessLaunched() OVERRIDE;
- virtual void OnChildDied() OVERRIDE;
virtual void OnProcessCrashed(int exit_code) OVERRIDE;
// Message handlers.
diff --git a/content/browser/plugin_data_remover_impl.cc b/content/browser/plugin_data_remover_impl.cc
index da0dbfc..38489d5 100644
--- a/content/browser/plugin_data_remover_impl.cc
+++ b/content/browser/plugin_data_remover_impl.cc
@@ -10,6 +10,7 @@
#include "base/version.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service.h"
+#include "content/common/child_process_host.h"
#include "content/common/plugin_messages.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/plugins/npapi/plugin_group.h"
diff --git a/content/browser/plugin_loader_posix.cc b/content/browser/plugin_loader_posix.cc
index 6d2be85..bc96427 100644
--- a/content/browser/plugin_loader_posix.cc
+++ b/content/browser/plugin_loader_posix.cc
@@ -8,6 +8,7 @@
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/metrics/histogram.h"
+#include "content/common/child_process_host.h"
#include "content/common/utility_messages.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/plugins/npapi/plugin_list.h"
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index 91c22c4..293072d 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -22,6 +22,7 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "content/browser/plugin_service.h"
+#include "content/common/child_process_host.h"
#include "content/common/plugin_messages.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -167,7 +168,7 @@ bool PluginProcessHost::Init(const webkit::WebPluginInfo& info,
info_ = info;
set_name(info_.name);
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
// Build command line for plugin. When we have a plugin launcher, we can't
@@ -180,14 +181,15 @@ bool PluginProcessHost::Init(const webkit::WebPluginInfo& info,
// Run the plug-in process in a mode tolerant of heap execution without
// explicit mprotect calls. Some plug-ins still rely on this quaint and
// archaic "feature." See http://crbug.com/93551.
- int flags = CHILD_ALLOW_HEAP_EXECUTION;
+ int flags = ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION;
#elif defined(OS_LINUX)
- int flags = plugin_launcher.empty() ? CHILD_ALLOW_SELF : CHILD_NORMAL;
+ int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
+ ChildProcessHost::CHILD_NORMAL;
#else
- int flags = CHILD_NORMAL;
+ int flags = ChildProcessHost::CHILD_NORMAL;
#endif
- FilePath exe_path = GetChildPath(flags);
+ FilePath exe_path = ChildProcessHost::GetChildPath(flags);
if (exe_path.empty())
return false;
@@ -233,7 +235,8 @@ bool PluginProcessHost::Init(const webkit::WebPluginInfo& info,
cmd_line->AppendSwitchASCII(switches::kLang, locale);
}
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
#if defined(OS_POSIX)
base::environment_vector env;
@@ -279,6 +282,10 @@ void PluginProcessHost::ForceShutdown() {
BrowserChildProcessHost::ForceShutdown();
}
+void PluginProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
+ child_process_host()->AddFilter(filter);
+}
+
bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg)
@@ -359,7 +366,7 @@ void PluginProcessHost::CancelPendingRequestsForResourceContext(
void PluginProcessHost::OpenChannelToPlugin(Client* client) {
Notify(content::NOTIFICATION_CHILD_INSTANCE_CREATED);
client->SetPluginInfo(info_);
- if (opening_channel()) {
+ if (child_process_host()->opening_channel()) {
// The channel is already in the process of being opened. Put
// this "open channel" request into a queue of requests that will
// be run once the channel is open.
diff --git a/content/browser/plugin_process_host.h b/content/browser/plugin_process_host.h
index b56183f..6ce5f08 100644
--- a/content/browser/plugin_process_host.h
+++ b/content/browser/plugin_process_host.h
@@ -17,6 +17,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/browser_child_process_host.h"
#include "content/common/content_export.h"
+#include "ipc/ipc_channel_proxy.h"
#include "webkit/plugins/webplugininfo.h"
#include "ui/gfx/native_widget_types.h"
@@ -69,7 +70,7 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHost {
bool Init(const webkit::WebPluginInfo& info, const std::string& locale);
// Force the plugin process to shutdown (cleanly).
- virtual void ForceShutdown() OVERRIDE;
+ void ForceShutdown();
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
@@ -109,6 +110,9 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHost {
void AddWindow(HWND window);
#endif
+ // Adds an IPC message filter. A reference will be kept to the filter.
+ void AddFilter(IPC::ChannelProxy::MessageFilter* filter);
+
private:
// Sends a message to the plugin process to request creation of a new channel
// for the given mime type.
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index 8b5faef..f4ccd33 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -11,6 +11,7 @@
#include "base/utf_string_conversions.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_message_filter.h"
+#include "content/common/child_process_host.h"
#include "content/common/child_process_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
@@ -84,7 +85,7 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreateBrokerHost(
}
void PpapiPluginProcessHost::OpenChannelToPlugin(Client* client) {
- if (opening_channel()) {
+ if (child_process_host()->opening_channel()) {
// The channel is already in the process of being opened. Put
// this "open channel" request into a queue of requests that will
// be run once the channel is open.
@@ -102,7 +103,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(net::HostResolver* host_resolver)
network_observer_(new PluginNetworkObserver(this)),
is_broker_(false),
process_id_(ChildProcessHost::GenerateChildProcessUniqueId()) {
- AddFilter(filter_.get());
+ child_process_host()->AddFilter(filter_.get());
}
PpapiPluginProcessHost::PpapiPluginProcessHost()
@@ -119,7 +120,7 @@ bool PpapiPluginProcessHost::Init(const content::PepperPluginInfo& info) {
set_name(UTF8ToUTF16(info.name));
}
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
@@ -140,7 +141,8 @@ bool PpapiPluginProcessHost::Init(const content::PepperPluginInfo& info) {
cmd_line->AppendSwitchASCII(switches::kProcessType,
is_broker_ ? switches::kPpapiBrokerProcess
: switches::kPpapiPluginProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
// These switches are forwarded to both plugin and broker pocesses.
static const char* kCommonForwardSwitches[] = {
@@ -198,10 +200,6 @@ void PpapiPluginProcessHost::RequestPluginChannel(Client* client) {
client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
}
-bool PpapiPluginProcessHost::CanShutdown() {
- return true;
-}
-
void PpapiPluginProcessHost::OnProcessLaunched() {
}
diff --git a/content/browser/ppapi_plugin_process_host.h b/content/browser/ppapi_plugin_process_host.h
index a968a27..f92aa1d 100644
--- a/content/browser/ppapi_plugin_process_host.h
+++ b/content/browser/ppapi_plugin_process_host.h
@@ -82,7 +82,6 @@ class PpapiPluginProcessHost
void RequestPluginChannel(Client* client);
- virtual bool CanShutdown() OVERRIDE;
virtual void OnProcessLaunched() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 267d1cc..f84b968 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -686,8 +686,7 @@ void RenderMessageFilter::OnCheckNotificationPermission(
void RenderMessageFilter::OnAllocateSharedMemory(
uint32 buffer_size,
base::SharedMemoryHandle* handle) {
- ChildProcessHost::OnAllocateSharedMemory(
- buffer_size, peer_handle(), handle);
+ ChildProcessHost::AllocateSharedMemory(buffer_size, peer_handle(), handle);
}
net::URLRequestContext* RenderMessageFilter::GetRequestContextForURL(
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index 65a7e70..8bc2234 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
+#include "content/common/child_process_host.h"
#include "content/common/utility_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
@@ -40,9 +41,9 @@ UtilityProcessHost::UtilityProcessHost(Client* client,
is_batch_mode_(false),
no_sandbox_(false),
#if defined(OS_LINUX)
- child_flags_(CHILD_ALLOW_SELF),
+ child_flags_(ChildProcessHost::CHILD_ALLOW_SELF),
#else
- child_flags_(CHILD_NORMAL),
+ child_flags_(ChildProcessHost::CHILD_NORMAL),
#endif
started_(false) {
}
@@ -72,7 +73,7 @@ void UtilityProcessHost::EndBatchMode() {
}
FilePath UtilityProcessHost::GetUtilityProcessCmd() {
- return GetChildPath(child_flags_);
+ return ChildProcessHost::GetChildPath(child_flags_);
}
bool UtilityProcessHost::StartProcess() {
@@ -86,7 +87,7 @@ bool UtilityProcessHost::StartProcess() {
// launches a UtilityProcessHost.
set_name(ASCIIToUTF16("utility process"));
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
FilePath exe_path = GetUtilityProcessCmd();
@@ -98,7 +99,8 @@ bool UtilityProcessHost::StartProcess() {
CommandLine* cmd_line = new CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kUtilityProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
std::string locale =
content::GetContentClient()->browser()->GetApplicationLocale();
cmd_line->AppendSwitchASCII(switches::kLang, locale);
@@ -151,7 +153,3 @@ void UtilityProcessHost::OnProcessCrashed(int exit_code) {
client_thread_id_, FROM_HERE,
base::Bind(&Client::OnProcessCrashed, client_.get(), exit_code));
}
-
-bool UtilityProcessHost::CanShutdown() {
- return true;
-}
diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
index de53610..b81d12d 100644
--- a/content/browser/utility_process_host.h
+++ b/content/browser/utility_process_host.h
@@ -84,7 +84,6 @@ class CONTENT_EXPORT UtilityProcessHost : public BrowserChildProcessHost {
// BrowserChildProcessHost:
virtual void OnProcessCrashed(int exit_code) OVERRIDE;
- virtual bool CanShutdown() OVERRIDE;
// A pointer to our client interface, who will be informed of progress.
scoped_refptr<Client> client_;
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index ba29447..68d75c9 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -31,6 +31,7 @@
#include "content/browser/worker_host/message_port_service.h"
#include "content/browser/worker_host/worker_message_filter.h"
#include "content/browser/worker_host/worker_service.h"
+#include "content/common/child_process_host.h"
#include "content/common/debug_flags.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
@@ -111,22 +112,23 @@ WorkerProcessHost::~WorkerProcessHost() {
}
bool WorkerProcessHost::Init(int render_process_id) {
- if (!CreateChannel())
+ if (!child_process_host()->CreateChannel())
return false;
#if defined(OS_LINUX)
- int flags = CHILD_ALLOW_SELF;
+ int flags = ChildProcessHost::CHILD_ALLOW_SELF;
#else
- int flags = CHILD_NORMAL;
+ int flags = ChildProcessHost::CHILD_NORMAL;
#endif
- FilePath exe_path = GetChildPath(flags);
+ FilePath exe_path = ChildProcessHost::GetChildPath(flags);
if (exe_path.empty())
return false;
CommandLine* cmd_line = new CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kWorkerProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID,
+ child_process_host()->channel_id());
std::string locale =
content::GetContentClient()->browser()->GetApplicationLocale();
cmd_line->AppendSwitchASCII(switches::kLang, locale);
@@ -237,29 +239,30 @@ void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
id(), content::PROCESS_TYPE_WORKER, resource_context_,
new URLRequestContextSelector(request_context),
resource_dispatcher_host_);
- AddFilter(resource_message_filter);
+ child_process_host()->AddFilter(resource_message_filter);
worker_message_filter_ = new WorkerMessageFilter(
render_process_id, resource_context_, resource_dispatcher_host_,
base::Bind(&WorkerService::next_worker_route_id,
base::Unretained(WorkerService::GetInstance())));
- AddFilter(worker_message_filter_);
- AddFilter(new AppCacheDispatcherHost(
+ child_process_host()->AddFilter(worker_message_filter_);
+ child_process_host()->AddFilter(new AppCacheDispatcherHost(
resource_context_->appcache_service(), id()));
- AddFilter(new FileSystemDispatcherHost(
+ child_process_host()->AddFilter(new FileSystemDispatcherHost(
request_context, resource_context_->file_system_context()));
- AddFilter(new FileUtilitiesMessageFilter(id()));
- AddFilter(new BlobMessageFilter(
+ child_process_host()->AddFilter(new FileUtilitiesMessageFilter(id()));
+ child_process_host()->AddFilter(new BlobMessageFilter(
id(), resource_context_->blob_storage_context()));
- AddFilter(new MimeRegistryMessageFilter());
- AddFilter(new DatabaseMessageFilter(
+ child_process_host()->AddFilter(new MimeRegistryMessageFilter());
+ child_process_host()->AddFilter(new DatabaseMessageFilter(
resource_context_->database_tracker()));
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
new SocketStreamDispatcherHost(
new URLRequestContextSelector(request_context), resource_context_);
- AddFilter(socket_stream_dispatcher_host);
- AddFilter(new content::WorkerDevToolsMessageFilter(id()));
+ child_process_host()->AddFilter(socket_stream_dispatcher_host);
+ child_process_host()->AddFilter(
+ new content::WorkerDevToolsMessageFilter(id()));
}
void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) {
diff --git a/content/common/child_process_host.cc b/content/common/child_process_host.cc
index fd1de4a..002e016 100644
--- a/content/common/child_process_host.cc
+++ b/content/common/child_process_host.cc
@@ -17,6 +17,7 @@
#include "base/stringprintf.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "content/common/child_process_messages.h"
+#include "content/public/common/child_process_host_delegate.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_logging.h"
@@ -73,8 +74,9 @@ FilePath TransformPathForFeature(const FilePath& path,
} // namespace
#endif // OS_MACOSX
-ChildProcessHost::ChildProcessHost()
- : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
+ChildProcessHost::ChildProcessHost(content::ChildProcessHostDelegate* delegate)
+ : delegate_(delegate),
+ peer_handle_(base::kNullProcessHandle),
opening_channel_(false) {
#if defined(OS_WIN)
AddFilter(new FontCacheDispatcher());
@@ -86,7 +88,8 @@ ChildProcessHost::~ChildProcessHost() {
filters_[i]->OnChannelClosing();
filters_[i]->OnFilterRemoved();
}
- listener_.Shutdown();
+
+ base::CloseProcessHandle(peer_handle_);
}
void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
@@ -147,7 +150,7 @@ void ChildProcessHost::ForceShutdown() {
bool ChildProcessHost::CreateChannel() {
channel_id_ = GenerateRandomChannelID(this);
channel_.reset(new IPC::Channel(
- channel_id_, IPC::Channel::MODE_SERVER, &listener_));
+ channel_id_, IPC::Channel::MODE_SERVER, this));
if (!channel_->Connect())
return false;
@@ -167,16 +170,6 @@ bool ChildProcessHost::CreateChannel() {
return true;
}
-bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) {
- return false;
-}
-
-void ChildProcessHost::OnChannelConnected(int32 peer_pid) {
-}
-
-void ChildProcessHost::OnChannelError() {
-}
-
bool ChildProcessHost::Send(IPC::Message* message) {
if (!channel_.get()) {
delete message;
@@ -185,7 +178,7 @@ bool ChildProcessHost::Send(IPC::Message* message) {
return channel_->Send(message);
}
-void ChildProcessHost::OnAllocateSharedMemory(
+void ChildProcessHost::AllocateSharedMemory(
uint32 buffer_size, base::ProcessHandle child_process_handle,
base::SharedMemoryHandle* shared_memory_handle) {
base::SharedMemory shared_buf;
@@ -215,35 +208,7 @@ int ChildProcessHost::GenerateChildProcessUniqueId() {
return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1);
}
-
-void ChildProcessHost::OnChildDied() {
- delete this;
-}
-
-void ChildProcessHost::OnChildDisconnected() {
- OnChildDied();
-}
-
-void ChildProcessHost::ShutdownStarted() {
-}
-
-ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
- : host_(host), peer_handle_(base::kNullProcessHandle) {
-}
-
-ChildProcessHost::ListenerHook::~ListenerHook() {
- base::CloseProcessHandle(peer_handle_);
-}
-
-void ChildProcessHost::ListenerHook::Shutdown() {
- host_ = NULL;
-}
-
-bool ChildProcessHost::ListenerHook::OnMessageReceived(
- const IPC::Message& msg) {
- if (!host_)
- return true;
-
+bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) {
#ifdef IPC_MESSAGE_LOG_ENABLED
IPC::Logging* logger = IPC::Logging::GetInstance();
if (msg.type() == IPC_LOGGING_ID) {
@@ -256,72 +221,62 @@ bool ChildProcessHost::ListenerHook::OnMessageReceived(
#endif
bool handled = false;
- for (size_t i = 0; i < host_->filters_.size(); ++i) {
- if (host_->filters_[i]->OnMessageReceived(msg)) {
+ for (size_t i = 0; i < filters_.size(); ++i) {
+ if (filters_[i]->OnMessageReceived(msg)) {
handled = true;
break;
}
}
if (!handled) {
- bool msg_is_good = false;
handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(ListenerHook, msg, msg_is_good)
+ IPC_BEGIN_MESSAGE_MAP(ChildProcessHost, msg)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
OnShutdownRequest)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP_EX()
+ IPC_END_MESSAGE_MAP()
if (!handled)
- handled = host_->OnMessageReceived(msg);
+ handled = delegate_->OnMessageReceived(msg);
}
#ifdef IPC_MESSAGE_LOG_ENABLED
if (logger->Enabled())
- logger->OnPostDispatchMessage(msg, host_->channel_id_);
+ logger->OnPostDispatchMessage(msg, channel_id_);
#endif
return handled;
}
-void ChildProcessHost::ListenerHook::OnChannelConnected(int32 peer_pid) {
- if (!host_)
- return;
+void ChildProcessHost::OnChannelConnected(int32 peer_pid) {
if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) {
NOTREACHED();
}
- host_->opening_channel_ = false;
- host_->OnChannelConnected(peer_pid);
- for (size_t i = 0; i < host_->filters_.size(); ++i)
- host_->filters_[i]->OnChannelConnected(peer_pid);
+ opening_channel_ = false;
+ delegate_->OnChannelConnected(peer_pid);
+ for (size_t i = 0; i < filters_.size(); ++i)
+ filters_[i]->OnChannelConnected(peer_pid);
}
-void ChildProcessHost::ListenerHook::OnChannelError() {
- if (!host_)
- return;
- host_->opening_channel_ = false;
- host_->OnChannelError();
+void ChildProcessHost::OnChannelError() {
+ opening_channel_ = false;
+ delegate_->OnChannelError();
- for (size_t i = 0; i < host_->filters_.size(); ++i)
- host_->filters_[i]->OnChannelError();
+ for (size_t i = 0; i < filters_.size(); ++i)
+ filters_[i]->OnChannelError();
// This will delete host_, which will also destroy this!
- host_->OnChildDisconnected();
-}
-
-bool ChildProcessHost::ListenerHook::Send(IPC::Message* message) {
- return host_->Send(message);
+ delegate_->OnChildDisconnected();
}
-void ChildProcessHost::ListenerHook::OnAllocateSharedMemory(
+void ChildProcessHost::OnAllocateSharedMemory(
uint32 buffer_size,
base::SharedMemoryHandle* handle) {
- ChildProcessHost::OnAllocateSharedMemory(
- buffer_size, peer_handle_, handle);
+ AllocateSharedMemory(buffer_size, peer_handle_, handle);
}
-void ChildProcessHost::ListenerHook::OnShutdownRequest() {
- if (host_->CanShutdown())
- host_->Send(new ChildProcessMsg_Shutdown());
+void ChildProcessHost::OnShutdownRequest() {
+ if (delegate_->CanShutdown())
+ Send(new ChildProcessMsg_Shutdown());
}
diff --git a/content/common/child_process_host.h b/content/common/child_process_host.h
index be73fa1..7f044f4 100644
--- a/content/common/child_process_host.h
+++ b/content/common/child_process_host.h
@@ -21,12 +21,12 @@
class FilePath;
-namespace IPC {
-class Message;
+namespace content {
+class ChildProcessHostDelegate;
}
// Provides common functionality for hosting a child process and processing IPC
-// messages between the host and the child process. Subclasses are responsible
+// messages between the host and the child process. Users are responsible
// for the actual launching and terminating of the child processes.
class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
public IPC::Message::Sender {
@@ -80,6 +80,8 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
// On failure, returns an empty FilePath.
static FilePath GetChildPath(int flags);
+ explicit ChildProcessHost(content::ChildProcessHostDelegate* delegate);
+
// IPC::Message::Sender implementation.
virtual bool Send(IPC::Message* message) OVERRIDE;
@@ -87,7 +89,7 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
void AddFilter(IPC::ChannelProxy::MessageFilter* filter);
// Public and static for reuse by RenderMessageFilter.
- static void OnAllocateSharedMemory(
+ static void AllocateSharedMemory(
uint32 buffer_size, base::ProcessHandle child_process,
base::SharedMemoryHandle* handle);
@@ -104,68 +106,30 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
// but normally this will be used on the IO thread.
static int GenerateChildProcessUniqueId();
- protected:
- ChildProcessHost();
-
- // Derived classes return true if it's ok to shut down the child process.
- virtual bool CanShutdown() = 0;
-
// Send the shutdown message to the child process.
// Does not check if CanShutdown is true.
- virtual void ForceShutdown();
+ void ForceShutdown();
// Creates the IPC channel. Returns true iff it succeeded.
- virtual bool CreateChannel();
-
- // IPC::Channel::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool CreateChannel();
bool opening_channel() { return opening_channel_; }
const std::string& channel_id() { return channel_id_; }
IPC::Channel* channel() { return channel_.get(); }
- // Called when the child process goes away. See OnChildDisconnected().
- virtual void OnChildDied();
-
- // Called when the child process unexpected closes the IPC channel. The
- // default action is to call OnChildDied(). Subclasses might want to override
- // this behavior.
- virtual void OnChildDisconnected();
-
- // Notifies the derived class that we told the child process to kill itself.
- virtual void ShutdownStarted();
-
private:
- // By using an internal class as the IPC::Channel::Listener, we can intercept
- // OnMessageReceived/OnChannelConnected and do our own processing before
- // calling the subclass' implementation.
- class ListenerHook : public IPC::Channel::Listener {
- public:
- explicit ListenerHook(ChildProcessHost* host);
- virtual ~ListenerHook();
-
- void Shutdown();
-
- // IPC::Channel::Listener methods:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
-
- bool Send(IPC::Message* message);
-
- private:
- void OnShutdownRequest();
- void OnAllocateSharedMemory(uint32 buffer_size,
- base::SharedMemoryHandle* handle);
- ChildProcessHost* host_;
- base::ProcessHandle peer_handle_;
- DISALLOW_COPY_AND_ASSIGN(ListenerHook);
- };
+ // IPC::Channel::Listener methods:
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ virtual void OnChannelError() OVERRIDE;
- ListenerHook listener_;
+ // Message handlers:
+ void OnShutdownRequest();
+ void OnAllocateSharedMemory(uint32 buffer_size,
+ base::SharedMemoryHandle* handle);
+ content::ChildProcessHostDelegate* delegate_;
+ base::ProcessHandle peer_handle_;
bool opening_channel_; // True while we're waiting the channel to be opened.
scoped_ptr<IPC::Channel> channel_;
std::string channel_id_;
diff --git a/content/content_common.gypi b/content/content_common.gypi
index b4891f8..a9bdb55 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -29,6 +29,7 @@
],
'sources': [
'public/common/bindings_policy.h',
+ 'public/common/child_process_host_delegate.h',
'public/common/child_process_sandbox_support_linux.h',
'public/common/content_constants.cc',
'public/common/content_constants.h',
diff --git a/content/public/common/child_process_host_delegate.h b/content/public/common/child_process_host_delegate.h
new file mode 100644
index 0000000..7b9cbd1
--- /dev/null
+++ b/content/public/common/child_process_host_delegate.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 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.
+
+#ifndef CONTENT_PULIC_COMMON_CHILD_PROCESS_HOST_DELEGATE_H_
+#define CONTENT_PULIC_COMMON_CHILD_PROCESS_HOST_DELEGATE_H_
+#pragma once
+
+#include <string>
+
+#include "ipc/ipc_channel.h"
+
+namespace content {
+
+// Interface that all users of ChildProcessHost need to provide.
+class ChildProcessHostDelegate : public IPC::Channel::Listener {
+ public:
+ virtual ~ChildProcessHostDelegate() {}
+
+ // Derived classes return true if it's ok to shut down the child process.
+ // Normally they would return true. The exception is if the host is in the
+ // middle of sending a request to the process, in which case the other side
+ // might think it's ok to shutdown, when really it's not.
+ virtual bool CanShutdown() = 0;
+
+ // Notifies the derived class that we told the child process to kill itself.
+ virtual void ShutdownStarted() = 0;
+
+ // Called when the child process unexpected closes the IPC channel. Delegates
+ // would normally delete the object in this case.
+ virtual void OnChildDisconnected() = 0;
+};
+
+}; // namespace content
+
+#endif // CONTENT_PULIC_COMMON_CHILD_PROCESS_HOST_DELEGATE_H_