| 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 <v8.h> | 7 #include <v8.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 using WebKit::WebRuntimeFeatures; | 86 using WebKit::WebRuntimeFeatures; |
| 87 using WebKit::WebSecurityPolicy; | 87 using WebKit::WebSecurityPolicy; |
| 88 using WebKit::WebScriptController; | 88 using WebKit::WebScriptController; |
| 89 using WebKit::WebString; | 89 using WebKit::WebString; |
| 90 using WebKit::WebStorageEventDispatcher; | 90 using WebKit::WebStorageEventDispatcher; |
| 91 using WebKit::WebView; | 91 using WebKit::WebView; |
| 92 | 92 |
| 93 namespace { | 93 namespace { |
| 94 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; | 94 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; |
| 95 static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; | 95 static const double kInitialIdleHandlerDelayS = 1.0 /* seconds */; |
| 96 static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; |
| 97 static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; |
| 96 | 98 |
| 97 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( | 99 static base::LazyInstance<base::ThreadLocalPointer<RenderThread> > lazy_tls( |
| 98 base::LINKER_INITIALIZED); | 100 base::LINKER_INITIALIZED); |
| 99 | 101 |
| 100 #if defined(OS_POSIX) | 102 #if defined(OS_POSIX) |
| 101 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 103 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
| 102 void OnChannelError() { | 104 void OnChannelError() { |
| 103 // On POSIX, at least, one can install an unload handler which loops | 105 // On POSIX, at least, one can install an unload handler which loops |
| 104 // forever and leave behind a renderer process which eats 100% CPU forever. | 106 // forever and leave behind a renderer process which eats 100% CPU forever. |
| 105 // | 107 // |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 | 156 |
| 155 void RenderThread::Init() { | 157 void RenderThread::Init() { |
| 156 lazy_tls.Pointer()->Set(this); | 158 lazy_tls.Pointer()->Set(this); |
| 157 #if defined(OS_WIN) | 159 #if defined(OS_WIN) |
| 158 // If you are running plugins in this thread you need COM active but in | 160 // If you are running plugins in this thread you need COM active but in |
| 159 // the normal case you don't. | 161 // the normal case you don't. |
| 160 if (RenderProcess::InProcessPlugins()) | 162 if (RenderProcess::InProcessPlugins()) |
| 161 CoInitialize(0); | 163 CoInitialize(0); |
| 162 #endif | 164 #endif |
| 163 | 165 |
| 166 std::string type_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 167 switches::kProcessType); |
| 168 is_extension_process_ = type_str == switches::kExtensionProcess; |
| 164 plugin_refresh_allowed_ = true; | 169 plugin_refresh_allowed_ = true; |
| 165 cache_stats_task_pending_ = false; | 170 cache_stats_task_pending_ = false; |
| 166 widget_count_ = 0; | 171 widget_count_ = 0; |
| 167 hidden_widget_count_ = 0; | 172 hidden_widget_count_ = 0; |
| 168 idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; | 173 idle_notification_delay_in_s_ = is_extension_process_ ? |
| 174 kInitialExtensionIdleHandlerDelayS : kInitialIdleHandlerDelayS; |
| 169 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); | 175 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThread>(this)); |
| 170 | 176 |
| 171 visited_link_slave_.reset(new VisitedLinkSlave()); | 177 visited_link_slave_.reset(new VisitedLinkSlave()); |
| 172 user_script_slave_.reset(new UserScriptSlave()); | 178 user_script_slave_.reset(new UserScriptSlave()); |
| 173 dns_master_.reset(new RenderDnsMaster()); | 179 dns_master_.reset(new RenderDnsMaster()); |
| 174 histogram_snapshots_.reset(new RendererHistogramSnapshots()); | 180 histogram_snapshots_.reset(new RendererHistogramSnapshots()); |
| 175 appcache_dispatcher_.reset(new AppCacheDispatcher(this)); | 181 appcache_dispatcher_.reset(new AppCacheDispatcher(this)); |
| 176 devtools_agent_filter_ = new DevToolsAgentFilter(); | 182 devtools_agent_filter_ = new DevToolsAgentFilter(); |
| 177 AddFilter(devtools_agent_filter_.get()); | 183 AddFilter(devtools_agent_filter_.get()); |
| 178 db_message_filter_ = new DBMessageFilter(); | 184 db_message_filter_ = new DBMessageFilter(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 channel()->AddFilter(filter); | 219 channel()->AddFilter(filter); |
| 214 } | 220 } |
| 215 | 221 |
| 216 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { | 222 void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 217 channel()->RemoveFilter(filter); | 223 channel()->RemoveFilter(filter); |
| 218 } | 224 } |
| 219 | 225 |
| 220 void RenderThread::WidgetHidden() { | 226 void RenderThread::WidgetHidden() { |
| 221 DCHECK(hidden_widget_count_ < widget_count_); | 227 DCHECK(hidden_widget_count_ < widget_count_); |
| 222 hidden_widget_count_++; | 228 hidden_widget_count_++; |
| 223 if (widget_count_ && hidden_widget_count_ == widget_count_) { | 229 if (!is_extension_process() && |
| 224 // Reset the delay. | 230 widget_count_ && hidden_widget_count_ == widget_count_) |
| 225 idle_notification_delay_in_s_ = kInitialIdleHandlerDelayS; | 231 ScheduleIdleHandler(kInitialIdleHandlerDelayS); |
| 226 | |
| 227 // Schedule the IdleHandler to wakeup in a bit. | |
| 228 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 229 task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), | |
| 230 static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); | |
| 231 } | |
| 232 } | 232 } |
| 233 | 233 |
| 234 void RenderThread::WidgetRestored() { | 234 void RenderThread::WidgetRestored() { |
| 235 DCHECK(hidden_widget_count_ > 0); | 235 DCHECK(hidden_widget_count_ > 0); |
| 236 hidden_widget_count_--; | 236 hidden_widget_count_--; |
| 237 | 237 if (!is_extension_process()) |
| 238 // Note: we may have a timer pending to call the IdleHandler (see the | 238 idle_timer_.Stop(); |
| 239 // WidgetHidden() code). But we don't bother to cancel it as it is | |
| 240 // benign and won't do anything if the tab is un-hidden when it is | |
| 241 // called. | |
| 242 } | 239 } |
| 243 | 240 |
| 244 void RenderThread::Resolve(const char* name, size_t length) { | 241 void RenderThread::Resolve(const char* name, size_t length) { |
| 245 return dns_master_->Resolve(name, length); | 242 return dns_master_->Resolve(name, length); |
| 246 } | 243 } |
| 247 | 244 |
| 248 void RenderThread::SendHistograms(int sequence_number) { | 245 void RenderThread::SendHistograms(int sequence_number) { |
| 249 return histogram_snapshots_->SendHistograms(sequence_number); | 246 return histogram_snapshots_->SendHistograms(sequence_number); |
| 250 } | 247 } |
| 251 | 248 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 void RenderThread::OnPageActionsUpdated( | 281 void RenderThread::OnPageActionsUpdated( |
| 285 const std::string& extension_id, | 282 const std::string& extension_id, |
| 286 const std::vector<std::string>& page_actions) { | 283 const std::vector<std::string>& page_actions) { |
| 287 ExtensionProcessBindings::SetPageActions(extension_id, page_actions); | 284 ExtensionProcessBindings::SetPageActions(extension_id, page_actions); |
| 288 } | 285 } |
| 289 | 286 |
| 290 void RenderThread::OnExtensionSetAPIPermissions( | 287 void RenderThread::OnExtensionSetAPIPermissions( |
| 291 const std::string& extension_id, | 288 const std::string& extension_id, |
| 292 const std::vector<std::string>& permissions) { | 289 const std::vector<std::string>& permissions) { |
| 293 ExtensionProcessBindings::SetAPIPermissions(extension_id, permissions); | 290 ExtensionProcessBindings::SetAPIPermissions(extension_id, permissions); |
| 291 |
| 292 // This is called when starting a new extension page, so start the idle |
| 293 // handler ticking. |
| 294 DCHECK(is_extension_process()); |
| 295 ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); |
| 294 } | 296 } |
| 295 | 297 |
| 296 void RenderThread::OnExtensionSetHostPermissions( | 298 void RenderThread::OnExtensionSetHostPermissions( |
| 297 const GURL& extension_url, const std::vector<URLPattern>& permissions) { | 299 const GURL& extension_url, const std::vector<URLPattern>& permissions) { |
| 298 ExtensionProcessBindings::SetHostPermissions(extension_url, permissions); | 300 ExtensionProcessBindings::SetHostPermissions(extension_url, permissions); |
| 299 } | 301 } |
| 300 | 302 |
| 301 void RenderThread::OnDOMStorageEvent( | 303 void RenderThread::OnDOMStorageEvent( |
| 302 const ViewMsg_DOMStorageEvent_Params& params) { | 304 const ViewMsg_DOMStorageEvent_Params& params) { |
| 303 if (!dom_storage_event_dispatcher_.get()) | 305 if (!dom_storage_event_dispatcher_.get()) |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 | 495 |
| 494 static void AddHistogramSample(void* hist, int sample) { | 496 static void AddHistogramSample(void* hist, int sample) { |
| 495 Histogram* histogram = static_cast<Histogram *>(hist); | 497 Histogram* histogram = static_cast<Histogram *>(hist); |
| 496 histogram->Add(sample); | 498 histogram->Add(sample); |
| 497 } | 499 } |
| 498 | 500 |
| 499 void RenderThread::EnsureWebKitInitialized() { | 501 void RenderThread::EnsureWebKitInitialized() { |
| 500 if (webkit_client_.get()) | 502 if (webkit_client_.get()) |
| 501 return; | 503 return; |
| 502 | 504 |
| 505 // For extensions, we want to ensure we call the IdleHandler every so often, |
| 506 // even if the extension keeps up activity. |
| 507 if (is_extension_process()) { |
| 508 forced_idle_timer_.Start( |
| 509 base::TimeDelta::FromSeconds(kMaxExtensionIdleHandlerDelayS), |
| 510 this, &RenderThread::IdleHandler); |
| 511 } |
| 512 |
| 503 v8::V8::SetCounterFunction(StatsTable::FindLocation); | 513 v8::V8::SetCounterFunction(StatsTable::FindLocation); |
| 504 v8::V8::SetCreateHistogramFunction(CreateHistogram); | 514 v8::V8::SetCreateHistogramFunction(CreateHistogram); |
| 505 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); | 515 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); |
| 506 | 516 |
| 507 webkit_client_.reset(new RendererWebKitClientImpl); | 517 webkit_client_.reset(new RendererWebKitClientImpl); |
| 508 WebKit::initialize(webkit_client_.get()); | 518 WebKit::initialize(webkit_client_.get()); |
| 509 | 519 |
| 510 WebScriptController::enableV8SingleThreadMode(); | 520 WebScriptController::enableV8SingleThreadMode(); |
| 511 | 521 |
| 512 // chrome: pages should not be accessible by normal content, and should | 522 // chrome: pages should not be accessible by normal content, and should |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 !command_line.HasSwitch(switches::kDisableDesktopNotifications)); | 604 !command_line.HasSwitch(switches::kDisableDesktopNotifications)); |
| 595 #endif | 605 #endif |
| 596 | 606 |
| 597 WebRuntimeFeatures::enableLocalStorage( | 607 WebRuntimeFeatures::enableLocalStorage( |
| 598 !command_line.HasSwitch(switches::kDisableLocalStorage)); | 608 !command_line.HasSwitch(switches::kDisableLocalStorage)); |
| 599 WebRuntimeFeatures::enableSessionStorage( | 609 WebRuntimeFeatures::enableSessionStorage( |
| 600 command_line.HasSwitch(switches::kEnableSessionStorage)); | 610 command_line.HasSwitch(switches::kEnableSessionStorage)); |
| 601 } | 611 } |
| 602 | 612 |
| 603 void RenderThread::IdleHandler() { | 613 void RenderThread::IdleHandler() { |
| 604 // It is possible that the timer was set while the widgets were idle, | |
| 605 // but that they are no longer idle. If so, just return. | |
| 606 if (!widget_count_ || hidden_widget_count_ < widget_count_) | |
| 607 return; | |
| 608 | |
| 609 #if defined(OS_WIN) && defined(USE_TCMALLOC) | 614 #if defined(OS_WIN) && defined(USE_TCMALLOC) |
| 610 MallocExtension::instance()->ReleaseFreeMemory(); | 615 MallocExtension::instance()->ReleaseFreeMemory(); |
| 611 #endif | 616 #endif |
| 612 | 617 |
| 613 LOG(INFO) << "RenderThread calling v8 IdleNotification for " << this; | 618 LOG(INFO) << "RenderThread calling v8 IdleNotification for " << this; |
| 614 v8::V8::IdleNotification(); | 619 v8::V8::IdleNotification(); |
| 615 | 620 |
| 616 // Schedule next invocation. | 621 // Schedule next invocation. |
| 617 // Dampen the delay using the algorithm: | 622 // Dampen the delay using the algorithm: |
| 618 // delay = delay + 1 / (delay + 2) | 623 // delay = delay + 1 / (delay + 2) |
| 619 // Using floor(delay) has a dampening effect such as: | 624 // Using floor(delay) has a dampening effect such as: |
| 620 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... | 625 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... |
| 621 // Note that idle_notification_delay_in_s_ would be reset to | 626 // Note that idle_notification_delay_in_s_ would be reset to |
| 622 // kInitialIdleHandlerDelayS in RenderThread::WidgetHidden. | 627 // kInitialIdleHandlerDelayS in RenderThread::WidgetHidden. |
| 623 idle_notification_delay_in_s_ += | 628 ScheduleIdleHandler(idle_notification_delay_in_s_ + |
| 624 1.0 / (idle_notification_delay_in_s_ + 2.0); | 629 1.0 / (idle_notification_delay_in_s_ + 2.0)); |
| 630 if (is_extension_process()) { |
| 631 // Dampen the forced delay as well if the extension stays idle for long |
| 632 // periods of time. |
| 633 int64 forced_delay_s = |
| 634 std::max(static_cast<int64>(idle_notification_delay_in_s_), |
| 635 kMaxExtensionIdleHandlerDelayS); |
| 636 forced_idle_timer_.Stop(); |
| 637 forced_idle_timer_.Start( |
| 638 base::TimeDelta::FromSeconds(forced_delay_s), |
| 639 this, &RenderThread::IdleHandler); |
| 640 } |
| 641 } |
| 625 | 642 |
| 626 // Schedule the next timer. | 643 void RenderThread::ScheduleIdleHandler(double initial_delay_s) { |
| 627 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 644 idle_notification_delay_in_s_ = initial_delay_s; |
| 628 task_factory_->NewRunnableMethod(&RenderThread::IdleHandler), | 645 idle_timer_.Stop(); |
| 629 static_cast<int64>(floor(idle_notification_delay_in_s_)) * 1000); | 646 idle_timer_.Start( |
| 647 base::TimeDelta::FromSeconds(static_cast<int64>(initial_delay_s)), |
| 648 this, &RenderThread::IdleHandler); |
| 630 } | 649 } |
| 631 | 650 |
| 632 void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, | 651 void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, |
| 633 const ListValue& args) { | 652 const ListValue& args) { |
| 634 RendererExtensionBindings::Invoke(function_name, args, NULL); | 653 RendererExtensionBindings::Invoke(function_name, args, NULL); |
| 654 |
| 655 // Reset the idle handler each time there's any activity like event or message |
| 656 // dispatch, for which Invoke is the chokepoint. |
| 657 if (is_extension_process()) |
| 658 ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayS); |
| 635 } | 659 } |
| 636 | 660 |
| 637 void RenderThread::OnPurgeMemory() { | 661 void RenderThread::OnPurgeMemory() { |
| 638 spellchecker_.reset(new SpellCheck()); | 662 spellchecker_.reset(new SpellCheck()); |
| 639 | 663 |
| 640 EnsureWebKitInitialized(); | 664 EnsureWebKitInitialized(); |
| 641 | 665 |
| 642 // Clear the object cache (as much as possible; some live objects cannot be | 666 // Clear the object cache (as much as possible; some live objects cannot be |
| 643 // freed). | 667 // freed). |
| 644 WebCache::clear(); | 668 WebCache::clear(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 spellchecker_->EnableAutoSpellCorrect(auto_spell_correct); | 712 spellchecker_->EnableAutoSpellCorrect(auto_spell_correct); |
| 689 } | 713 } |
| 690 | 714 |
| 691 void RenderThread::OnSpellCheckWordAdded(const std::string& word) { | 715 void RenderThread::OnSpellCheckWordAdded(const std::string& word) { |
| 692 spellchecker_->WordAdded(word); | 716 spellchecker_->WordAdded(word); |
| 693 } | 717 } |
| 694 | 718 |
| 695 void RenderThread::OnSpellCheckEnableAutoSpellCorrect(bool enable) { | 719 void RenderThread::OnSpellCheckEnableAutoSpellCorrect(bool enable) { |
| 696 spellchecker_->EnableAutoSpellCorrect(enable); | 720 spellchecker_->EnableAutoSpellCorrect(enable); |
| 697 } | 721 } |
| OLD | NEW |