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