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 |