diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 00:25:06 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 00:25:06 +0000 |
commit | f784592cd075d7866c74e410833768c8b6f9b622 (patch) | |
tree | 8512d6dc402faef8df803c7ff07ba5b77eecda3f /chrome | |
parent | a63f220009f90657fc1070d4a9bde26726deb6b4 (diff) | |
download | chromium_src-f784592cd075d7866c74e410833768c8b6f9b622.zip chromium_src-f784592cd075d7866c74e410833768c8b6f9b622.tar.gz chromium_src-f784592cd075d7866c74e410833768c8b6f9b622.tar.bz2 |
Switch the first thread in a child process to be the main thread, and make theIO thread be the second thread. The change is needed for plugins on mac.
Review URL: http://codereview.chromium.org/155944
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21355 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
26 files changed, 208 insertions, 353 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 2370fd3..07f202a 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -54,6 +54,7 @@ #include "chrome/common/render_messages.h" #include "chrome/common/result_codes.h" #include "chrome/renderer/render_process.h" +#include "chrome/renderer/render_thread.h" #include "chrome/installer/util/google_update_settings.h" #include "grit/generated_resources.h" @@ -92,7 +93,8 @@ class RendererMainThread : public base::Thread { CoInitialize(NULL); #endif - render_process_ = new RenderProcess(channel_id_); + render_process_ = new RenderProcess(); + render_process_->set_main_thread(new RenderThread(channel_id_)); // It's a little lame to manually set this flag. But the single process // RendererThread will receive the WM_QUIT. We don't need to assert on // this thread, so just force the flag manually. @@ -411,18 +413,14 @@ bool BrowserRenderProcessHost::Init() { if (run_renderer_in_process()) { // Crank up a thread and run the initialization there. With the way that // messages flow between the browser and renderer, this thread is required - // to prevent a deadlock in single-process mode. When using multiple - // processes, the primordial thread in the renderer process has a message - // loop which is used for sending messages asynchronously to the io thread - // in the browser process. If we don't create this thread, then the - // RenderThread is both responsible for rendering and also for - // communicating IO. This can lead to deadlocks where the RenderThread is - // waiting for the IO to complete, while the browsermain is trying to pass - // an event to the RenderThread. + // to prevent a deadlock in single-process mode. Since the primordial + // thread in the renderer process runs the WebKit code and can sometimes + // blocking calls to the UI thread (i.e. this thread), they need to run on + // separate threads. in_process_renderer_.reset(new RendererMainThread(channel_id)); base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; + options.message_loop_type = MessageLoop::TYPE_UI; in_process_renderer_->StartWithOptions(options); } else { base::ProcessHandle process = 0; diff --git a/chrome/common/child_process.cc b/chrome/common/child_process.cc index f32708c..34ea7a2 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,29 @@ ChildProcess::~ChildProcess() { // notice shutdown before the render process begins waiting for them to exit. shutdown_event_.Signal(); - if (child_thread_.get()) - child_thread_->Stop(); + // Kill the main thread object before nulling child_process_, since + // destruction code might depend on it. + main_thread_.reset(); 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 15a98b3..e2f7c5f 100644 --- a/chrome/common/child_thread.cc +++ b/chrome/common/child_thread.cc @@ -8,40 +8,67 @@ #include "base/command_line.h" #include "chrome/common/child_process.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_service.h" #include "chrome/common/plugin_messages.h" #include "ipc/ipc_logging.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() { channel_name_ = WideToASCII( CommandLine::ForCurrentProcess()->GetSwitchValue( switches::kProcessChannelID)); + Init(); +} +ChildThread::ChildThread(const std::string channel_name) + : channel_name_(channel_name) { + Init(); +} + +void ChildThread::Init() { + check_with_browser_before_shutdown_ = false; + message_loop_ = MessageLoop::current(); if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserAgent)) { webkit_glue::SetUserAgent(WideToUTF8( 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 +103,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 +115,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 1affe25..91ea9b7 100644 --- a/chrome/common/child_thread.h +++ b/chrome/common/child_thread.h @@ -7,18 +7,20 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" -#include "base/thread.h" #include "chrome/common/message_router.h" #include "chrome/common/resource_dispatcher.h" #include "ipc/ipc_sync_channel.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(); + // Used for single-process mode. + ChildThread(const std::string channel_name); virtual ~ChildThread(); // IPC::Message::Sender implementation: @@ -28,58 +30,39 @@ 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: + void Init(); + // 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 +70,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/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc index 7361d64..63d295d 100644 --- a/chrome/plugin/plugin_main.cc +++ b/chrome/plugin/plugin_main.cc @@ -29,8 +29,8 @@ // main() routine for running as the plugin process. int PluginMain(const MainFunctionParams& parameters) { - // The main thread of the plugin services IO. - MessageLoopForIO main_message_loop; + // The main thread of the plugin services UI. + MessageLoop main_message_loop(MessageLoop::TYPE_UI); std::wstring app_name = chrome::kBrowserAppName; PlatformThread::SetName(WideToASCII(app_name + L"_PluginMain").c_str()); @@ -80,7 +80,8 @@ int PluginMain(const MainFunctionParams& parameters) { } { - ChildProcess plugin_process(new PluginThread()); + ChildProcess plugin_process; + plugin_process.set_main_thread(new PluginThread()); #if defined(OS_WIN) if (!no_sandbox && target_services) target_services->LowerToken(); diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index da5c68c..ae90e1a 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -6,11 +6,6 @@ #include "build/build_config.h" -#if defined(OS_WIN) -#include <windows.h> -#include <objbase.h> -#endif - #include "base/command_line.h" #include "base/lazy_instance.h" #include "base/process_util.h" @@ -18,7 +13,6 @@ #include "chrome/common/child_process.h" #include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/notification_service.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" #include "chrome/plugin/chrome_plugin_host.h" @@ -32,27 +26,10 @@ static base::LazyInstance<base::ThreadLocalPointer<PluginThread> > lazy_tls( base::LINKER_INITIALIZED); PluginThread::PluginThread() - : ChildThread(base::Thread::Options(MessageLoop::TYPE_UI, 0)), - preloaded_plugin_module_(NULL) { + : preloaded_plugin_module_(NULL) { plugin_path_ = FilePath::FromWStringHack( CommandLine::ForCurrentProcess()->GetSwitchValue(switches::kPluginPath)); -} - -PluginThread::~PluginThread() { -} - -PluginThread* PluginThread::current() { - return lazy_tls.Pointer()->Get(); -} - -void PluginThread::OnControlMessageReceived(const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(PluginThread, msg) - IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel) - IPC_MESSAGE_HANDLER(PluginProcessMsg_PluginMessage, OnPluginMessage) - IPC_END_MESSAGE_MAP() -} -void PluginThread::Init() { lazy_tls.Pointer()->Set(this); #if defined(OS_LINUX) { @@ -75,14 +52,8 @@ void PluginThread::Init() { } } #endif - ChildThread::Init(); PatchNPNFunctions(); -#if defined(OS_WIN) - CoInitialize(NULL); -#endif - - notification_service_.reset(new NotificationService); // Preload the library to avoid loading, unloading then reloading preloaded_plugin_module_ = base::LoadNativeLibrary(plugin_path_); @@ -100,7 +71,7 @@ void PluginThread::Init() { message_loop()->set_exception_restoration(true); } -void PluginThread::CleanUp() { +PluginThread::~PluginThread() { if (preloaded_plugin_module_) { base::UnloadNativeLibrary(preloaded_plugin_module_); preloaded_plugin_module_ = NULL; @@ -108,26 +79,29 @@ void PluginThread::CleanUp() { PluginChannelBase::CleanupChannels(); NPAPI::PluginLib::UnloadAllPlugins(); ChromePluginLib::UnloadAllPlugins(); - notification_service_.reset(); -#if defined(OS_WIN) - CoUninitialize(); -#endif if (webkit_glue::ShouldForcefullyTerminatePluginProcess()) base::KillProcess(base::GetCurrentProcessHandle(), 0, /* wait= */ false); - // Call this last because it deletes the ResourceDispatcher, which is used - // in some of the above cleanup. - // See http://code.google.com/p/chromium/issues/detail?id=8980 - ChildThread::CleanUp(); lazy_tls.Pointer()->Set(NULL); } +PluginThread* PluginThread::current() { + return lazy_tls.Pointer()->Get(); +} + +void PluginThread::OnControlMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PluginThread, msg) + IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel) + IPC_MESSAGE_HANDLER(PluginProcessMsg_PluginMessage, OnPluginMessage) + IPC_END_MESSAGE_MAP() +} + void PluginThread::OnCreateChannel( int process_id, bool off_the_record) { - scoped_refptr<PluginChannel> channel = - PluginChannel::GetPluginChannel(process_id, owner_loop()); + scoped_refptr<PluginChannel> channel = PluginChannel::GetPluginChannel( + process_id, ChildProcess::current()->io_message_loop()); IPC::ChannelHandle channel_handle; if (channel.get()) { channel_handle.name = channel->channel_name(); diff --git a/chrome/plugin/plugin_thread.h b/chrome/plugin/plugin_thread.h index e9074aa..2e9803c 100644 --- a/chrome/plugin/plugin_thread.h +++ b/chrome/plugin/plugin_thread.h @@ -16,8 +16,6 @@ #include "base/file_descriptor_posix.h" #endif -class NotificationService; - // The PluginThread class represents a background thread where plugin instances // live. Communication occurs between WebPluginDelegateProxy in the renderer // process and WebPluginDelegateStub in this thread through IPC messages. @@ -32,18 +30,12 @@ class PluginThread : public ChildThread { private: virtual void OnControlMessageReceived(const IPC::Message& msg); - // Thread implementation: - virtual void Init(); - virtual void CleanUp(); - // Callback for when a channel has been created. void OnCreateChannel( int process_id, bool off_the_record); void OnPluginMessage(const std::vector<uint8> &data); - scoped_ptr<NotificationService> notification_service_; - // The plugin module which is preloaded in Init base::NativeLibrary preloaded_plugin_module_; diff --git a/chrome/renderer/mock_render_process.h b/chrome/renderer/mock_render_process.h index 629967f..49bc02c 100644 --- a/chrome/renderer/mock_render_process.h +++ b/chrome/renderer/mock_render_process.h @@ -14,8 +14,7 @@ class ChildThread; // a render widget instance. class MockProcess : public ChildProcess { public: - explicit MockProcess() : ChildProcess(NULL) {} - explicit MockProcess(ChildThread* thread) : ChildProcess(thread) {} + explicit MockProcess() : ChildProcess() {} }; #endif // CHROME_RENDERER_MOCK_RENDER_PROCESS_H_ diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index 1b8509f..ba5c37a 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -47,43 +47,10 @@ static size_t GetMaxSharedMemorySize() { //----------------------------------------------------------------------------- RenderProcess::RenderProcess() - : ChildProcess(new RenderThread()), - ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( + : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( base::TimeDelta::FromSeconds(5), this, &RenderProcess::ClearTransportDIBCache)), sequence_number_(0) { - Init(); -} - -RenderProcess::RenderProcess(const std::string& channel_name) - : ChildProcess(new RenderThread(channel_name)), - ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( - base::TimeDelta::FromSeconds(5), - this, &RenderProcess::ClearTransportDIBCache)), - sequence_number_(0) { - Init(); -} - -RenderProcess::~RenderProcess() { - // TODO(port) - // Try and limit what we pull in for our non-Win unit test bundle -#ifndef NDEBUG - // log important leaked objects - webkit_glue::CheckForLeaks(); -#endif - - GetShutDownEvent()->Signal(); - - // We need to stop the RenderThread as the clearer_factory_ - // member could be in use while the object itself is destroyed, - // as a result of the containing RenderProcess object being destroyed. - // This race condition causes a crash when the renderer process is shutting - // down. - child_thread()->Stop(); - ClearTransportDIBCache(); -} - -void RenderProcess::Init() { in_process_plugins_ = InProcessPlugins(); for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) shared_mem_cache_[i] = NULL; @@ -131,6 +98,18 @@ void RenderProcess::Init() { media::InitializeMediaLibrary(module_path); } +RenderProcess::~RenderProcess() { + // TODO(port) + // Try and limit what we pull in for our non-Win unit test bundle +#ifndef NDEBUG + // log important leaked objects + webkit_glue::CheckForLeaks(); +#endif + + GetShutDownEvent()->Signal(); + ClearTransportDIBCache(); +} + bool RenderProcess::InProcessPlugins() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); #if defined(OS_LINUX) @@ -157,7 +136,7 @@ TransportDIB* RenderProcess::CreateTransportDIB(size_t size) { // get one. TransportDIB::Handle handle; IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &handle); - if (!child_thread()->Send(msg)) + if (!main_thread()->Send(msg)) return NULL; if (handle.fd < 0) return NULL; @@ -173,7 +152,7 @@ void RenderProcess::FreeTransportDIB(TransportDIB* dib) { // On Mac we need to tell the browser that it can drop a reference to the // shared memory. IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id()); - child_thread()->Send(msg); + main_thread()->Send(msg); #endif delete dib; diff --git a/chrome/renderer/render_process.h b/chrome/renderer/render_process.h index 727aae5..d445fbe 100644 --- a/chrome/renderer/render_process.h +++ b/chrome/renderer/render_process.h @@ -21,11 +21,7 @@ class TransportDIB; // each renderer. class RenderProcess : public ChildProcess { public: - // This constructor grabs the channel name from the command line arguments. RenderProcess(); - // This constructor uses the given channel name. - RenderProcess(const std::string& channel_name); - ~RenderProcess(); // Get a canvas suitable for drawing and transporting to the browser @@ -52,14 +48,10 @@ class RenderProcess : public ChildProcess { return static_cast<RenderProcess*>(ChildProcess::current()); } - protected: - friend class RenderThread; // Just like in_process_plugins(), but called before RenderProcess is created. static bool InProcessPlugins(); private: - void Init(); - // Look in the shared memory cache for a suitable object to reuse. // result: (output) the memory found // size: the resulting memory will be >= this size, in bytes diff --git a/chrome/renderer/render_process_unittest.cc b/chrome/renderer/render_process_unittest.cc index feac0aa..5692d81 100644 --- a/chrome/renderer/render_process_unittest.cc +++ b/chrome/renderer/render_process_unittest.cc @@ -17,7 +17,7 @@ class RenderProcessTest : public testing::Test { virtual void SetUp() { // Need a MODE_SERVER to make MODE_CLIENTs (like a RenderThread) happy. channel_ = new IPC::Channel(kThreadName, IPC::Channel::MODE_SERVER, NULL); - render_process_.reset(new RenderProcess(kThreadName)); + render_process_.reset(new RenderProcess()); } virtual void TearDown() { diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index e35377a..80811b2 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -17,7 +17,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" #include "chrome/common/renderer_preferences.h" -#include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" #include "chrome/plugin/npobject_util.h" // TODO(port) @@ -55,54 +54,10 @@ using WebKit::WebCache; using WebKit::WebString; +namespace { static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; - static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( base::LINKER_INITIALIZED); - -//----------------------------------------------------------------------------- -// Methods below are only called on the owner's thread: - -// When we run plugins in process, we actually run them on the render thread, -// which means that we need to make the render thread pump UI events. -RenderThread::RenderThread() - : ChildThread( - base::Thread::Options(RenderProcess::InProcessPlugins() ? - MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)), - plugin_refresh_allowed_(true) { -} - -RenderThread::RenderThread(const std::string& channel_name) - : ChildThread( - base::Thread::Options(RenderProcess::InProcessPlugins() ? - MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)), - plugin_refresh_allowed_(true) { - SetChannelName(channel_name); -} - -RenderThread::~RenderThread() { -} - -RenderThread* RenderThread::current() { - return lazy_tls.Pointer()->Get(); -} - -void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { - channel()->AddFilter(filter); -} - -void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { - channel()->RemoveFilter(filter); -} - -void RenderThread::Resolve(const char* name, size_t length) { - return dns_master_->Resolve(name, length); -} - -void RenderThread::SendHistograms(int sequence_number) { - return histogram_snapshots_->SendHistograms(sequence_number); -} - static WebAppCacheContext* CreateAppCacheContextForRenderer() { return new AppCacheContextImpl(RenderThread::current()); } @@ -128,6 +83,18 @@ class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { } }; #endif +} // namespace + +// When we run plugins in process, we actually run them on the render thread, +// which means that we need to make the render thread pump UI events. +RenderThread::RenderThread() { + Init(); +} + +RenderThread::RenderThread(const std::string& channel_name) + : ChildThread(channel_name) { + Init(); +} void RenderThread::Init() { lazy_tls.Pointer()->Set(this); @@ -138,8 +105,7 @@ void RenderThread::Init() { CoInitialize(0); #endif - ChildThread::Init(); - notification_service_.reset(new NotificationService); + plugin_refresh_allowed_ = true; cache_stats_factory_.reset( new ScopedRunnableMethodFactory<RenderThread>(this)); @@ -158,24 +124,13 @@ void RenderThread::Init() { #endif } -void RenderThread::CleanUp() { +RenderThread::~RenderThread() { // Shutdown in reverse of the initialization order. RemoveFilter(devtools_agent_filter_.get()); - devtools_agent_filter_ = NULL; WebAppCacheContext::SetFactory(NULL); - app_cache_dispatcher_.reset(); - histogram_snapshots_.reset(); - dns_master_.reset(); - user_script_slave_.reset(); - visited_link_slave_.reset(); - - if (webkit_client_.get()) { + if (webkit_client_.get()) WebKit::shutdown(); - webkit_client_.reset(); - } - notification_service_.reset(); - ChildThread::CleanUp(); lazy_tls.Pointer()->Set(NULL); // TODO(port) @@ -188,6 +143,26 @@ void RenderThread::CleanUp() { #endif } +RenderThread* RenderThread::current() { + return lazy_tls.Pointer()->Get(); +} + +void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { + channel()->AddFilter(filter); +} + +void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { + channel()->RemoveFilter(filter); +} + +void RenderThread::Resolve(const char* name, size_t length) { + return dns_master_->Resolve(name, length); +} + +void RenderThread::SendHistograms(int sequence_number) { + return histogram_snapshots_->SendHistograms(sequence_number); +} + void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) { DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle"; visited_link_slave_->Init(table); @@ -274,8 +249,6 @@ void RenderThread::OnCreateNewView(gfx::NativeViewId parent_hwnd, true, false); #endif - // TODO(darin): once we have a RenderThread per RenderView, this will need to - // change to assert that we are not creating more than one view. RenderView::Create( this, parent_hwnd, waitable_event, MSG_ROUTING_NONE, renderer_prefs, webkit_prefs, new SharedRenderViewCounter(0), view_id); diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 5ced914..d2a1fcd 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -20,7 +20,7 @@ class AppCacheDispatcher; class DevToolsAgentFilter; class FilePath; class ListValue; -class NotificationService; + class RenderDnsMaster; class RendererHistogram; class RendererWebKitClientImpl; @@ -114,9 +114,7 @@ class RenderThread : public RenderThreadBase, private: virtual void OnControlMessageReceived(const IPC::Message& msg); - // Called by the thread base class. - virtual void Init(); - virtual void CleanUp(); + void Init(); void OnUpdateVisitedLinks(base::SharedMemoryHandle table); void OnAddVisitedLinks(const VisitedLinkSlave::Fingerprints& fingerprints); @@ -154,23 +152,14 @@ class RenderThread : public RenderThreadBase, void EnsureWebKitInitialized(); // These objects live solely on the render thread. + scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > cache_stats_factory_; scoped_ptr<VisitedLinkSlave> visited_link_slave_; - scoped_ptr<UserScriptSlave> user_script_slave_; - scoped_ptr<RenderDnsMaster> dns_master_; - - scoped_ptr<RendererHistogramSnapshots> histogram_snapshots_; - - scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > cache_stats_factory_; - - scoped_ptr<NotificationService> notification_service_; - - scoped_ptr<RendererWebKitClientImpl> webkit_client_; - scoped_ptr<AppCacheDispatcher> app_cache_dispatcher_; - scoped_refptr<DevToolsAgentFilter> devtools_agent_filter_; + scoped_ptr<RendererHistogramSnapshots> histogram_snapshots_; + scoped_ptr<RendererWebKitClientImpl> webkit_client_; #if defined(OS_POSIX) scoped_refptr<IPC::ChannelProxy::MessageFilter> diff --git a/chrome/renderer/render_thread_unittest.cc b/chrome/renderer/render_thread_unittest.cc index 76491fe..e22cabb 100644 --- a/chrome/renderer/render_thread_unittest.cc +++ b/chrome/renderer/render_thread_unittest.cc @@ -18,7 +18,8 @@ class RenderThreadTest : public testing::Test { virtual void SetUp() { // Need a MODE_SERVER to make MODE_CLIENTs (like a RenderThread) happy. channel_ = new IPC::Channel(kThreadName, IPC::Channel::MODE_SERVER, NULL); - mock_process_.reset(new MockProcess(new RenderThread(kThreadName))); + mock_process_.reset(new MockProcess()); + mock_process_->set_main_thread(new RenderThread(kThreadName)); } virtual void TearDown() { @@ -34,15 +35,13 @@ class RenderThreadTest : public testing::Test { } protected: - MessageLoopForIO message_loop_; + MessageLoop message_loop_; scoped_ptr<MockProcess> mock_process_; IPC::Channel *channel_; }; TEST_F(RenderThreadTest, TestGlobal) { - // Can't reach the RenderThread object on other threads, since it's not - // thread-safe! - ASSERT_FALSE(RenderThread::current()); + ASSERT_TRUE(RenderThread::current()); } TEST_F(RenderThreadTest, TestVisitedMsg) { @@ -55,7 +54,7 @@ TEST_F(RenderThreadTest, TestVisitedMsg) { ASSERT_TRUE(msg); // Message goes nowhere, but this confirms Init() has happened. // Unusually (?), RenderThread() Start()s itself in it's constructor. - mock_process_->child_thread()->Send(msg); + mock_process_->main_thread()->Send(msg); // No need to delete msg; per Message::Send() documentation, "The // implementor takes ownership of the given Message regardless of diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 21c40e2..fd8f61a 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2814,14 +2814,6 @@ std::string RenderView::GetAltHTMLForTemplate( template_html, &error_strings, "t"); } -MessageLoop* RenderView::GetMessageLoopForIO() { - // Assume that we have only one RenderThread in the process and the owner loop - // of RenderThread is an IO message loop. - if (RenderThread::current()) - return RenderThread::current()->owner_loop(); - return NULL; -} - void RenderView::OnMoveOrResizeStarted() { if (webview()) webview()->HideAutofillPopup(); diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 7624620..d83bab9 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -360,12 +360,6 @@ class RenderView : public RenderWidget, delay_seconds_for_form_state_sync_ = delay_in_seconds; } - // Returns a message loop of type IO that can be used to run I/O jobs. The - // renderer thread is of type TYPE_DEFAULT, so doesn't support everything - // needed by some consumers. The returned thread will be the main thread of - // the renderer, which processes all IPC, to any I/O should be non-blocking. - MessageLoop* GetMessageLoopForIO(); - AudioMessageFilter* audio_message_filter() { return audio_message_filter_; } void OnClearFocusedNode(); diff --git a/chrome/renderer/renderer_main.cc b/chrome/renderer/renderer_main.cc index f5d7811..55234ec 100644 --- a/chrome/renderer/renderer_main.cc +++ b/chrome/renderer/renderer_main.cc @@ -22,6 +22,7 @@ #include "chrome/common/main_function_params.h" #include "chrome/renderer/renderer_main_platform_delegate.h" #include "chrome/renderer/render_process.h" +#include "chrome/renderer/render_thread.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -96,8 +97,11 @@ int RendererMain(const MainFunctionParams& parameters) { StatsScope<StatsCounterTimer> startup_timer(chrome::Counters::renderer_main()); - // The main thread of the renderer services IO. - MessageLoopForIO main_message_loop; + // The main message loop of the renderer services doesn't have IO or UI tasks, + // unless in-process-plugins is used. + MessageLoop main_message_loop(RenderProcess::InProcessPlugins() ? + MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT); + std::wstring app_name = chrome::kBrowserAppName; PlatformThread::SetName(WideToASCII(app_name + L"_RendererMain").c_str()); @@ -128,6 +132,7 @@ int RendererMain(const MainFunctionParams& parameters) { { RenderProcess render_process; + render_process.set_main_thread(new RenderThread()); bool run_loop = true; if (!no_sandbox) { run_loop = platform.EnableSandbox(); diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 34a728d..233749b9 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -237,10 +237,9 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn, IPC::AddChannelSocket(channel_handle.name, channel_handle.socket.fd); #endif - MessageLoop* ipc_message_loop = RenderThread::current()->owner_loop(); scoped_refptr<PluginChannelHost> channel_host = - PluginChannelHost::GetPluginChannelHost(channel_handle.name, - ipc_message_loop); + PluginChannelHost::GetPluginChannelHost( + channel_handle.name, ChildProcess::current()->io_message_loop()); if (!channel_host.get()) return false; diff --git a/chrome/utility/utility_main.cc b/chrome/utility/utility_main.cc index ad66043c..bb669a7 100644 --- a/chrome/utility/utility_main.cc +++ b/chrome/utility/utility_main.cc @@ -20,15 +20,16 @@ // Mainline routine for running as the utility process. int UtilityMain(const MainFunctionParams& parameters) { - // The main thread of the render process. - MessageLoopForIO main_message_loop; + // The main message loop of the utility process. + MessageLoop main_message_loop; std::wstring app_name = chrome::kBrowserAppName; PlatformThread::SetName(WideToASCII(app_name + L"_UtilityMain").c_str()); // Initialize the SystemMonitor base::SystemMonitor::Start(); - ChildProcess utility_process(new UtilityThread()); + ChildProcess utility_process; + utility_process.set_main_thread(new UtilityThread()); #if defined(OS_WIN) sandbox::TargetServices* target_services = parameters.sandbox_info_.TargetServices(); diff --git a/chrome/utility/utility_thread.cc b/chrome/utility/utility_thread.cc index 46815b1..dc9f965 100644 --- a/chrome/utility/utility_thread.cc +++ b/chrome/utility/utility_thread.cc @@ -11,20 +11,11 @@ #include "chrome/common/extensions/extension_unpacker.h" #include "chrome/common/render_messages.h" -UtilityThread::UtilityThread() : ChildThread(base::Thread::Options()) { -} - -UtilityThread::~UtilityThread() { -} - -void UtilityThread::Init() { - ChildThread::Init(); +UtilityThread::UtilityThread() { ChildProcess::current()->AddRefProcess(); } -void UtilityThread::CleanUp() { - // Shutdown in reverse of the initialization order. - ChildThread::CleanUp(); +UtilityThread::~UtilityThread() { } void UtilityThread::OnControlMessageReceived(const IPC::Message& msg) { diff --git a/chrome/utility/utility_thread.h b/chrome/utility/utility_thread.h index 1c128ad..4fad53e 100644 --- a/chrome/utility/utility_thread.h +++ b/chrome/utility/utility_thread.h @@ -7,7 +7,6 @@ #include <string> -#include "base/thread.h" #include "chrome/common/child_thread.h" class GURL; @@ -31,10 +30,6 @@ class UtilityThread : public ChildThread { // IPC messages for web resource service. void OnUnpackWebResource(const std::string& resource_data); - // Called by the thread base class - virtual void Init(); - virtual void CleanUp(); - DISALLOW_COPY_AND_ASSIGN(UtilityThread); }; diff --git a/chrome/worker/worker_main.cc b/chrome/worker/worker_main.cc index 03831b8b..d6304ab 100644 --- a/chrome/worker/worker_main.cc +++ b/chrome/worker/worker_main.cc @@ -20,15 +20,16 @@ // Mainline routine for running as the worker process. int WorkerMain(const MainFunctionParams& parameters) { - // The main thread of the render process. - MessageLoopForIO main_message_loop; + // The main message loop of the worker process. + MessageLoop main_message_loop; std::wstring app_name = chrome::kBrowserAppName; PlatformThread::SetName(WideToASCII(app_name + L"_WorkerMain").c_str()); // Initialize the SystemMonitor base::SystemMonitor::Start(); - ChildProcess worker_process(new WorkerThread()); + ChildProcess worker_process; + worker_process.set_main_thread(new WorkerThread()); #if defined(OS_WIN) sandbox::TargetServices* target_services = parameters.sandbox_info_.TargetServices(); diff --git a/chrome/worker/worker_thread.cc b/chrome/worker/worker_thread.cc index 7663b7a..e4be0b9 100644 --- a/chrome/worker/worker_thread.cc +++ b/chrome/worker/worker_thread.cc @@ -15,37 +15,22 @@ static base::LazyInstance<base::ThreadLocalPointer<WorkerThread> > lazy_tls( base::LINKER_INITIALIZED); -WorkerThread::WorkerThread() - : ChildThread(base::Thread::Options(MessageLoop::TYPE_DEFAULT, - kV8StackSize)) { -} - -WorkerThread::~WorkerThread() { -} - -WorkerThread* WorkerThread::current() { - return lazy_tls.Pointer()->Get(); -} - -void WorkerThread::Init() { +WorkerThread::WorkerThread() { lazy_tls.Pointer()->Set(this); - ChildThread::Init(); webkit_client_.reset(new WorkerWebKitClientImpl); WebKit::initialize(webkit_client_.get()); } -void WorkerThread::CleanUp() { +WorkerThread::~WorkerThread() { // Shutdown in reverse of the initialization order. - - if (webkit_client_.get()) { - WebKit::shutdown(); - webkit_client_.reset(); - } - - ChildThread::CleanUp(); + WebKit::shutdown(); lazy_tls.Pointer()->Set(NULL); } +WorkerThread* WorkerThread::current() { + return lazy_tls.Pointer()->Get(); +} + void WorkerThread::OnControlMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg) IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateWorker) diff --git a/chrome/worker/worker_thread.h b/chrome/worker/worker_thread.h index 6bea33c..27d0abf 100644 --- a/chrome/worker/worker_thread.h +++ b/chrome/worker/worker_thread.h @@ -5,7 +5,6 @@ #ifndef CHROME_WORKER_WORKER_THREAD_H_ #define CHROME_WORKER_WORKER_THREAD_H_ -#include "base/thread.h" #include "chrome/common/child_thread.h" class GURL; @@ -22,10 +21,6 @@ class WorkerThread : public ChildThread { private: virtual void OnControlMessageReceived(const IPC::Message& msg); - // Called by the thread base class - virtual void Init(); - virtual void CleanUp(); - void OnCreateWorker(const GURL& url, int route_id); scoped_ptr<WorkerWebKitClientImpl> webkit_client_; |