diff options
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/mock_render_process.h | 3 | ||||
-rw-r--r-- | chrome/renderer/render_process.cc | 51 | ||||
-rw-r--r-- | chrome/renderer/render_process.h | 8 | ||||
-rw-r--r-- | chrome/renderer/render_process_unittest.cc | 2 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 99 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 21 | ||||
-rw-r--r-- | chrome/renderer/render_thread_unittest.cc | 11 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 6 | ||||
-rw-r--r-- | chrome/renderer/renderer_main.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 5 |
11 files changed, 151 insertions, 72 deletions
diff --git a/chrome/renderer/mock_render_process.h b/chrome/renderer/mock_render_process.h index 49bc02c..629967f 100644 --- a/chrome/renderer/mock_render_process.h +++ b/chrome/renderer/mock_render_process.h @@ -14,7 +14,8 @@ class ChildThread; // a render widget instance. class MockProcess : public ChildProcess { public: - explicit MockProcess() : ChildProcess() {} + explicit MockProcess() : ChildProcess(NULL) {} + explicit MockProcess(ChildThread* thread) : ChildProcess(thread) {} }; #endif // CHROME_RENDERER_MOCK_RENDER_PROCESS_H_ diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index 2718d37..3fe22c5 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -47,10 +47,43 @@ static size_t GetMaxSharedMemorySize() { //----------------------------------------------------------------------------- RenderProcess::RenderProcess() - : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( + : ChildProcess(new RenderThread()), + 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; @@ -98,18 +131,6 @@ RenderProcess::RenderProcess() 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) @@ -136,7 +157,7 @@ TransportDIB* RenderProcess::CreateTransportDIB(size_t size) { // get one. TransportDIB::Handle handle; IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &handle); - if (!main_thread()->Send(msg)) + if (!child_thread()->Send(msg)) return NULL; if (handle.fd < 0) return NULL; @@ -152,7 +173,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()); - main_thread()->Send(msg); + child_thread()->Send(msg); #endif delete dib; diff --git a/chrome/renderer/render_process.h b/chrome/renderer/render_process.h index d445fbe..727aae5 100644 --- a/chrome/renderer/render_process.h +++ b/chrome/renderer/render_process.h @@ -21,7 +21,11 @@ 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 @@ -48,10 +52,14 @@ 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 5692d81..feac0aa 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()); + render_process_.reset(new RenderProcess(kThreadName)); } virtual void TearDown() { diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 80811b2..e35377a 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -17,6 +17,7 @@ #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) @@ -54,10 +55,54 @@ 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()); } @@ -83,18 +128,6 @@ 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); @@ -105,7 +138,8 @@ void RenderThread::Init() { CoInitialize(0); #endif - plugin_refresh_allowed_ = true; + ChildThread::Init(); + notification_service_.reset(new NotificationService); cache_stats_factory_.reset( new ScopedRunnableMethodFactory<RenderThread>(this)); @@ -124,13 +158,24 @@ void RenderThread::Init() { #endif } -RenderThread::~RenderThread() { +void RenderThread::CleanUp() { // Shutdown in reverse of the initialization order. RemoveFilter(devtools_agent_filter_.get()); + devtools_agent_filter_ = NULL; WebAppCacheContext::SetFactory(NULL); - if (webkit_client_.get()) + app_cache_dispatcher_.reset(); + histogram_snapshots_.reset(); + dns_master_.reset(); + user_script_slave_.reset(); + visited_link_slave_.reset(); + + if (webkit_client_.get()) { WebKit::shutdown(); + webkit_client_.reset(); + } + notification_service_.reset(); + ChildThread::CleanUp(); lazy_tls.Pointer()->Set(NULL); // TODO(port) @@ -143,26 +188,6 @@ RenderThread::~RenderThread() { #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); @@ -249,6 +274,8 @@ 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 d2a1fcd..5ced914 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,7 +114,9 @@ class RenderThread : public RenderThreadBase, private: virtual void OnControlMessageReceived(const IPC::Message& msg); - void Init(); + // Called by the thread base class. + virtual void Init(); + virtual void CleanUp(); void OnUpdateVisitedLinks(base::SharedMemoryHandle table); void OnAddVisitedLinks(const VisitedLinkSlave::Fingerprints& fingerprints); @@ -152,15 +154,24 @@ 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<AppCacheDispatcher> app_cache_dispatcher_; - scoped_refptr<DevToolsAgentFilter> devtools_agent_filter_; + 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_; + #if defined(OS_POSIX) scoped_refptr<IPC::ChannelProxy::MessageFilter> suicide_on_channel_error_filter_; diff --git a/chrome/renderer/render_thread_unittest.cc b/chrome/renderer/render_thread_unittest.cc index e22cabb..76491fe 100644 --- a/chrome/renderer/render_thread_unittest.cc +++ b/chrome/renderer/render_thread_unittest.cc @@ -18,8 +18,7 @@ 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()); - mock_process_->set_main_thread(new RenderThread(kThreadName)); + mock_process_.reset(new MockProcess(new RenderThread(kThreadName))); } virtual void TearDown() { @@ -35,13 +34,15 @@ class RenderThreadTest : public testing::Test { } protected: - MessageLoop message_loop_; + MessageLoopForIO message_loop_; scoped_ptr<MockProcess> mock_process_; IPC::Channel *channel_; }; TEST_F(RenderThreadTest, TestGlobal) { - ASSERT_TRUE(RenderThread::current()); + // Can't reach the RenderThread object on other threads, since it's not + // thread-safe! + ASSERT_FALSE(RenderThread::current()); } TEST_F(RenderThreadTest, TestVisitedMsg) { @@ -54,7 +55,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_->main_thread()->Send(msg); + mock_process_->child_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 fd8f61a..21c40e2 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2814,6 +2814,14 @@ 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 d83bab9..7624620 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -360,6 +360,12 @@ 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 55234ec..f5d7811 100644 --- a/chrome/renderer/renderer_main.cc +++ b/chrome/renderer/renderer_main.cc @@ -22,7 +22,6 @@ #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" @@ -97,11 +96,8 @@ int RendererMain(const MainFunctionParams& parameters) { StatsScope<StatsCounterTimer> startup_timer(chrome::Counters::renderer_main()); - // 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); - + // The main thread of the renderer services IO. + MessageLoopForIO main_message_loop; std::wstring app_name = chrome::kBrowserAppName; PlatformThread::SetName(WideToASCII(app_name + L"_RendererMain").c_str()); @@ -132,7 +128,6 @@ 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 233749b9..34a728d 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -237,9 +237,10 @@ 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, ChildProcess::current()->io_message_loop()); + PluginChannelHost::GetPluginChannelHost(channel_handle.name, + ipc_message_loop); if (!channel_host.get()) return false; |