Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: chrome/renderer/render_thread.cc

Issue 460062: Hook up V8 idle notifications for extension prcoesses. (Closed)
Patch Set: dampen max timer Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/renderer/render_thread.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/renderer/render_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698