Index: content/browser/browser_child_process_host.cc |
=================================================================== |
--- content/browser/browser_child_process_host.cc (revision 118420) |
+++ content/browser/browser_child_process_host.cc (working copy) |
@@ -20,6 +20,7 @@ |
#include "content/common/child_process_host_impl.h" |
#include "content/common/plugin_messages.h" |
#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/browser_child_process_host_delegate.h" |
#include "content/public/browser/child_process_data.h" |
#include "content/public/browser/content_browser_client.h" |
#include "content/public/browser/notification_service.h" |
@@ -33,31 +34,48 @@ |
#include "base/bind.h" |
#endif |
+using content::BrowserChildProcessHostDelegate; |
using content::BrowserThread; |
+using content::ChildProcessData; |
using content::ChildProcessHost; |
using content::ChildProcessHostImpl; |
namespace { |
-typedef std::list<BrowserChildProcessHost*> BrowserChildProcessList; |
-static base::LazyInstance<BrowserChildProcessList> g_child_process_list = |
- LAZY_INSTANCE_INITIALIZER; |
+static base::LazyInstance<BrowserChildProcessHost::BrowserChildProcessList> |
+ g_child_process_list = LAZY_INSTANCE_INITIALIZER; |
// Helper functions since the child process related notifications happen on the |
// UI thread. |
void ChildNotificationHelper(int notification_type, |
- const content::ChildProcessData& data) { |
+ const ChildProcessData& data) { |
content::NotificationService::current()-> |
Notify(notification_type, content::NotificationService::AllSources(), |
- content::Details<const content::ChildProcessData>(&data)); |
+ content::Details<const ChildProcessData>(&data)); |
} |
} // namespace |
+namespace content { |
+ |
+BrowserChildProcessHost* BrowserChildProcessHost::Create( |
+ ProcessType type, |
+ BrowserChildProcessHostDelegate* delegate) { |
+ return new ::BrowserChildProcessHost(type, delegate); |
+} |
+ |
+} // namespace content |
+ |
+BrowserChildProcessHost::BrowserChildProcessList* |
+ BrowserChildProcessHost::GetIterator() { |
+ return g_child_process_list.Pointer(); |
+} |
+ |
BrowserChildProcessHost::BrowserChildProcessHost( |
- content::ProcessType type) |
+ content::ProcessType type, |
+ BrowserChildProcessHostDelegate* delegate) |
: data_(type), |
- ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)), |
+ delegate_(delegate), |
#if !defined(OS_WIN) |
ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), |
#endif |
@@ -77,6 +95,7 @@ |
// static |
void BrowserChildProcessHost::TerminateAll() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
// Make a copy since the BrowserChildProcessHost dtor mutates the original |
// list. |
BrowserChildProcessList copy = g_child_process_list.Get(); |
@@ -91,9 +110,10 @@ |
const base::environment_vector& environ, |
#endif |
CommandLine* cmd_line) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
content::GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
- cmd_line, data().id); |
+ cmd_line, data_.id); |
child_process_.reset(new ChildProcessLauncher( |
#if defined(OS_WIN) |
@@ -101,13 +121,24 @@ |
#elif defined(OS_POSIX) |
use_zygote, |
environ, |
- child_process_host()->TakeClientFileDescriptor(), |
+ child_process_host_->TakeClientFileDescriptor(), |
#endif |
cmd_line, |
- &client_)); |
+ this)); |
} |
-base::ProcessHandle BrowserChildProcessHost::GetChildProcessHandle() const { |
+const ChildProcessData& BrowserChildProcessHost::GetData() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return data_; |
+} |
+ |
+ChildProcessHost* BrowserChildProcessHost::GetHost() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return child_process_host_.get(); |
+} |
+ |
+base::ProcessHandle BrowserChildProcessHost::GetHandle() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
DCHECK(child_process_.get()) |
<< "Requesting a child process handle before launching."; |
DCHECK(child_process_->GetHandle()) |
@@ -116,20 +147,24 @@ |
} |
void BrowserChildProcessHost::SetName(const string16& name) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
data_.name = name; |
} |
void BrowserChildProcessHost::SetHandle(base::ProcessHandle handle) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
data_.handle = handle; |
} |
void BrowserChildProcessHost::ForceShutdown() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
g_child_process_list.Get().remove(this); |
child_process_host_->ForceShutdown(); |
} |
void BrowserChildProcessHost::SetTerminateChildOnShutdown( |
- bool terminate_on_shutdown) { |
+ bool terminate_on_shutdown) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown); |
} |
@@ -140,23 +175,29 @@ |
base::Bind(&ChildNotificationHelper, type, data_)); |
} |
-base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus( |
+base::TerminationStatus BrowserChildProcessHost::GetTerminationStatus( |
int* exit_code) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
if (!child_process_.get()) // If the delegate doesn't use Launch() helper. |
- return base::GetTerminationStatus(data().handle, exit_code); |
+ return base::GetTerminationStatus(data_.handle, exit_code); |
return child_process_->GetChildTerminationStatus(exit_code); |
} |
bool BrowserChildProcessHost::OnMessageReceived(const IPC::Message& message) { |
- return false; |
+ return delegate_->OnMessageReceived(message); |
} |
void BrowserChildProcessHost::OnChannelConnected(int32 peer_pid) { |
Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_CONNECTED); |
+ delegate_->OnChannelConnected(peer_pid); |
} |
+void BrowserChildProcessHost::OnChannelError() { |
+ delegate_->OnChannelError(); |
+} |
+ |
bool BrowserChildProcessHost::CanShutdown() { |
- return true; |
+ return delegate_->CanShutdown(); |
} |
// Normally a ChildProcessHostDelegate deletes itself from this callback, but at |
@@ -167,21 +208,21 @@ |
// may be called twice: once from the actual channel error and once from |
// OnWaitableEventSignaled() or the delayed task. |
void BrowserChildProcessHost::OnChildDisconnected() { |
- DCHECK(data().handle != base::kNullProcessHandle); |
+ DCHECK(data_.handle != base::kNullProcessHandle); |
int exit_code; |
- base::TerminationStatus status = GetChildTerminationStatus(&exit_code); |
+ base::TerminationStatus status = GetTerminationStatus(&exit_code); |
switch (status) { |
case base::TERMINATION_STATUS_PROCESS_CRASHED: |
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: { |
- OnProcessCrashed(exit_code); |
+ delegate_->OnProcessCrashed(exit_code); |
// Report that this child process crashed. |
Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED); |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
if (disconnect_was_alive_) { |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.CrashedWasAlive", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
} |
break; |
@@ -189,11 +230,11 @@ |
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: { |
// Report that this child process was killed. |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
if (disconnect_was_alive_) { |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.KilledWasAlive", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
} |
break; |
@@ -203,14 +244,14 @@ |
// code. |
if (disconnect_was_alive_) { |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
break; |
} |
disconnect_was_alive_ = true; |
#if defined(OS_WIN) |
child_watcher_.StartWatching( |
- new base::WaitableEvent(data().handle), this); |
+ new base::WaitableEvent(data_.handle), this); |
#else |
// On non-Windows platforms, give the child process some time to die after |
// disconnecting the channel so that the exit code and termination status |
@@ -230,11 +271,11 @@ |
break; |
} |
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected", |
- data().type, |
+ data_.type, |
content::PROCESS_TYPE_MAX); |
// Notify in the main loop of the disconnection. |
Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED); |
- delete this; |
+ delete delegate_; // Will delete us |
} |
// The child process handle has been signaled so the exit code is finally |
@@ -248,7 +289,7 @@ |
GetExitCodeProcess(waitable_event->Release(), &exit_code); |
delete waitable_event; |
if (exit_code == STILL_ACTIVE) { |
- delete this; |
+ delete delegate_; // Will delete us |
} else { |
BrowserChildProcessHost::OnChildDisconnected(); |
} |
@@ -265,50 +306,12 @@ |
g_child_process_list.Get().remove(this); |
} |
-BrowserChildProcessHost::ClientHook::ClientHook(BrowserChildProcessHost* host) |
- : host_(host) { |
-} |
-void BrowserChildProcessHost::ClientHook::OnProcessLaunched() { |
- if (!host_->child_process_->GetHandle()) { |
- delete host_; |
+void BrowserChildProcessHost::OnProcessLaunched() { |
+ if (!child_process_->GetHandle()) { |
+ delete delegate_; // Will delete us |
return; |
} |
- host_->data_.handle = host_->child_process_->GetHandle(); |
- host_->OnProcessLaunched(); |
+ data_.handle = child_process_->GetHandle(); |
+ delegate_->OnProcessLaunched(); |
} |
- |
-BrowserChildProcessHost::Iterator::Iterator() |
- : all_(true), type_(content::PROCESS_TYPE_UNKNOWN) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << |
- "BrowserChildProcessHost::Iterator must be used on the IO thread."; |
- iterator_ = g_child_process_list.Get().begin(); |
-} |
- |
-BrowserChildProcessHost::Iterator::Iterator(content::ProcessType type) |
- : all_(false), type_(type) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << |
- "BrowserChildProcessHost::Iterator must be used on the IO thread."; |
- iterator_ = g_child_process_list.Get().begin(); |
- if (!Done() && (*iterator_)->data().type != type_) |
- ++(*this); |
-} |
- |
-BrowserChildProcessHost* BrowserChildProcessHost::Iterator::operator++() { |
- do { |
- ++iterator_; |
- if (Done()) |
- break; |
- |
- if (!all_ && (*iterator_)->data().type != type_) |
- continue; |
- |
- return *iterator_; |
- } while (true); |
- |
- return NULL; |
-} |
- |
-bool BrowserChildProcessHost::Iterator::Done() { |
- return iterator_ == g_child_process_list.Get().end(); |
-} |