diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 07:15:17 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 07:15:17 +0000 |
commit | ea51de3307a6a5947ca047fa9d0e20359fdcf658 (patch) | |
tree | c1a49c1d41c4bfbf74ddbc28c371f840dd2848fa /chrome/renderer | |
parent | b6aedfff89cd93f07c1c38a13062801e81bf26e4 (diff) | |
download | chromium_src-ea51de3307a6a5947ca047fa9d0e20359fdcf658.zip chromium_src-ea51de3307a6a5947ca047fa9d0e20359fdcf658.tar.gz chromium_src-ea51de3307a6a5947ca047fa9d0e20359fdcf658.tar.bz2 |
Reverting 10080.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10082 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/chrome_plugin_host.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/mock_render_process.h | 12 | ||||
-rw-r--r-- | chrome/renderer/net/render_dns_master.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/render_process.cc | 78 | ||||
-rw-r--r-- | chrome/renderer/render_process.h | 46 | ||||
-rw-r--r-- | chrome/renderer/render_process_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 126 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 70 | ||||
-rw-r--r-- | chrome/renderer/render_thread_unittest.cc | 23 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 17 | ||||
-rw-r--r-- | chrome/renderer/render_view_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 16 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 2 | ||||
-rw-r--r-- | chrome/renderer/render_widget_unittest.cc | 11 | ||||
-rw-r--r-- | chrome/renderer/renderer_glue.cc | 48 | ||||
-rw-r--r-- | chrome/renderer/renderer_main.cc | 7 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 4 |
17 files changed, 294 insertions, 200 deletions
diff --git a/chrome/renderer/chrome_plugin_host.cc b/chrome/renderer/chrome_plugin_host.cc index 9d437c0..6f793b7 100644 --- a/chrome/renderer/chrome_plugin_host.cc +++ b/chrome/renderer/chrome_plugin_host.cc @@ -320,7 +320,7 @@ int STDCALL CPB_GetBrowsingContextInfo( return sizeof(char*); std::wstring wretval; - if (!RenderThread::current()->Send(new ViewHostMsg_GetDataDir(&wretval))) + if (!g_render_thread->Send(new ViewHostMsg_GetDataDir(&wretval))) return CPERR_FAILURE; file_util::AppendToPath(&wretval, chrome::kChromePluginDataDirname); *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, WideToUTF8(wretval)); @@ -491,8 +491,8 @@ CPError STDCALL CPB_SendMessage(CPID id, const void *data, uint32 data_len) { const uint8* data_ptr = static_cast<const uint8*>(data); std::vector<uint8> v(data_ptr, data_ptr + data_len); - if (!RenderThread::current()->Send( - new ViewHostMsg_PluginMessage(plugin->filename(), v))) { + if (!g_render_thread->Send(new ViewHostMsg_PluginMessage(plugin->filename(), + v))) { return CPERR_FAILURE; } return CPERR_SUCCESS; @@ -507,7 +507,7 @@ CPError STDCALL CPB_SendSyncMessage(CPID id, const void *data, uint32 data_len, const uint8* data_ptr = static_cast<const uint8*>(data); std::vector<uint8> v(data_ptr, data_ptr + data_len); std::vector<uint8> r; - if (!RenderThread::current()->Send(new ViewHostMsg_PluginSyncMessage( + if (!g_render_thread->Send(new ViewHostMsg_PluginSyncMessage( plugin->filename(), v, &r))) { return CPERR_FAILURE; } diff --git a/chrome/renderer/mock_render_process.h b/chrome/renderer/mock_render_process.h index 629967f..d7bd178 100644 --- a/chrome/renderer/mock_render_process.h +++ b/chrome/renderer/mock_render_process.h @@ -5,17 +5,21 @@ #ifndef CHROME_RENDERER_MOCK_RENDER_PROCESS_H_ #define CHROME_RENDERER_MOCK_RENDER_PROCESS_H_ -#include "chrome/common/child_process.h" +#include <string> -class ChildThread; +#include "chrome/common/child_process.h" // This class is a trivial mock of the child process singleton. It is necessary // so we don't trip DCHECKs in ChildProcess::ReleaseProcess() when destroying // a render widget instance. class MockProcess : public ChildProcess { public: - explicit MockProcess() : ChildProcess(NULL) {} - explicit MockProcess(ChildThread* thread) : ChildProcess(thread) {} + explicit MockProcess(const std::wstring& channel_name) {} + static void GlobalInit() { + ChildProcessFactory<MockProcess> factory; + ChildProcess::GlobalInit(L"dummy", &factory); + } }; #endif // CHROME_RENDERER_MOCK_RENDER_PROCESS_H_ + diff --git a/chrome/renderer/net/render_dns_master.cc b/chrome/renderer/net/render_dns_master.cc index b62b6ca..beacec6 100644 --- a/chrome/renderer/net/render_dns_master.cc +++ b/chrome/renderer/net/render_dns_master.cc @@ -19,7 +19,7 @@ // This API is used in the render process by renderer_glue.cc. // IF you are in the render process, you MUST be on the renderer thread to call. void DnsPrefetchCString(const char* hostname, size_t length) { - RenderThread::current()->Resolve(hostname, length); + g_render_thread->Resolve(hostname, length); } // The number of hostnames submitted to Browser DNS resolver per call to @@ -55,7 +55,7 @@ void RenderDnsMaster::Resolve(const char* name, size_t length) { if (0 != old_size) return; // Overkill safety net: Don't send too many InvokeLater's. render_dns_factory_.RevokeAll(); - RenderThread::current()->message_loop()->PostDelayedTask(FROM_HERE, + g_render_thread->message_loop()->PostDelayedTask(FROM_HERE, render_dns_factory_.NewRunnableMethod( &RenderDnsMaster::SubmitHostnames), 10); } @@ -89,7 +89,7 @@ void RenderDnsMaster::SubmitHostnames() { DnsPrefetchNames(kMAX_SUBMISSION_PER_TASK); if (new_name_count_ > 0 || 0 < c_string_queue_.Size()) { render_dns_factory_.RevokeAll(); - RenderThread::current()->message_loop()->PostDelayedTask(FROM_HERE, + g_render_thread->message_loop()->PostDelayedTask(FROM_HERE, render_dns_factory_.NewRunnableMethod( &RenderDnsMaster::SubmitHostnames), 10); } else { @@ -145,7 +145,7 @@ void RenderDnsMaster::DnsPrefetchNames(size_t max_count) { new_name_count_ -= names.size(); DCHECK(new_name_count_ >= 0); - RenderThread::current()->Send(new ViewHostMsg_DnsPrefetch(names)); + g_render_thread->Send(new ViewHostMsg_DnsPrefetch(names)); } // is_numeric_ip() checks to see if all characters in name are either numeric, diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index ff1cd33..198f854f 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -29,48 +29,34 @@ #include "chrome/renderer/render_view.h" #include "webkit/glue/webkit_glue.h" +//----------------------------------------------------------------------------- -RenderProcess::RenderProcess() - : ChildProcess(new RenderThread()), - ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( - base::TimeDelta::FromSeconds(5), - this, &RenderProcess::ClearTransportDIBCache)), - sequence_number_(0) { - Init(); -} +bool RenderProcess::load_plugins_in_process_ = false; + +//----------------------------------------------------------------------------- RenderProcess::RenderProcess(const std::wstring& channel_name) - : ChildProcess(new RenderThread(channel_name)), + : render_thread_(channel_name), ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( base::TimeDelta::FromSeconds(5), this, &RenderProcess::ClearTransportDIBCache)), sequence_number_(0) { - Init(); + for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) + shared_mem_cache_[i] = NULL; } 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 - // 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(); + render_thread_.Stop(); ClearTransportDIBCache(); } -void RenderProcess::Init() { - in_process_plugins_ = InProcessPlugins(); - in_process_gears_ = false; - for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) - shared_mem_cache_[i] = NULL; - +// static +bool RenderProcess::GlobalInit(const std::wstring &channel_name) { #if defined(OS_WIN) // HACK: See http://b/issue?id=1024307 for rationale. if (GetModuleHandle(L"LPK.DLL") == NULL) { @@ -98,6 +84,10 @@ void RenderProcess::Init() { webkit_glue::SetRecordPlaybackMode(true); } + if (command_line.HasSwitch(switches::kInProcessPlugins) || + command_line.HasSwitch(switches::kSingleProcess)) + load_plugins_in_process_ = true; + if (command_line.HasSwitch(switches::kEnableWatchdog)) { // TODO(JAR): Need to implement renderer IO msgloop watchdog. } @@ -108,7 +98,6 @@ void RenderProcess::Init() { if (command_line.HasSwitch(switches::kGearsInRenderer)) { #if defined(OS_WIN) - in_process_gears_ = true; // Load gears.dll on startup so we can access it before the sandbox // blocks us. std::wstring path; @@ -124,12 +113,19 @@ void RenderProcess::Init() { // TODO(scherkus): check for any DLL dependencies. webkit_glue::SetMediaPlayerAvailable(true); } + + ChildProcessFactory<RenderProcess> factory; + return ChildProcess::GlobalInit(channel_name, &factory); } -bool RenderProcess::InProcessPlugins() { - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - return command_line.HasSwitch(switches::kInProcessPlugins) || - command_line.HasSwitch(switches::kSingleProcess); +// static +void RenderProcess::GlobalCleanup() { + ChildProcess::GlobalCleanup(); +} + +// static +bool RenderProcess::ShouldLoadPluginsInProcess() { + return load_plugins_in_process_; } // ----------------------------------------------------------------------------- @@ -159,7 +155,7 @@ TransportDIB* RenderProcess::CreateTransportDIB(size_t size) { // get one. IPC::Maybe<TransportDIB::Handle> mhandle; IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &mhandle); - if (!child_thread()->Send(msg)) + if (!render_thread_.Send(msg)) return NULL; if (!mhandle.valid) return NULL; @@ -175,7 +171,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); + render_thread_.Send(msg); #endif delete dib; @@ -184,13 +180,14 @@ void RenderProcess::FreeTransportDIB(TransportDIB* dib) { // ----------------------------------------------------------------------------- +// static skia::PlatformCanvas* RenderProcess::GetDrawingCanvas( TransportDIB** memory, const gfx::Rect& rect) { const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width()); const size_t size = stride * rect.height(); - if (!GetTransportDIBFromCache(memory, size)) { - *memory = CreateTransportDIB(size); + if (!self()->GetTransportDIBFromCache(memory, size)) { + *memory = self()->CreateTransportDIB(size); if (!*memory) return false; } @@ -198,13 +195,14 @@ skia::PlatformCanvas* RenderProcess::GetDrawingCanvas( return CanvasFromTransportDIB(*memory, rect); } +// static void RenderProcess::ReleaseTransportDIB(TransportDIB* mem) { - if (PutSharedMemInCache(mem)) { - shared_mem_cache_cleaner_.Reset(); + if (self()->PutSharedMemInCache(mem)) { + self()->shared_mem_cache_cleaner_.Reset(); return; } - FreeTransportDIB(mem); + self()->FreeTransportDIB(mem); } bool RenderProcess::GetTransportDIBFromCache(TransportDIB** mem, @@ -268,3 +266,11 @@ void RenderProcess::ClearTransportDIBCache() { } } +void RenderProcess::Cleanup() { + // 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 +} diff --git a/chrome/renderer/render_process.h b/chrome/renderer/render_process.h index a4bc0ff5..9c4cabe 100644 --- a/chrome/renderer/render_process.h +++ b/chrome/renderer/render_process.h @@ -21,12 +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::wstring& channel_name); + static bool GlobalInit(const std::wstring& channel_name); + static void GlobalCleanup(); - ~RenderProcess(); + // Returns true if plugins should be loaded in-process. + static bool ShouldLoadPluginsInProcess(); // Get a canvas suitable for drawing and transporting to the browser // memory: (output) the transport DIB memory @@ -35,31 +34,25 @@ class RenderProcess : public ChildProcess { // // When no longer needed, you should pass the TransportDIB to // ReleaseTransportDIB so that it can be recycled. - skia::PlatformCanvas* GetDrawingCanvas( + static skia::PlatformCanvas* GetDrawingCanvas( TransportDIB** memory, const gfx::Rect& rect); // Frees shared memory allocated by AllocSharedMemory. You should only use // this function to free the SharedMemory object. - void ReleaseTransportDIB(TransportDIB* memory); + static void ReleaseTransportDIB(TransportDIB* memory); - // Returns true if plugins should be loaded in-process. - bool in_process_plugins() const { return in_process_plugins_; } - - // Returns true if Gears should be loaded in-process. - bool in_process_gears() const { return in_process_gears_; } + private: + friend class ChildProcessFactory<RenderProcess>; + explicit RenderProcess(const std::wstring& channel_name); + ~RenderProcess(); - // Returns a pointer to the RenderProcess singleton instance. - static RenderProcess* current() { - return static_cast<RenderProcess*>(ChildProcess::current()); + // Returns a pointer to the RenderProcess singleton instance. This is + // guaranteed to be non-NULL between calls to GlobalInit and GlobalCleanup. + static RenderProcess* self() { + return static_cast<RenderProcess*>(child_process_); } - protected: - friend class RenderThread; - // Just like in_process_plugins(), but called before RenderProcess is created. - static bool InProcessPlugins(); - - private: - void Init(); + static ChildProcess* ClassFactory(const std::wstring& channel_name); // Look in the shared memory cache for a suitable object to reuse. // result: (output) the memory found @@ -84,6 +77,12 @@ class RenderProcess : public ChildProcess { TransportDIB* CreateTransportDIB(size_t size); void FreeTransportDIB(TransportDIB*); + // ChildProcess implementation + virtual void Cleanup(); + + // The one render thread (to be replaced with a set of render threads). + RenderThread render_thread_; + // A very simplistic and small cache. If an entry in this array is non-null, // then it points to a SharedMemory object that is available for reuse. TransportDIB* shared_mem_cache_[2]; @@ -94,8 +93,7 @@ class RenderProcess : public ChildProcess { // TransportDIB sequence number uint32 sequence_number_; - bool in_process_plugins_; - bool in_process_gears_; + static bool load_plugins_in_process_; DISALLOW_COPY_AND_ASSIGN(RenderProcess); }; diff --git a/chrome/renderer/render_process_unittest.cc b/chrome/renderer/render_process_unittest.cc index 7859d8f..4f77d5d 100644 --- a/chrome/renderer/render_process_unittest.cc +++ b/chrome/renderer/render_process_unittest.cc @@ -13,16 +13,15 @@ namespace { class RenderProcessTest : public testing::Test { public: virtual void SetUp() { - render_process_.reset(new RenderProcess(L"render_process_unittest")); + RenderProcess::GlobalInit(L"render_process_unittest"); } virtual void TearDown() { - render_process_.reset(); + RenderProcess::GlobalCleanup(); } private: MessageLoopForIO message_loop_; - scoped_ptr<RenderProcess> render_process_; }; @@ -31,10 +30,10 @@ TEST_F(RenderProcessTest, TestTransportDIBAllocation) { #if !defined(OS_MACOSX) const gfx::Rect rect(0, 0, 100, 100); TransportDIB* dib; - skia::PlatformCanvas* canvas = RenderProcess::current()->GetDrawingCanvas(&dib, rect); + skia::PlatformCanvas* canvas = RenderProcess::GetDrawingCanvas(&dib, rect); ASSERT_TRUE(dib); ASSERT_TRUE(canvas); - RenderProcess::current()->ReleaseTransportDIB(dib); + RenderProcess::ReleaseTransportDIB(dib); delete canvas; #endif } diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 58de4ef..2937935 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -14,9 +14,9 @@ #include "base/shared_memory.h" #include "chrome/common/chrome_plugin_lib.h" +#include "chrome/common/ipc_logging.h" #include "chrome/common/render_messages.h" #include "chrome/common/notification_service.h" -#include "chrome/plugin/npobject_util.h" // TODO(port) #if defined(OS_WIN) #include "chrome/plugin/plugin_channel.h" @@ -34,6 +34,8 @@ #include "webkit/glue/cache_manager.h" +RenderThread* g_render_thread; + static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; // V8 needs a 1MB stack size. @@ -42,53 +44,78 @@ static const size_t kStackSize = 1024 * 1024; //----------------------------------------------------------------------------- // 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, kStackSize)), - visited_link_slave_(NULL), - user_script_slave_(NULL), - render_dns_master_(NULL) { -} - RenderThread::RenderThread(const std::wstring& channel_name) - : ChildThread( - base::Thread::Options(RenderProcess::InProcessPlugins() ? - MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kStackSize)), + : Thread("Chrome_RenderThread"), + owner_loop_(MessageLoop::current()), + channel_name_(channel_name), visited_link_slave_(NULL), user_script_slave_(NULL), - render_dns_master_(NULL) { - SetChannelName(channel_name); + render_dns_master_(NULL), + in_send_(0) { + DCHECK(owner_loop_); + base::Thread::Options options; + options.stack_size = kStackSize; + // 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. + if (RenderProcess::ShouldLoadPluginsInProcess()) + options.message_loop_type = MessageLoop::TYPE_UI; + StartWithOptions(options); } RenderThread::~RenderThread() { + Stop(); } -RenderThread* RenderThread::current() { - DCHECK(!IsPluginProcess()); - return static_cast<RenderThread*>(ChildThread::current()); +void RenderThread::OnChannelError() { + owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); +} + +bool RenderThread::Send(IPC::Message* msg) { + in_send_++; + bool rv = channel_->Send(msg); + in_send_--; + return rv; } void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { - channel()->AddFilter(filter); + channel_->AddFilter(filter); } void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { - channel()->RemoveFilter(filter); + channel_->RemoveFilter(filter); } void RenderThread::Resolve(const char* name, size_t length) { return render_dns_master_->Resolve(name, length); } +void RenderThread::AddRoute(int32 routing_id, + IPC::Channel::Listener* listener) { + DCHECK(MessageLoop::current() == message_loop()); + + // This corresponds to the AddRoute call done in CreateView. + router_.AddRoute(routing_id, listener); +} + +void RenderThread::RemoveRoute(int32 routing_id) { + DCHECK(MessageLoop::current() == message_loop()); + + router_.RemoveRoute(routing_id); +} + void RenderThread::Init() { - ChildThread::Init(); + DCHECK(!g_render_thread); + g_render_thread = this; + notification_service_.reset(new NotificationService); + cache_stats_factory_.reset( new ScopedRunnableMethodFactory<RenderThread>(this)); + channel_.reset(new IPC::SyncChannel(channel_name_, + IPC::Channel::MODE_CLIENT, this, NULL, owner_loop_, true, + RenderProcess::GetShutDownEvent())); + #if defined(OS_WIN) // The renderer thread should wind-up COM. CoInitialize(0); @@ -97,10 +124,19 @@ void RenderThread::Init() { visited_link_slave_ = new VisitedLinkSlave(); user_script_slave_ = new UserScriptSlave(); render_dns_master_.reset(new RenderDnsMaster()); + +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::current()->SetIPCSender(this); +#endif } void RenderThread::CleanUp() { - ChildThread::CleanUp(); + DCHECK(g_render_thread == this); + g_render_thread = NULL; + + // Need to destruct the SyncChannel to the browser before we go away because + // it caches a pointer to this thread. + channel_.reset(); // TODO(port) #if defined(OS_WIN) @@ -108,6 +144,10 @@ void RenderThread::CleanUp() { PluginChannelBase::CleanupChannels(); #endif +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::current()->SetIPCSender(NULL); +#endif + notification_service_.reset(); delete visited_link_slave_; @@ -132,20 +172,30 @@ void RenderThread::OnUpdateUserScripts( user_script_slave_->UpdateScripts(scripts); } -void RenderThread::OnControlMessageReceived(const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(RenderThread, msg) - IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks) - IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID) - // TODO(port): removed from render_messages_internal.h; - // is there a new non-windows message I should add here? - IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView) - IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities) - IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats, - OnGetCacheResourceStats) - IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage) - IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_NewScripts, - OnUpdateUserScripts) - IPC_END_MESSAGE_MAP() +void RenderThread::OnMessageReceived(const IPC::Message& msg) { + // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but + // it seems simpler to just process any control messages that we care about + // up-front and then send the rest of the messages onto router_. + + if (msg.routing_id() == MSG_ROUTING_CONTROL) { + IPC_BEGIN_MESSAGE_MAP(RenderThread, msg) + IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks) + IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID) + // TODO(port): removed from render_messages_internal.h; + // is there a new non-windows message I should add here? + IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView) + IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities) + IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats, + OnGetCacheResourceStats) + IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage) + IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_NewScripts, + OnUpdateUserScripts) + // send the rest to the router + IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg)) + IPC_END_MESSAGE_MAP() + } else { + router_.OnMessageReceived(msg); + } } void RenderThread::OnPluginMessage(const FilePath& plugin_path, diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index a3bd534..44dd548 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -10,8 +10,10 @@ #include "base/gfx/native_widget_types.h" #include "base/shared_memory.h" #include "base/task.h" +#include "base/thread.h" #include "build/build_config.h" -#include "chrome/common/child_thread.h" +#include "chrome/common/ipc_sync_channel.h" +#include "chrome/common/message_router.h" class FilePath; class NotificationService; @@ -25,12 +27,10 @@ struct WebPreferences; // The RenderThreadBase is the minimal interface that a RenderView/Widget // expects from a render thread. The interface basically abstracts a way to send // and receive messages. -class RenderThreadBase { +class RenderThreadBase : public IPC::Message::Sender { public: virtual ~RenderThreadBase() {} - virtual bool Send(IPC::Message* msg) = 0; - // True if currently sending a message. virtual bool InSend() const = 0; @@ -52,35 +52,21 @@ class RenderThreadBase { // Most of the communication occurs in the form of IPC messages. They are // routed to the RenderThread according to the routing IDs of the messages. // The routing IDs correspond to RenderView instances. -class RenderThread : public RenderThreadBase, - public ChildThread { +class RenderThread : public IPC::Channel::Listener, + public RenderThreadBase, + public base::Thread { public: - // Grabs the IPC channel name from the command line. - RenderThread(); - // Constructor that's used when running in single process mode. - RenderThread(const std::wstring& channel_name); + explicit RenderThread(const std::wstring& channel_name); virtual ~RenderThread(); - // Returns the one render thread for this process. Note that this should only - // be accessed when running on the render thread itself - static RenderThread* current(); - - // Overridded from RenderThreadBase. - virtual bool Send(IPC::Message* msg) { - return ChildThread::Send(msg); - } - - virtual bool InSend() const { - return ChildThread::InSend(); - } + // IPC::Channel::Listener implementation: + virtual void OnMessageReceived(const IPC::Message& msg); + virtual void OnChannelError(); - virtual void AddRoute(int32 routing_id, IPC::Channel::Listener* listener) { - return ChildThread::AddRoute(routing_id, listener); - } - virtual void RemoveRoute(int32 routing_id) { - return ChildThread::RemoveRoute(routing_id); - } + // IPC::Message::Sender implementation: + virtual bool Send(IPC::Message* msg); + // Overridded from RenderThreadBase. virtual void AddFilter(IPC::ChannelProxy::MessageFilter* filter); virtual void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter); @@ -93,17 +79,25 @@ class RenderThread : public RenderThreadBase, // Do DNS prefetch resolution of a hostname. void Resolve(const char* name, size_t length); + // See documentation on MessageRouter for AddRoute and RemoveRoute + virtual void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); + virtual void RemoveRoute(int32 routing_id); + // Invokes InformHostOfCacheStats after a short delay. Used to move this // bookkeeping operation off the critical latency path. void InformHostOfCacheStatsLater(); - private: - virtual void OnControlMessageReceived(const IPC::Message& msg); + MessageLoop* owner_loop() { return owner_loop_; } + // Indicates if RenderThread::Send() is on the call stack. + virtual bool InSend() const { return in_send_ != 0; } + + protected: // Called by the thread base class virtual void Init(); virtual void CleanUp(); + private: void OnUpdateVisitedLinks(base::SharedMemoryHandle table); void OnUpdateUserScripts(base::SharedMemoryHandle table); @@ -125,6 +119,16 @@ class RenderThread : public RenderThreadBase, // decisions about how to allocation resources using current information. void InformHostOfCacheStats(); + // The message loop used to run tasks on the thread that started this thread. + MessageLoop* owner_loop_; + + // Used only on the background render thread to implement message routing + // functionality to the consumers of the RenderThread. + MessageRouter router_; + + std::wstring channel_name_; + scoped_ptr<IPC::SyncChannel> channel_; + // These objects live solely on the render thread. VisitedLinkSlave* visited_link_slave_; UserScriptSlave* user_script_slave_; @@ -135,7 +139,13 @@ class RenderThread : public RenderThreadBase, scoped_ptr<NotificationService> notification_service_; + int in_send_; + DISALLOW_COPY_AND_ASSIGN(RenderThread); }; +// The global RenderThread object for this process. Note that this should only +// be accessed when running on the render thread itself. +extern RenderThread* g_render_thread; + #endif // CHROME_RENDERER_RENDER_THREAD_H_ diff --git a/chrome/renderer/render_thread_unittest.cc b/chrome/renderer/render_thread_unittest.cc index 4192f68..12e6941 100644 --- a/chrome/renderer/render_thread_unittest.cc +++ b/chrome/renderer/render_thread_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/string_util.h" #include "base/waitable_event.h" #include "chrome/common/ipc_sync_channel.h" #include "chrome/common/render_messages.h" @@ -11,33 +12,39 @@ namespace { -const wchar_t kThreadName[] = L"render_thread_unittest"; +const char kThreadName[] = "render_thread_unittest"; class RenderThreadTest : public testing::Test { public: virtual void SetUp() { - mock_process_.reset(new MockProcess(new RenderThread(kThreadName))); + MockProcess::GlobalInit(); // Need a MODE_SERVER to make MODE_CLIENTs (like a RenderThread) happy. - channel_ = new IPC::Channel(kThreadName, IPC::Channel::MODE_SERVER, NULL); + channel_ = new IPC::Channel(ASCIIToWide(kThreadName), + IPC::Channel::MODE_SERVER, NULL); } virtual void TearDown() { message_loop_.RunAllPending(); delete channel_; - mock_process_.reset(); + MockProcess::GlobalCleanup(); } - protected: + private: MessageLoopForIO message_loop_; - scoped_ptr<MockProcess> mock_process_; IPC::Channel *channel_; }; TEST_F(RenderThreadTest, TestGlobal) { - ASSERT_TRUE(RenderThread::current()); + ASSERT_FALSE(g_render_thread); + { + RenderThread thread(ASCIIToWide(kThreadName)); + ASSERT_TRUE(g_render_thread); + } + ASSERT_FALSE(g_render_thread); } TEST_F(RenderThreadTest, TestVisitedMsg) { + RenderThread thread(ASCIIToWide(kThreadName)); #if defined(OS_WIN) IPC::Message* msg = new ViewMsg_VisitedLink_NewTable(NULL); #elif defined(OS_POSIX) @@ -47,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); + 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 d87b327..9528187 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -1461,8 +1461,8 @@ void RenderView::DidFinishDocumentLoadForFrame(WebView* webview, // Check whether we have new encoding name. UpdateEncoding(frame, webview->GetMainFrameEncodingName()); - if (RenderThread::current()) // Will be NULL during unit tests. - RenderThread::current()->user_script_slave()->InjectScripts( + if (g_render_thread) // Will be NULL during unit tests. + g_render_thread->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_END); } @@ -1532,8 +1532,8 @@ void RenderView::WindowObjectCleared(WebFrame* webframe) { } void RenderView::DocumentElementAvailable(WebFrame* frame) { - if (RenderThread::current()) // Will be NULL during unit tests. - RenderThread::current()->user_script_slave()->InjectScripts( + if (g_render_thread) // Will be NULL during unit tests. + g_render_thread->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_START); } @@ -1863,12 +1863,13 @@ WebWidget* RenderView::CreatePopupWidget(WebView* webview, static bool ShouldLoadPluginInProcess(const std::string& mime_type, bool* is_gears) { - if (RenderProcess::current()->in_process_plugins()) + if (RenderProcess::ShouldLoadPluginsInProcess()) return true; if (mime_type == "application/x-googlegears") { *is_gears = true; - return RenderProcess::current()->in_process_gears(); + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kGearsInRenderer); } return false; @@ -2865,8 +2866,8 @@ std::string RenderView::GetAltHTMLForTemplate( 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(); + if (g_render_thread) + return g_render_thread->owner_loop(); return NULL; } diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc index 5443c73..82aff43 100644 --- a/chrome/renderer/render_view_unittest.cc +++ b/chrome/renderer/render_view_unittest.cc @@ -60,7 +60,7 @@ class RenderViewTest : public testing::Test { // testing::Test virtual void SetUp() { - mock_process_.reset(new MockProcess()); + MockProcess::GlobalInit(); render_thread_.set_routing_id(kRouteId); @@ -77,12 +77,15 @@ class RenderViewTest : public testing::Test { view_ = NULL; - mock_process_.reset(); + // There is a delayed task that the child process posts to terminate the + // message loop so we need to spin the message loop to delete the task. + MockProcess::GlobalCleanup(); + msg_loop_.Run(); } MessageLoop msg_loop_; MockRenderThread render_thread_; - scoped_ptr<MockProcess> mock_process_; + scoped_refptr<RenderView> view_; }; diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 9d1d3a3..7782fd5 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -98,21 +98,21 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable) ime_control_updated_(false), ime_control_busy_(false), activatable_(activatable) { - RenderProcess::current()->AddRefProcess(); + RenderProcess::AddRefProcess(); DCHECK(render_thread_); } RenderWidget::~RenderWidget() { DCHECK(!webwidget_) << "Leaking our WebWidget!"; if (current_paint_buf_) { - RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_); + RenderProcess::ReleaseTransportDIB(current_paint_buf_); current_paint_buf_ = NULL; } if (current_scroll_buf_) { - RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_); + RenderProcess::ReleaseTransportDIB(current_scroll_buf_); current_scroll_buf_ = NULL; } - RenderProcess::current()->ReleaseProcess(); + RenderProcess::ReleaseProcess(); } /*static*/ @@ -298,7 +298,7 @@ void RenderWidget::OnPaintRectAck() { // If we sent a PaintRect message with a zero-sized bitmap, then // we should have no current paint buf. if (current_paint_buf_) { - RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_); + RenderProcess::ReleaseTransportDIB(current_paint_buf_); current_paint_buf_ = NULL; } @@ -310,7 +310,7 @@ void RenderWidget::OnScrollRectAck() { DCHECK(scroll_reply_pending()); if (current_scroll_buf_) { - RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_); + RenderProcess::ReleaseTransportDIB(current_scroll_buf_); current_scroll_buf_ = NULL; } @@ -403,7 +403,7 @@ void RenderWidget::DoDeferredPaint() { // Compute a buffer for painting and cache it. skia::PlatformCanvas* canvas = - RenderProcess::current()->GetDrawingCanvas(¤t_paint_buf_, damaged_rect); + RenderProcess::GetDrawingCanvas(¤t_paint_buf_, damaged_rect); if (!canvas) { NOTREACHED(); return; @@ -480,7 +480,7 @@ void RenderWidget::DoDeferredScroll() { damaged_rect = scroll_rect_.Intersect(damaged_rect); skia::PlatformCanvas* canvas = - RenderProcess::current()->GetDrawingCanvas(¤t_scroll_buf_, damaged_rect); + RenderProcess::GetDrawingCanvas(¤t_scroll_buf_, damaged_rect); if (!canvas) { NOTREACHED(); return; diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index edcc5af..b0c4b11 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -32,7 +32,7 @@ class RenderWidget : public IPC::Channel::Listener, public: // Creates a new RenderWidget. The opener_id is the routing ID of the // RenderView that this widget lives inside. The render_thread is any - // RenderThreadBase implementation, mostly commonly RenderThread::current(). + // RenderThreadBase implementation, mostly commonly g_render_thread. static RenderWidget* Create(int32 opener_id, RenderThreadBase* render_thread, bool activatable); diff --git a/chrome/renderer/render_widget_unittest.cc b/chrome/renderer/render_widget_unittest.cc index 6937a64..6c2b24f 100644 --- a/chrome/renderer/render_widget_unittest.cc +++ b/chrome/renderer/render_widget_unittest.cc @@ -28,17 +28,20 @@ class RenderWidgetTest : public testing::Test { private: // testing::Test virtual void SetUp() { - mock_process_.reset(new MockProcess()); + MockProcess::GlobalInit(); + render_thread_.set_routing_id(kRouteId); widget_ = RenderWidget::Create(kOpenerId, &render_thread_, true); ASSERT_TRUE(widget_); } virtual void TearDown() { widget_ = NULL; - mock_process_.reset(); - } - scoped_ptr<MockProcess> mock_process_; + // There is a delayed task that the child process posts to terminate the + // message loop so we need to spin the message loop to delete the task. + MockProcess::GlobalCleanup(); + msg_loop_.Run(); + } }; } // namespace diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc index 7ccf018..a65f326 100644 --- a/chrome/renderer/renderer_glue.cc +++ b/chrome/renderer/renderer_glue.cc @@ -134,14 +134,14 @@ ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() { #if defined(OS_WIN) if (shared_buf_) { - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_ClipboardWriteObjectsSync(objects_)); delete shared_buf_; return; } #endif - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_ClipboardWriteObjectsAsync(objects_)); } @@ -183,7 +183,7 @@ bool GetMimeTypeFromExtension(const FilePath::StringType &ext, // The sandbox restricts our access to the registry, so we need to proxy // these calls over to the browser process. DCHECK(mime_type->empty()); - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_GetMimeTypeFromExtension(ext, mime_type)); return !mime_type->empty(); } @@ -196,7 +196,7 @@ bool GetMimeTypeFromFile(const FilePath &file_path, // The sandbox restricts our access to the registry, so we need to proxy // these calls over to the browser process. DCHECK(mime_type->empty()); - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_GetMimeTypeFromFile(file_path, mime_type)); return !mime_type->empty(); } @@ -209,7 +209,7 @@ bool GetPreferredExtensionForMimeType(const std::string& mime_type, // The sandbox restricts our access to the registry, so we need to proxy // these calls over to the browser process. DCHECK(ext->empty()); - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_GetPreferredExtensionForMimeType(mime_type, ext)); return !ext->empty(); } @@ -246,21 +246,21 @@ bool ClipboardIsFormatAvailable(Clipboard::FormatType format) { bool ClipboardIsFormatAvailable(unsigned int format) { bool result; - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_ClipboardIsFormatAvailable(format, &result)); return result; } void ClipboardReadText(std::wstring* result) { - RenderThread::current()->Send(new ViewHostMsg_ClipboardReadText(result)); + g_render_thread->Send(new ViewHostMsg_ClipboardReadText(result)); } void ClipboardReadAsciiText(std::string* result) { - RenderThread::current()->Send(new ViewHostMsg_ClipboardReadAsciiText(result)); + g_render_thread->Send(new ViewHostMsg_ClipboardReadAsciiText(result)); } void ClipboardReadHTML(std::wstring* markup, GURL* url) { - RenderThread::current()->Send(new ViewHostMsg_ClipboardReadHTML(markup, url)); + g_render_thread->Send(new ViewHostMsg_ClipboardReadHTML(markup, url)); } GURL GetInspectorURL() { @@ -271,8 +271,9 @@ std::string GetUIResourceProtocol() { return "chrome"; } -bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { - return RenderThread::current()->Send( +bool GetPlugins(bool refresh, + std::vector<WebPluginInfo>* plugins) { + return g_render_thread->Send( new ViewHostMsg_GetPlugins(refresh, plugins)); } @@ -280,24 +281,33 @@ bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { bool EnsureFontLoaded(HFONT font) { LOGFONT logfont; GetObject(font, sizeof(LOGFONT), &logfont); - return RenderThread::current()->Send(new ViewHostMsg_LoadFont(logfont)); + return g_render_thread->Send(new ViewHostMsg_LoadFont(logfont)); } #endif webkit_glue::ScreenInfo GetScreenInfo(gfx::NativeViewId window) { webkit_glue::ScreenInfo results; - RenderThread::current()->Send( + g_render_thread->Send( new ViewHostMsg_GetScreenInfo(window, &results)); return results; } uint64 VisitedLinkHash(const char* canonical_url, size_t length) { - return RenderThread::current()->visited_link_slave()->ComputeURLFingerprint( + return g_render_thread->visited_link_slave()->ComputeURLFingerprint( canonical_url, length); } bool IsLinkVisited(uint64 link_hash) { - return RenderThread::current()->visited_link_slave()->IsVisited(link_hash); + return g_render_thread->visited_link_slave()->IsVisited(link_hash); +} + +int ResolveProxyFromRenderThread(const GURL& url, std::string* proxy_result) { + // Send a synchronous IPC from renderer process to the browser process to + // resolve the proxy. (includes --single-process case). + int net_error; + bool ipc_ok = g_render_thread->Send( + new ViewHostMsg_ResolveProxy(url, &net_error, proxy_result)); + return ipc_ok ? net_error : net::ERR_UNEXPECTED; } #ifndef USING_SIMPLE_RESOURCE_LOADER_BRIDGE @@ -344,12 +354,12 @@ ResourceLoaderBridge* ResourceLoaderBridge::Create( void SetCookie(const GURL& url, const GURL& policy_url, const std::string& cookie) { - RenderThread::current()->Send(new ViewHostMsg_SetCookie(url, policy_url, cookie)); + g_render_thread->Send(new ViewHostMsg_SetCookie(url, policy_url, cookie)); } std::string GetCookies(const GURL& url, const GURL& policy_url) { std::string cookies; - RenderThread::current()->Send(new ViewHostMsg_GetCookies(url, policy_url, &cookies)); + g_render_thread->Send(new ViewHostMsg_GetCookies(url, policy_url, &cookies)); return cookies; } @@ -357,8 +367,8 @@ void NotifyCacheStats() { // Update the browser about our cache // NOTE: Since this can be called from the plugin process, we might not have // a RenderThread. Do nothing in that case. - if (!IsPluginProcess()) - RenderThread::current()->InformHostOfCacheStatsLater(); + if (g_render_thread) + g_render_thread->InformHostOfCacheStatsLater(); } #endif // !USING_SIMPLE_RESOURCE_LOADER_BRIDGE diff --git a/chrome/renderer/renderer_main.cc b/chrome/renderer/renderer_main.cc index 8ca5346..c376486 100644 --- a/chrome/renderer/renderer_main.cc +++ b/chrome/renderer/renderer_main.cc @@ -90,8 +90,9 @@ int RendererMain(const MainFunctionParams& parameters) { HandleRendererErrorTestParameters(parsed_command_line); - { - RenderProcess render_process; + std::wstring channel_name = + parsed_command_line.GetSwitchValue(switches::kProcessChannelID); + if (RenderProcess::GlobalInit(channel_name)) { bool run_loop = true; if (!no_sandbox) { run_loop = platform.EnableSandbox(); @@ -107,6 +108,8 @@ int RendererMain(const MainFunctionParams& parameters) { if (pool) pool->Recycle(); MessageLoop::current()->Run(); } + + RenderProcess::GlobalCleanup(); } platform.PlatformUninitialize(); return 0; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index bc0754e..155c19a 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -209,12 +209,12 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn, bool load_manually) { std::wstring channel_name; FilePath plugin_path; - if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( + if (!g_render_thread->Send(new ViewHostMsg_OpenChannelToPlugin( url, mime_type_, clsid_, webkit_glue::GetWebKitLocale(), &channel_name, &plugin_path))) return false; - MessageLoop* ipc_message_loop = RenderThread::current()->owner_loop(); + MessageLoop* ipc_message_loop = g_render_thread->owner_loop(); scoped_refptr<PluginChannelHost> channel_host = PluginChannelHost::GetPluginChannelHost(channel_name, ipc_message_loop); if (!channel_host.get()) |