| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/render_thread.h" | 5 #include "chrome/renderer/render_thread.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/shared_memory.h" | 12 #include "base/shared_memory.h" |
| 13 #include "base/stats_table.h" | 13 #include "base/stats_table.h" |
| 14 #include "base/thread_local.h" | 14 #include "base/thread_local.h" |
| 15 #include "chrome/common/app_cache/app_cache_context_impl.h" | 15 #include "chrome/common/app_cache/app_cache_context_impl.h" |
| 16 #include "chrome/common/app_cache/app_cache_dispatcher.h" | 16 #include "chrome/common/app_cache/app_cache_dispatcher.h" |
| 17 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
| 18 #include "chrome/common/render_messages.h" | 18 #include "chrome/common/render_messages.h" |
| 19 #include "chrome/common/renderer_preferences.h" | 19 #include "chrome/common/renderer_preferences.h" |
| 20 #include "chrome/common/notification_service.h" |
| 20 #include "chrome/common/url_constants.h" | 21 #include "chrome/common/url_constants.h" |
| 21 #include "chrome/plugin/npobject_util.h" | 22 #include "chrome/plugin/npobject_util.h" |
| 22 // TODO(port) | 23 // TODO(port) |
| 23 #if defined(OS_WIN) | 24 #if defined(OS_WIN) |
| 24 #include "chrome/plugin/plugin_channel.h" | 25 #include "chrome/plugin/plugin_channel.h" |
| 25 #else | 26 #else |
| 26 #include "base/scoped_handle.h" | 27 #include "base/scoped_handle.h" |
| 27 #include "chrome/plugin/plugin_channel_base.h" | 28 #include "chrome/plugin/plugin_channel_base.h" |
| 28 #endif | 29 #endif |
| 29 #include "chrome/renderer/devtools_agent_filter.h" | 30 #include "chrome/renderer/devtools_agent_filter.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 47 #include "webkit/extensions/v8/playback_extension.h" | 48 #include "webkit/extensions/v8/playback_extension.h" |
| 48 | 49 |
| 49 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
| 50 #include <windows.h> | 51 #include <windows.h> |
| 51 #include <objbase.h> | 52 #include <objbase.h> |
| 52 #endif | 53 #endif |
| 53 | 54 |
| 54 using WebKit::WebCache; | 55 using WebKit::WebCache; |
| 55 using WebKit::WebString; | 56 using WebKit::WebString; |
| 56 | 57 |
| 57 namespace { | |
| 58 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; | 58 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; |
| 59 |
| 59 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( | 60 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( |
| 60 base::LINKER_INITIALIZED); | 61 base::LINKER_INITIALIZED); |
| 62 |
| 63 //----------------------------------------------------------------------------- |
| 64 // Methods below are only called on the owner's thread: |
| 65 |
| 66 // When we run plugins in process, we actually run them on the render thread, |
| 67 // which means that we need to make the render thread pump UI events. |
| 68 RenderThread::RenderThread() |
| 69 : ChildThread( |
| 70 base::Thread::Options(RenderProcess::InProcessPlugins() ? |
| 71 MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)), |
| 72 plugin_refresh_allowed_(true) { |
| 73 } |
| 74 |
| 75 RenderThread::RenderThread(const std::string& channel_name) |
| 76 : ChildThread( |
| 77 base::Thread::Options(RenderProcess::InProcessPlugins() ? |
| 78 MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)), |
| 79 plugin_refresh_allowed_(true) { |
| 80 SetChannelName(channel_name); |
| 81 } |
| 82 |
| 83 RenderThread::~RenderThread() { |
| 84 } |
| 85 |
| 86 RenderThread* RenderThread::current() { |
| 87 return lazy_tls.Pointer()->Get(); |
| 88 } |
| 89 |
| 90 void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 91 channel()->AddFilter(filter); |
| 92 } |
| 93 |
| 94 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 95 channel()->RemoveFilter(filter); |
| 96 } |
| 97 |
| 98 void RenderThread::Resolve(const char* name, size_t length) { |
| 99 return dns_master_->Resolve(name, length); |
| 100 } |
| 101 |
| 102 void RenderThread::SendHistograms(int sequence_number) { |
| 103 return histogram_snapshots_->SendHistograms(sequence_number); |
| 104 } |
| 105 |
| 61 static WebAppCacheContext* CreateAppCacheContextForRenderer() { | 106 static WebAppCacheContext* CreateAppCacheContextForRenderer() { |
| 62 return new AppCacheContextImpl(RenderThread::current()); | 107 return new AppCacheContextImpl(RenderThread::current()); |
| 63 } | 108 } |
| 64 | 109 |
| 65 #if defined(OS_POSIX) | 110 #if defined(OS_POSIX) |
| 66 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 111 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
| 67 void OnChannelError() { | 112 void OnChannelError() { |
| 68 // On POSIX, at least, one can install an unload handler which loops | 113 // On POSIX, at least, one can install an unload handler which loops |
| 69 // forever and leave behind a renderer process which eats 100% CPU forever. | 114 // forever and leave behind a renderer process which eats 100% CPU forever. |
| 70 // | 115 // |
| 71 // This is because the terminate signals (ViewMsg_ShouldClose and the error | 116 // This is because the terminate signals (ViewMsg_ShouldClose and the error |
| 72 // from the IPC channel) are routed to the main message loop but never | 117 // from the IPC channel) are routed to the main message loop but never |
| 73 // processed (because that message loop is stuck in V8). | 118 // processed (because that message loop is stuck in V8). |
| 74 // | 119 // |
| 75 // One could make the browser SIGKILL the renderers, but that leaves open a | 120 // One could make the browser SIGKILL the renderers, but that leaves open a |
| 76 // large window where a browser failure (or a user, manually terminating | 121 // large window where a browser failure (or a user, manually terminating |
| 77 // the browser because "it's stuck") will leave behind a process eating all | 122 // the browser because "it's stuck") will leave behind a process eating all |
| 78 // the CPU. | 123 // the CPU. |
| 79 // | 124 // |
| 80 // So, we install a filter on the channel so that we can process this event | 125 // So, we install a filter on the channel so that we can process this event |
| 81 // here and kill the process. | 126 // here and kill the process. |
| 82 _exit(0); | 127 _exit(0); |
| 83 } | 128 } |
| 84 }; | 129 }; |
| 85 #endif | 130 #endif |
| 86 } // namespace | |
| 87 | |
| 88 // When we run plugins in process, we actually run them on the render thread, | |
| 89 // which means that we need to make the render thread pump UI events. | |
| 90 RenderThread::RenderThread() { | |
| 91 Init(); | |
| 92 } | |
| 93 | |
| 94 RenderThread::RenderThread(const std::string& channel_name) | |
| 95 : ChildThread(channel_name) { | |
| 96 Init(); | |
| 97 } | |
| 98 | 131 |
| 99 void RenderThread::Init() { | 132 void RenderThread::Init() { |
| 100 lazy_tls.Pointer()->Set(this); | 133 lazy_tls.Pointer()->Set(this); |
| 101 #if defined(OS_WIN) | 134 #if defined(OS_WIN) |
| 102 // If you are running plugins in this thread you need COM active but in | 135 // If you are running plugins in this thread you need COM active but in |
| 103 // the normal case you don't. | 136 // the normal case you don't. |
| 104 if (RenderProcess::InProcessPlugins()) | 137 if (RenderProcess::InProcessPlugins()) |
| 105 CoInitialize(0); | 138 CoInitialize(0); |
| 106 #endif | 139 #endif |
| 107 | 140 |
| 108 plugin_refresh_allowed_ = true; | 141 ChildThread::Init(); |
| 142 notification_service_.reset(new NotificationService); |
| 109 cache_stats_factory_.reset( | 143 cache_stats_factory_.reset( |
| 110 new ScopedRunnableMethodFactory<RenderThread>(this)); | 144 new ScopedRunnableMethodFactory<RenderThread>(this)); |
| 111 | 145 |
| 112 visited_link_slave_.reset(new VisitedLinkSlave()); | 146 visited_link_slave_.reset(new VisitedLinkSlave()); |
| 113 user_script_slave_.reset(new UserScriptSlave()); | 147 user_script_slave_.reset(new UserScriptSlave()); |
| 114 dns_master_.reset(new RenderDnsMaster()); | 148 dns_master_.reset(new RenderDnsMaster()); |
| 115 histogram_snapshots_.reset(new RendererHistogramSnapshots()); | 149 histogram_snapshots_.reset(new RendererHistogramSnapshots()); |
| 116 app_cache_dispatcher_.reset(new AppCacheDispatcher()); | 150 app_cache_dispatcher_.reset(new AppCacheDispatcher()); |
| 117 WebAppCacheContext::SetFactory(CreateAppCacheContextForRenderer); | 151 WebAppCacheContext::SetFactory(CreateAppCacheContextForRenderer); |
| 118 devtools_agent_filter_ = new DevToolsAgentFilter(); | 152 devtools_agent_filter_ = new DevToolsAgentFilter(); |
| 119 AddFilter(devtools_agent_filter_.get()); | 153 AddFilter(devtools_agent_filter_.get()); |
| 120 | 154 |
| 121 #if defined(OS_POSIX) | 155 #if defined(OS_POSIX) |
| 122 suicide_on_channel_error_filter_ = new SuicideOnChannelErrorFilter; | 156 suicide_on_channel_error_filter_ = new SuicideOnChannelErrorFilter; |
| 123 AddFilter(suicide_on_channel_error_filter_.get()); | 157 AddFilter(suicide_on_channel_error_filter_.get()); |
| 124 #endif | 158 #endif |
| 125 } | 159 } |
| 126 | 160 |
| 127 RenderThread::~RenderThread() { | 161 void RenderThread::CleanUp() { |
| 128 // Shutdown in reverse of the initialization order. | 162 // Shutdown in reverse of the initialization order. |
| 129 RemoveFilter(devtools_agent_filter_.get()); | 163 RemoveFilter(devtools_agent_filter_.get()); |
| 164 devtools_agent_filter_ = NULL; |
| 130 WebAppCacheContext::SetFactory(NULL); | 165 WebAppCacheContext::SetFactory(NULL); |
| 131 if (webkit_client_.get()) | 166 app_cache_dispatcher_.reset(); |
| 167 histogram_snapshots_.reset(); |
| 168 dns_master_.reset(); |
| 169 user_script_slave_.reset(); |
| 170 visited_link_slave_.reset(); |
| 171 |
| 172 if (webkit_client_.get()) { |
| 132 WebKit::shutdown(); | 173 WebKit::shutdown(); |
| 174 webkit_client_.reset(); |
| 175 } |
| 133 | 176 |
| 177 notification_service_.reset(); |
| 178 ChildThread::CleanUp(); |
| 134 lazy_tls.Pointer()->Set(NULL); | 179 lazy_tls.Pointer()->Set(NULL); |
| 135 | 180 |
| 136 // TODO(port) | 181 // TODO(port) |
| 137 #if defined(OS_WIN) | 182 #if defined(OS_WIN) |
| 138 // Clean up plugin channels before this thread goes away. | 183 // Clean up plugin channels before this thread goes away. |
| 139 PluginChannelBase::CleanupChannels(); | 184 PluginChannelBase::CleanupChannels(); |
| 140 // Don't call COM if the renderer is in the sandbox. | 185 // Don't call COM if the renderer is in the sandbox. |
| 141 if (RenderProcess::InProcessPlugins()) | 186 if (RenderProcess::InProcessPlugins()) |
| 142 CoUninitialize(); | 187 CoUninitialize(); |
| 143 #endif | 188 #endif |
| 144 } | 189 } |
| 145 | 190 |
| 146 RenderThread* RenderThread::current() { | |
| 147 return lazy_tls.Pointer()->Get(); | |
| 148 } | |
| 149 | |
| 150 void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { | |
| 151 channel()->AddFilter(filter); | |
| 152 } | |
| 153 | |
| 154 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { | |
| 155 channel()->RemoveFilter(filter); | |
| 156 } | |
| 157 | |
| 158 void RenderThread::Resolve(const char* name, size_t length) { | |
| 159 return dns_master_->Resolve(name, length); | |
| 160 } | |
| 161 | |
| 162 void RenderThread::SendHistograms(int sequence_number) { | |
| 163 return histogram_snapshots_->SendHistograms(sequence_number); | |
| 164 } | |
| 165 | |
| 166 void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) { | 191 void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) { |
| 167 DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle"; | 192 DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle"; |
| 168 visited_link_slave_->Init(table); | 193 visited_link_slave_->Init(table); |
| 169 } | 194 } |
| 170 | 195 |
| 171 void RenderThread::OnAddVisitedLinks( | 196 void RenderThread::OnAddVisitedLinks( |
| 172 const VisitedLinkSlave::Fingerprints& fingerprints) { | 197 const VisitedLinkSlave::Fingerprints& fingerprints) { |
| 173 for (size_t i = 0; i < fingerprints.size(); ++i) | 198 for (size_t i = 0; i < fingerprints.size(); ++i) |
| 174 WebView::UpdateVisitedLinkState(fingerprints[i]); | 199 WebView::UpdateVisitedLinkState(fingerprints[i]); |
| 175 } | 200 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 EnsureWebKitInitialized(); | 267 EnsureWebKitInitialized(); |
| 243 | 268 |
| 244 // When bringing in render_view, also bring in webkit's glue and jsbindings. | 269 // When bringing in render_view, also bring in webkit's glue and jsbindings. |
| 245 base::WaitableEvent* waitable_event = new base::WaitableEvent( | 270 base::WaitableEvent* waitable_event = new base::WaitableEvent( |
| 246 #if defined(OS_WIN) | 271 #if defined(OS_WIN) |
| 247 modal_dialog_event.event); | 272 modal_dialog_event.event); |
| 248 #else | 273 #else |
| 249 true, false); | 274 true, false); |
| 250 #endif | 275 #endif |
| 251 | 276 |
| 277 // TODO(darin): once we have a RenderThread per RenderView, this will need to |
| 278 // change to assert that we are not creating more than one view. |
| 252 RenderView::Create( | 279 RenderView::Create( |
| 253 this, parent_hwnd, waitable_event, MSG_ROUTING_NONE, renderer_prefs, | 280 this, parent_hwnd, waitable_event, MSG_ROUTING_NONE, renderer_prefs, |
| 254 webkit_prefs, new SharedRenderViewCounter(0), view_id); | 281 webkit_prefs, new SharedRenderViewCounter(0), view_id); |
| 255 } | 282 } |
| 256 | 283 |
| 257 void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity, | 284 void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity, |
| 258 size_t max_dead_capacity, | 285 size_t max_dead_capacity, |
| 259 size_t capacity) { | 286 size_t capacity) { |
| 260 EnsureWebKitInitialized(); | 287 EnsureWebKitInitialized(); |
| 261 WebCache::setCapacities( | 288 WebCache::setCapacities( |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 | 405 |
| 379 void RenderThread::OnPurgePluginListCache() { | 406 void RenderThread::OnPurgePluginListCache() { |
| 380 // The call below will cause a GetPlugins call with refresh=true, but at this | 407 // The call below will cause a GetPlugins call with refresh=true, but at this |
| 381 // point we already know that the browser has refreshed its list, so disable | 408 // point we already know that the browser has refreshed its list, so disable |
| 382 // refresh temporarily to prevent each renderer process causing the list to be | 409 // refresh temporarily to prevent each renderer process causing the list to be |
| 383 // regenerated. | 410 // regenerated. |
| 384 plugin_refresh_allowed_ = false; | 411 plugin_refresh_allowed_ = false; |
| 385 WebKit::resetPluginCache(); | 412 WebKit::resetPluginCache(); |
| 386 plugin_refresh_allowed_ = true; | 413 plugin_refresh_allowed_ = true; |
| 387 } | 414 } |
| OLD | NEW |