summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-20 22:20:20 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-20 22:20:20 +0000
commitf717ea6403554cc60a5dd9312fe585cdf64a8815 (patch)
tree523186875fe4c36bcc1c6905b3da36943a174318 /chrome/common
parente74b81de4f2785b5cff5cb0cc85e76b3d434248e (diff)
downloadchromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.zip
chromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.tar.gz
chromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.tar.bz2
Switch the first thread in a child process to be the main thread, and make the IO thread be the second thread. The change is needed for plugins on mac.
Review URL: http://codereview.chromium.org/149558 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21117 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/child_process.cc27
-rw-r--r--chrome/common/child_process.h28
-rw-r--r--chrome/common/child_thread.cc72
-rw-r--r--chrome/common/child_thread.h38
-rw-r--r--chrome/common/histogram_synchronizer.cc1
-rw-r--r--chrome/common/ipc_channel_proxy.cc4
-rw-r--r--chrome/common/ipc_channel_proxy.h4
7 files changed, 85 insertions, 89 deletions
diff --git a/chrome/common/child_process.cc b/chrome/common/child_process.cc
index f32708c..b777ff2 100644
--- a/chrome/common/child_process.cc
+++ b/chrome/common/child_process.cc
@@ -9,14 +9,14 @@
ChildProcess* ChildProcess::child_process_;
-ChildProcess::ChildProcess(ChildThread* child_thread)
- : child_thread_(child_thread),
- ref_count_(0),
- shutdown_event_(true, false) {
+ChildProcess::ChildProcess()
+ : ref_count_(0),
+ shutdown_event_(true, false),
+ io_thread_("Chrome_ChildIOThread") {
DCHECK(!child_process_);
child_process_ = this;
- if (child_thread_.get()) // null in unittests.
- child_thread_->Run();
+
+ io_thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
}
ChildProcess::~ChildProcess() {
@@ -28,28 +28,25 @@ ChildProcess::~ChildProcess() {
// notice shutdown before the render process begins waiting for them to exit.
shutdown_event_.Signal();
- if (child_thread_.get())
- child_thread_->Stop();
-
child_process_ = NULL;
}
void ChildProcess::AddRefProcess() {
- DCHECK(!child_thread_.get() || // null in unittests.
- MessageLoop::current() == child_thread_->message_loop());
+ DCHECK(!main_thread_.get() || // null in unittests.
+ MessageLoop::current() == main_thread_->message_loop());
ref_count_++;
}
void ChildProcess::ReleaseProcess() {
- DCHECK(!child_thread_.get() || // null in unittests.
- MessageLoop::current() == child_thread_->message_loop());
+ DCHECK(!main_thread_.get() || // null in unittests.
+ MessageLoop::current() == main_thread_->message_loop());
DCHECK(ref_count_);
DCHECK(child_process_);
if (--ref_count_)
return;
- if (child_thread_.get()) // null in unittests.
- child_thread_->OnProcessFinalRelease();
+ if (main_thread_.get()) // null in unittests.
+ main_thread_->OnProcessFinalRelease();
}
base::WaitableEvent* ChildProcess::GetShutDownEvent() {
diff --git a/chrome/common/child_process.h b/chrome/common/child_process.h
index 1366a02..5e125bc 100644
--- a/chrome/common/child_process.h
+++ b/chrome/common/child_process.h
@@ -7,21 +7,23 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
+#include "base/thread.h"
#include "base/waitable_event.h"
-
-class ChildThread;
+#include "chrome/common/child_thread.h"
// Base class for child processes of the browser process (i.e. renderer and
// plugin host). This is a singleton object for each child process.
class ChildProcess {
public:
- // Child processes should have an object that derives from this class. The
- // constructor will return once ChildThread has started.
- ChildProcess(ChildThread* child_thread);
+ // Child processes should have an object that derives from this class.
+ ChildProcess();
virtual ~ChildProcess();
- // Getter for this process' main thread.
- ChildThread* child_thread() { return child_thread_.get(); }
+ // Getter for the child process' main thread.
+ ChildThread* main_thread() { return main_thread_.get(); }
+ void set_main_thread(ChildThread* thread) { main_thread_.reset(thread); }
+
+ MessageLoop* io_message_loop() { return io_thread_.message_loop(); }
// A global event object that is signalled when the main thread's message
// loop exits. This gives background threads a way to observe the main
@@ -45,15 +47,19 @@ class ChildProcess {
static ChildProcess* current() { return child_process_; }
private:
- // NOTE: make sure that child_thread_ is listed before shutdown_event_, since
- // it depends on it (indirectly through IPC::SyncChannel).
- scoped_ptr<ChildThread> child_thread_;
-
int ref_count_;
// An event that will be signalled when we shutdown.
base::WaitableEvent shutdown_event_;
+ // The thread that handles IO events.
+ base::Thread io_thread_;
+
+ // NOTE: make sure that main_thread_ is listed after shutdown_event_, since
+ // it depends on it (indirectly through IPC::SyncChannel). Same for
+ // io_thread_.
+ scoped_ptr<ChildThread> main_thread_;
+
// The singleton instance for this process.
static ChildProcess* child_process_;
diff --git a/chrome/common/child_thread.cc b/chrome/common/child_thread.cc
index 4c97b72..db3c4c5 100644
--- a/chrome/common/child_thread.cc
+++ b/chrome/common/child_thread.cc
@@ -9,19 +9,14 @@
#include "chrome/common/child_process.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/ipc_logging.h"
+#include "chrome/common/notification_service.h"
#include "chrome/common/plugin_messages.h"
#include "webkit/glue/webkit_glue.h"
-// V8 needs a 1MB stack size.
-const size_t ChildThread::kV8StackSize = 1024 * 1024;
-
-ChildThread::ChildThread(Thread::Options options)
- : Thread("Chrome_ChildThread"),
- owner_loop_(MessageLoop::current()),
- options_(options),
- check_with_browser_before_shutdown_(false) {
- DCHECK(owner_loop_);
+ChildThread::ChildThread()
+ : check_with_browser_before_shutdown_(false),
+ message_loop_(MessageLoop::current()) {
channel_name_ = WideToASCII(
CommandLine::ForCurrentProcess()->GetSwitchValue(
switches::kProcessChannelID));
@@ -31,17 +26,41 @@ ChildThread::ChildThread(Thread::Options options)
CommandLine::ForCurrentProcess()->GetSwitchValue(
switches::kUserAgent)));
}
+
+ channel_.reset(new IPC::SyncChannel(channel_name_,
+ IPC::Channel::MODE_CLIENT, this, NULL,
+ ChildProcess::current()->io_message_loop(), true,
+ ChildProcess::current()->GetShutDownEvent()));
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ IPC::Logging::current()->SetIPCSender(this);
+#endif
+
+ resource_dispatcher_.reset(new ResourceDispatcher(this));
+
+ // When running in unit tests, there is already a NotificationService object.
+ // Since only one can exist at a time per thread, check first.
+ if (!NotificationService::current())
+ notification_service_.reset(new NotificationService);
}
ChildThread::~ChildThread() {
-}
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ IPC::Logging::current()->SetIPCSender(NULL);
+#endif
-bool ChildThread::Run() {
- return StartWithOptions(options_);
+ // The ChannelProxy object caches a pointer to the IPC thread, so need to
+ // reset it as it's not guaranteed to outlive this object.
+ // NOTE: this also has the side-effect of not closing the main IPC channel to
+ // the browser process. This is needed because this is the signal that the
+ // browser uses to know that this process has died, so we need it to be alive
+ // until this process is shut down, and the OS closes the handle
+ // automatically. We used to watch the object handle on Windows to do this,
+ // but it wasn't possible to do so on POSIX.
+ channel_->ClearIPCMessageLoop();
}
void ChildThread::OnChannelError() {
- owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoop::current()->Quit();
}
bool ChildThread::Send(IPC::Message* msg) {
@@ -76,7 +95,7 @@ void ChildThread::OnMessageReceived(const IPC::Message& msg) {
}
if (msg.type() == PluginProcessMsg_Shutdown::ID) {
- owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoop::current()->Quit();
return;
}
@@ -88,33 +107,12 @@ void ChildThread::OnMessageReceived(const IPC::Message& msg) {
}
ChildThread* ChildThread::current() {
- return ChildProcess::current()->child_thread();
-}
-
-void ChildThread::Init() {
- channel_.reset(new IPC::SyncChannel(channel_name_,
- IPC::Channel::MODE_CLIENT, this, NULL, owner_loop_, true,
- ChildProcess::current()->GetShutDownEvent()));
-#ifdef IPC_MESSAGE_LOG_ENABLED
- IPC::Logging::current()->SetIPCSender(this);
-#endif
-
- resource_dispatcher_.reset(new ResourceDispatcher(this));
-}
-
-void ChildThread::CleanUp() {
-#ifdef IPC_MESSAGE_LOG_ENABLED
- IPC::Logging::current()->SetIPCSender(NULL);
-#endif
- // Need to destruct the SyncChannel to the browser before we go away because
- // it caches a pointer to this thread.
- channel_.reset();
- resource_dispatcher_.reset();
+ return ChildProcess::current()->main_thread();
}
void ChildThread::OnProcessFinalRelease() {
if (!check_with_browser_before_shutdown_) {
- owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoop::current()->Quit();
return;
}
diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h
index cc4abaa..86eae4c 100644
--- a/chrome/common/child_thread.h
+++ b/chrome/common/child_thread.h
@@ -7,18 +7,18 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
-#include "base/thread.h"
#include "chrome/common/ipc_sync_channel.h"
#include "chrome/common/message_router.h"
#include "chrome/common/resource_dispatcher.h"
-// Child processes's background thread should derive from this class.
+class NotificationService;
+
+// The main thread of a child process derives from this class.
class ChildThread : public IPC::Channel::Listener,
- public IPC::Message::Sender,
- public base::Thread {
+ public IPC::Message::Sender {
public:
// Creates the thread.
- ChildThread(Thread::Options options);
+ ChildThread();
virtual ~ChildThread();
// IPC::Message::Sender implementation:
@@ -28,58 +28,40 @@ class ChildThread : public IPC::Channel::Listener,
void AddRoute(int32 routing_id, IPC::Channel::Listener* listener);
void RemoveRoute(int32 routing_id);
- MessageLoop* owner_loop() { return owner_loop_; }
-
ResourceDispatcher* resource_dispatcher() {
return resource_dispatcher_.get();
}
+ MessageLoop* message_loop() { return message_loop_; }
+
// Returns the one child thread.
static ChildThread* current();
protected:
friend class ChildProcess;
- // Starts the thread.
- bool Run();
-
// Overrides the channel name. Used for --single-process mode.
void SetChannelName(const std::string& name) { channel_name_ = name; }
// Called when the process refcount is 0.
void OnProcessFinalRelease();
- protected:
- // The required stack size if V8 runs on a thread.
- static const size_t kV8StackSize;
-
virtual void OnControlMessageReceived(const IPC::Message& msg) { }
IPC::SyncChannel* channel() { return channel_.get(); }
- // Thread implementation.
- virtual void Init();
- virtual void CleanUp();
-
private:
// IPC::Channel::Listener implementation:
virtual void OnMessageReceived(const IPC::Message& msg);
virtual void OnChannelError();
- // The message loop used to run tasks on the thread that started this thread.
- MessageLoop* owner_loop_;
-
std::string channel_name_;
scoped_ptr<IPC::SyncChannel> channel_;
- // Used only on the background render thread to implement message routing
- // functionality to the consumers of the ChildThread.
+ // Implements message routing functionality to the consumers of ChildThread.
MessageRouter router_;
- Thread::Options options_;
-
// Handles resource loads for this process.
- // NOTE: this object lives on the owner thread.
scoped_ptr<ResourceDispatcher> resource_dispatcher_;
// If true, checks with the browser process before shutdown. This avoids race
@@ -87,6 +69,10 @@ class ChildThread : public IPC::Channel::Listener,
// that would addref it.
bool check_with_browser_before_shutdown_;
+ MessageLoop* message_loop_;
+
+ scoped_ptr<NotificationService> notification_service_;
+
DISALLOW_COPY_AND_ASSIGN(ChildThread);
};
diff --git a/chrome/common/histogram_synchronizer.cc b/chrome/common/histogram_synchronizer.cc
index 4713084..9ed94b0 100644
--- a/chrome/common/histogram_synchronizer.cc
+++ b/chrome/common/histogram_synchronizer.cc
@@ -7,6 +7,7 @@
#include "base/histogram.h"
#include "base/logging.h"
#include "base/string_util.h"
+#include "base/thread.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
diff --git a/chrome/common/ipc_channel_proxy.cc b/chrome/common/ipc_channel_proxy.cc
index c97e6f5..eedca7e 100644
--- a/chrome/common/ipc_channel_proxy.cc
+++ b/chrome/common/ipc_channel_proxy.cc
@@ -272,6 +272,10 @@ void ChannelProxy::RemoveFilter(MessageFilter* filter) {
context_.get(), &Context::OnRemoveFilter, filter));
}
+void ChannelProxy::ClearIPCMessageLoop() {
+ context()->ClearIPCMessageLoop();
+}
+
#if defined(OS_POSIX)
// See the TODO regarding lazy initialization of the channel in
// ChannelProxy::Init().
diff --git a/chrome/common/ipc_channel_proxy.h b/chrome/common/ipc_channel_proxy.h
index 8adcb5b..3725ab1 100644
--- a/chrome/common/ipc_channel_proxy.h
+++ b/chrome/common/ipc_channel_proxy.h
@@ -117,6 +117,9 @@ class ChannelProxy : public Message::Sender {
void AddFilter(MessageFilter* filter);
void RemoveFilter(MessageFilter* filter);
+ // Called to clear the pointer to the IPC message loop when it's going away.
+ void ClearIPCMessageLoop();
+
#if defined(OS_POSIX)
// Calls through to the underlying channel's methods.
// TODO(playmobil): For now this is only implemented in the case of
@@ -140,6 +143,7 @@ class ChannelProxy : public Message::Sender {
Context(Channel::Listener* listener, MessageFilter* filter,
MessageLoop* ipc_thread);
virtual ~Context() { }
+ void ClearIPCMessageLoop() { ipc_message_loop_ = NULL; }
MessageLoop* ipc_message_loop() const { return ipc_message_loop_; }
const std::string& channel_id() const { return channel_id_; }