| 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/logging.h" |
| 12 #include "base/shared_memory.h" | 13 #include "base/shared_memory.h" |
| 13 #include "base/stats_table.h" | 14 #include "base/stats_table.h" |
| 14 #include "base/thread_local.h" | 15 #include "base/thread_local.h" |
| 15 #include "chrome/common/appcache/appcache_dispatcher.h" | 16 #include "chrome/common/appcache/appcache_dispatcher.h" |
| 16 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
| 17 #include "chrome/common/db_message_filter.h" | 18 #include "chrome/common/db_message_filter.h" |
| 18 #include "chrome/common/render_messages.h" | 19 #include "chrome/common/render_messages.h" |
| 19 #include "chrome/common/renderer_preferences.h" | 20 #include "chrome/common/renderer_preferences.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" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 51 #if defined(OS_WIN) | 52 #if defined(OS_WIN) |
| 52 #include <windows.h> | 53 #include <windows.h> |
| 53 #include <objbase.h> | 54 #include <objbase.h> |
| 54 #endif | 55 #endif |
| 55 | 56 |
| 56 using WebKit::WebCache; | 57 using WebKit::WebCache; |
| 57 using WebKit::WebString; | 58 using WebKit::WebString; |
| 58 | 59 |
| 59 namespace { | 60 namespace { |
| 60 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; | 61 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; |
| 62 static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; |
| 63 |
| 61 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( | 64 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( |
| 62 base::LINKER_INITIALIZED); | 65 base::LINKER_INITIALIZED); |
| 63 | 66 |
| 64 #if defined(OS_POSIX) | 67 #if defined(OS_POSIX) |
| 65 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 68 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
| 66 void OnChannelError() { | 69 void OnChannelError() { |
| 67 // On POSIX, at least, one can install an unload handler which loops | 70 // On POSIX, at least, one can install an unload handler which loops |
| 68 // forever and leave behind a renderer process which eats 100% CPU forever. | 71 // forever and leave behind a renderer process which eats 100% CPU forever. |
| 69 // | 72 // |
| 70 // This is because the terminate signals (ViewMsg_ShouldClose and the error | 73 // This is because the terminate signals (ViewMsg_ShouldClose and the error |
| (...skipping 27 matching lines...) Expand all Loading... |
| 98 void RenderThread::Init() { | 101 void RenderThread::Init() { |
| 99 lazy_tls.Pointer()->Set(this); | 102 lazy_tls.Pointer()->Set(this); |
| 100 #if defined(OS_WIN) | 103 #if defined(OS_WIN) |
| 101 // If you are running plugins in this thread you need COM active but in | 104 // If you are running plugins in this thread you need COM active but in |
| 102 // the normal case you don't. | 105 // the normal case you don't. |
| 103 if (RenderProcess::InProcessPlugins()) | 106 if (RenderProcess::InProcessPlugins()) |
| 104 CoInitialize(0); | 107 CoInitialize(0); |
| 105 #endif | 108 #endif |
| 106 | 109 |
| 107 plugin_refresh_allowed_ = true; | 110 plugin_refresh_allowed_ = true; |
| 108 cache_stats_factory_.reset( | 111 cache_stats_task_pending_ = false; |
| 109 new ScopedRunnableMethodFactory<RenderThread>(this)); | 112 widget_count_ = 0; |
| 113 hidden_widget_count_ = 0; |
| 114 idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; |
| 115 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); |
| 110 | 116 |
| 111 visited_link_slave_.reset(new VisitedLinkSlave()); | 117 visited_link_slave_.reset(new VisitedLinkSlave()); |
| 112 user_script_slave_.reset(new UserScriptSlave()); | 118 user_script_slave_.reset(new UserScriptSlave()); |
| 113 dns_master_.reset(new RenderDnsMaster()); | 119 dns_master_.reset(new RenderDnsMaster()); |
| 114 histogram_snapshots_.reset(new RendererHistogramSnapshots()); | 120 histogram_snapshots_.reset(new RendererHistogramSnapshots()); |
| 115 appcache_dispatcher_.reset(new AppCacheDispatcher(this)); | 121 appcache_dispatcher_.reset(new AppCacheDispatcher(this)); |
| 116 devtools_agent_filter_ = new DevToolsAgentFilter(); | 122 devtools_agent_filter_ = new DevToolsAgentFilter(); |
| 117 AddFilter(devtools_agent_filter_.get()); | 123 AddFilter(devtools_agent_filter_.get()); |
| 118 db_message_filter_ = new DBMessageFilter(); | 124 db_message_filter_ = new DBMessageFilter(); |
| 119 AddFilter(db_message_filter_.get()); | 125 AddFilter(db_message_filter_.get()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 149 } | 155 } |
| 150 | 156 |
| 151 void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { | 157 void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 152 channel()->AddFilter(filter); | 158 channel()->AddFilter(filter); |
| 153 } | 159 } |
| 154 | 160 |
| 155 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { | 161 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 156 channel()->RemoveFilter(filter); | 162 channel()->RemoveFilter(filter); |
| 157 } | 163 } |
| 158 | 164 |
| 165 void RenderThread::WidgetHidden() { |
| 166 DCHECK(hidden_widget_count_ < widget_count_); |
| 167 hidden_widget_count_++ ; |
| 168 if (widget_count_ && hidden_widget_count_ == widget_count_) { |
| 169 // Reset the delay. |
| 170 idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; |
| 171 |
| 172 // Schedule the IdleHandler to wakeup in a bit. |
| 173 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 174 task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), |
| 175 static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); |
| 176 } |
| 177 } |
| 178 |
| 179 void RenderThread::WidgetRestored() { |
| 180 DCHECK(hidden_widget_count_ > 0); |
| 181 hidden_widget_count_--; |
| 182 |
| 183 // Note: we may have a timer pending to call the IdleHandler (see the |
| 184 // WidgetHidden() code). But we don't bother to cancel it as it is |
| 185 // benign and won't do anything if the tab is un-hidden when it is |
| 186 // called. |
| 187 } |
| 188 |
| 159 void RenderThread::Resolve(const char* name, size_t length) { | 189 void RenderThread::Resolve(const char* name, size_t length) { |
| 160 return dns_master_->Resolve(name, length); | 190 return dns_master_->Resolve(name, length); |
| 161 } | 191 } |
| 162 | 192 |
| 163 void RenderThread::SendHistograms(int sequence_number) { | 193 void RenderThread::SendHistograms(int sequence_number) { |
| 164 return histogram_snapshots_->SendHistograms(sequence_number); | 194 return histogram_snapshots_->SendHistograms(sequence_number); |
| 165 } | 195 } |
| 166 | 196 |
| 167 void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) { | 197 void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) { |
| 168 DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle"; | 198 DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle"; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 | 339 |
| 310 void RenderThread::OnGetRendererHistograms(int sequence_number) { | 340 void RenderThread::OnGetRendererHistograms(int sequence_number) { |
| 311 SendHistograms(sequence_number); | 341 SendHistograms(sequence_number); |
| 312 } | 342 } |
| 313 | 343 |
| 314 void RenderThread::InformHostOfCacheStats() { | 344 void RenderThread::InformHostOfCacheStats() { |
| 315 EnsureWebKitInitialized(); | 345 EnsureWebKitInitialized(); |
| 316 WebCache::UsageStats stats; | 346 WebCache::UsageStats stats; |
| 317 WebCache::getUsageStats(&stats); | 347 WebCache::getUsageStats(&stats); |
| 318 Send(new ViewHostMsg_UpdatedCacheStats(stats)); | 348 Send(new ViewHostMsg_UpdatedCacheStats(stats)); |
| 349 cache_stats_task_pending_ = false; |
| 319 } | 350 } |
| 320 | 351 |
| 321 void RenderThread::InformHostOfCacheStatsLater() { | 352 void RenderThread::InformHostOfCacheStatsLater() { |
| 322 // Rate limit informing the host of our cache stats. | 353 // Rate limit informing the host of our cache stats. |
| 323 if (!cache_stats_factory_->empty()) | 354 if (cache_stats_task_pending_) |
| 324 return; | 355 return; |
| 325 | 356 |
| 357 cache_stats_task_pending_ = true; |
| 326 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 358 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 327 cache_stats_factory_->NewRunnableMethod( | 359 task_factory_->NewRunnableMethod( |
| 328 &RenderThread::InformHostOfCacheStats), | 360 &RenderThread::InformHostOfCacheStats), |
| 329 kCacheStatsDelayMS); | 361 kCacheStatsDelayMS); |
| 330 } | 362 } |
| 331 | 363 |
| 332 void RenderThread::CloseIdleConnections() { | 364 void RenderThread::CloseIdleConnections() { |
| 333 Send(new ViewHostMsg_CloseIdleConnections()); | 365 Send(new ViewHostMsg_CloseIdleConnections()); |
| 334 } | 366 } |
| 335 | 367 |
| 336 void RenderThread::SetCacheMode(bool enabled) { | 368 void RenderThread::SetCacheMode(bool enabled) { |
| 337 Send(new ViewHostMsg_SetCacheMode(enabled)); | 369 Send(new ViewHostMsg_SetCacheMode(enabled)); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 WebKit::enableMediaPlayer(); | 449 WebKit::enableMediaPlayer(); |
| 418 | 450 |
| 419 // Note: We are forcing --enable-databases to on with --enable-extensions so | 451 // Note: We are forcing --enable-databases to on with --enable-extensions so |
| 420 // that extension developers can test databases. | 452 // that extension developers can test databases. |
| 421 if (command_line.HasSwitch(switches::kEnableDatabases) || | 453 if (command_line.HasSwitch(switches::kEnableDatabases) || |
| 422 command_line.HasSwitch(switches::kEnableExtensions)) { | 454 command_line.HasSwitch(switches::kEnableExtensions)) { |
| 423 WebKit::enableDatabases(); | 455 WebKit::enableDatabases(); |
| 424 } | 456 } |
| 425 } | 457 } |
| 426 | 458 |
| 459 void RenderThread::IdleHandler() { |
| 460 // It is possible that the timer was set while the widgets were idle, |
| 461 // but that they are no longer idle. If so, just return. |
| 462 if (!widget_count_ || hidden_widget_count_ < widget_count_) |
| 463 return; |
| 464 |
| 465 if (v8::V8::IsDead()) |
| 466 return; |
| 467 |
| 468 LOG(INFO) << "RenderThread calling v8 IdleNotification for " << this; |
| 469 |
| 470 // When V8::IdleNotification returns true, it means that it has cleaned up |
| 471 // as much as it can. There is no point in continuing to call it. |
| 472 if (!v8::V8::IdleNotification(false)) { |
| 473 // Dampen the delay using the algorithm: |
| 474 // delay = delay + 1 / (delay + 2) |
| 475 // Using floor(delay) has a dampening effect such as: |
| 476 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... |
| 477 idle_notification_delay_in_s_ += |
| 478 1.0 / (idle_notification_delay_in_s_ + 2.0); |
| 479 |
| 480 // Schedule the next timer. |
| 481 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 482 task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), |
| 483 static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); |
| 484 } |
| 485 } |
| 486 |
| 427 void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, | 487 void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, |
| 428 const ListValue& args) { | 488 const ListValue& args) { |
| 429 RendererExtensionBindings::Invoke(function_name, args, NULL); | 489 RendererExtensionBindings::Invoke(function_name, args, NULL); |
| 430 } | 490 } |
| 431 | 491 |
| 432 void RenderThread::OnPurgePluginListCache() { | 492 void RenderThread::OnPurgePluginListCache() { |
| 433 // The call below will cause a GetPlugins call with refresh=true, but at this | 493 // The call below will cause a GetPlugins call with refresh=true, but at this |
| 434 // point we already know that the browser has refreshed its list, so disable | 494 // point we already know that the browser has refreshed its list, so disable |
| 435 // refresh temporarily to prevent each renderer process causing the list to be | 495 // refresh temporarily to prevent each renderer process causing the list to be |
| 436 // regenerated. | 496 // regenerated. |
| 437 plugin_refresh_allowed_ = false; | 497 plugin_refresh_allowed_ = false; |
| 438 WebKit::resetPluginCache(); | 498 WebKit::resetPluginCache(); |
| 439 plugin_refresh_allowed_ = true; | 499 plugin_refresh_allowed_ = true; |
| 440 } | 500 } |
| OLD | NEW |