OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/renderer/render_thread_impl.h" | 5 #include "content/renderer/render_thread_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <map> | 9 #include <map> |
10 #include <vector> | 10 #include <vector> |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 using WebKit::WebFrame; | 93 using WebKit::WebFrame; |
94 using WebKit::WebNetworkStateNotifier; | 94 using WebKit::WebNetworkStateNotifier; |
95 using WebKit::WebRuntimeFeatures; | 95 using WebKit::WebRuntimeFeatures; |
96 using WebKit::WebScriptController; | 96 using WebKit::WebScriptController; |
97 using WebKit::WebString; | 97 using WebKit::WebString; |
98 using WebKit::WebStorageEventDispatcher; | 98 using WebKit::WebStorageEventDispatcher; |
99 using WebKit::WebView; | 99 using WebKit::WebView; |
100 using content::RenderProcessObserver; | 100 using content::RenderProcessObserver; |
101 | 101 |
102 namespace { | 102 namespace { |
103 static const int64 kInitialIdleHandlerDelayMs = 1000; | 103 static const int64 kLongIdleDelayMs = 30000; |
104 static const int64 kShortIdleDelayMs = 1000; | |
105 static const int kIdleCPUUsageThresholdInPercents = 3; | |
ulan
2011/11/15 19:08:53
I have chosen these values based on GeneralMixMemo
| |
104 | 106 |
105 #if defined(TOUCH_UI) | 107 #if defined(TOUCH_UI) |
106 static const int kPopupListBoxMinimumRowHeight = 60; | 108 static const int kPopupListBoxMinimumRowHeight = 60; |
107 #endif | 109 #endif |
108 | 110 |
109 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access | 111 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access |
110 // incorrectly from the wrong thread. | 112 // incorrectly from the wrong thread. |
111 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > lazy_tls( | 113 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > lazy_tls( |
112 base::LINKER_INITIALIZED); | 114 base::LINKER_INITIALIZED); |
113 | 115 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 if (RenderProcessImpl::InProcessPlugins()) | 187 if (RenderProcessImpl::InProcessPlugins()) |
186 initialize_com_.reset(new base::win::ScopedCOMInitializer()); | 188 initialize_com_.reset(new base::win::ScopedCOMInitializer()); |
187 #endif | 189 #endif |
188 | 190 |
189 // In single process the single process is all there is. | 191 // In single process the single process is all there is. |
190 suspend_webkit_shared_timer_ = true; | 192 suspend_webkit_shared_timer_ = true; |
191 notify_webkit_of_modal_loop_ = true; | 193 notify_webkit_of_modal_loop_ = true; |
192 plugin_refresh_allowed_ = true; | 194 plugin_refresh_allowed_ = true; |
193 widget_count_ = 0; | 195 widget_count_ = 0; |
194 hidden_widget_count_ = 0; | 196 hidden_widget_count_ = 0; |
195 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; | 197 idle_delay_ms_ = kLongIdleDelayMs; |
198 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | |
199 #if defined(OS_MACOSX) | |
200 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle, | |
201 NULL)); | |
202 #else | |
203 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); | |
204 #endif | |
196 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); | 205 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); |
197 | 206 |
198 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); | 207 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); |
199 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); | 208 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); |
200 | 209 |
201 db_message_filter_ = new DBMessageFilter(); | 210 db_message_filter_ = new DBMessageFilter(); |
202 AddFilter(db_message_filter_.get()); | 211 AddFilter(db_message_filter_.get()); |
203 | 212 |
204 vc_manager_ = new VideoCaptureImplManager(); | 213 vc_manager_ = new VideoCaptureImplManager(); |
205 AddFilter(vc_manager_->video_capture_message_filter()); | 214 AddFilter(vc_manager_->video_capture_message_filter()); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 } | 399 } |
391 | 400 |
392 void RenderThreadImpl::SetResourceDispatcherDelegate( | 401 void RenderThreadImpl::SetResourceDispatcherDelegate( |
393 content::ResourceDispatcherDelegate* delegate) { | 402 content::ResourceDispatcherDelegate* delegate) { |
394 resource_dispatcher()->set_delegate(delegate); | 403 resource_dispatcher()->set_delegate(delegate); |
395 } | 404 } |
396 | 405 |
397 void RenderThreadImpl::WidgetHidden() { | 406 void RenderThreadImpl::WidgetHidden() { |
398 DCHECK(hidden_widget_count_ < widget_count_); | 407 DCHECK(hidden_widget_count_ < widget_count_); |
399 hidden_widget_count_++; | 408 hidden_widget_count_++; |
400 | |
401 if (!content::GetContentClient()->renderer()-> | |
402 RunIdleHandlerWhenWidgetsHidden()) { | |
403 return; | |
404 } | |
405 | |
406 if (widget_count_ && hidden_widget_count_ == widget_count_) | 409 if (widget_count_ && hidden_widget_count_ == widget_count_) |
407 ScheduleIdleHandler(kInitialIdleHandlerDelayMs); | 410 ResetIdleTimer(); |
408 } | 411 } |
409 | 412 |
410 void RenderThreadImpl::WidgetRestored() { | 413 void RenderThreadImpl::WidgetRestored() { |
411 DCHECK_GT(hidden_widget_count_, 0); | 414 DCHECK_GT(hidden_widget_count_, 0); |
412 hidden_widget_count_--; | 415 hidden_widget_count_--; |
413 if (!content::GetContentClient()->renderer()-> | |
414 RunIdleHandlerWhenWidgetsHidden()) { | |
415 return; | |
416 } | |
417 | |
418 idle_timer_.Stop(); | |
419 } | 416 } |
420 | 417 |
421 void RenderThreadImpl::EnsureWebKitInitialized() { | 418 void RenderThreadImpl::EnsureWebKitInitialized() { |
422 if (webkit_platform_support_.get()) | 419 if (webkit_platform_support_.get()) |
423 return; | 420 return; |
424 | 421 |
425 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); | 422 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); |
426 v8::V8::SetCreateHistogramFunction(CreateHistogram); | 423 v8::V8::SetCreateHistogramFunction(CreateHistogram); |
427 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); | 424 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); |
428 | 425 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 | 514 |
518 WebRuntimeFeatures::enableFileSystem( | 515 WebRuntimeFeatures::enableFileSystem( |
519 !command_line.HasSwitch(switches::kDisableFileSystem)); | 516 !command_line.HasSwitch(switches::kDisableFileSystem)); |
520 | 517 |
521 WebRuntimeFeatures::enableJavaScriptI18NAPI( | 518 WebRuntimeFeatures::enableJavaScriptI18NAPI( |
522 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); | 519 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); |
523 | 520 |
524 WebRuntimeFeatures::enableQuota(true); | 521 WebRuntimeFeatures::enableQuota(true); |
525 | 522 |
526 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); | 523 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); |
524 | |
525 ScheduleIdleHandler(kLongIdleDelayMs); | |
527 } | 526 } |
528 | 527 |
529 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { | 528 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { |
530 Send(new ViewHostMsg_UserMetricsRecordAction(action)); | 529 Send(new ViewHostMsg_UserMetricsRecordAction(action)); |
531 } | 530 } |
532 | 531 |
533 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( | 532 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( |
534 uint32 buffer_size) { | 533 uint32 buffer_size) { |
535 base::SharedMemoryHandle mem_handle; | 534 base::SharedMemoryHandle mem_handle; |
536 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( | 535 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( |
537 buffer_size, &mem_handle)); | 536 buffer_size, &mem_handle)); |
538 return mem_handle; | 537 return mem_handle; |
539 } | 538 } |
540 | 539 |
541 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) { | 540 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) { |
542 WebScriptController::registerExtension(extension); | 541 WebScriptController::registerExtension(extension); |
543 v8_extensions_.insert(extension->name()); | 542 v8_extensions_.insert(extension->name()); |
544 } | 543 } |
545 | 544 |
546 bool RenderThreadImpl::IsRegisteredExtension( | 545 bool RenderThreadImpl::IsRegisteredExtension( |
547 const std::string& v8_extension_name) const { | 546 const std::string& v8_extension_name) const { |
548 return v8_extensions_.find(v8_extension_name) != v8_extensions_.end(); | 547 return v8_extensions_.find(v8_extension_name) != v8_extensions_.end(); |
549 } | 548 } |
550 | 549 |
551 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { | 550 void RenderThreadImpl::ResetIdleTimer() { |
552 idle_notification_delay_in_ms_ = initial_delay_ms; | 551 if (idle_delay_ms_ > kShortIdleDelayMs) { |
553 idle_timer_.Stop(); | 552 idle_timer_.Stop(); |
554 idle_timer_.Start(FROM_HERE, | 553 ScheduleIdleHandler(kShortIdleDelayMs); |
555 base::TimeDelta::FromMilliseconds(initial_delay_ms), | 554 } |
556 this, &RenderThreadImpl::IdleHandler); | |
557 } | |
558 | |
559 void RenderThreadImpl::IdleHandler() { | |
560 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) | |
561 MallocExtension::instance()->ReleaseFreeMemory(); | |
562 #endif | |
563 | |
564 v8::V8::IdleNotification(); | |
565 | |
566 // Schedule next invocation. | |
567 // Dampen the delay using the algorithm (if delay is in seconds): | |
568 // delay = delay + 1 / (delay + 2) | |
569 // Using floor(delay) has a dampening effect such as: | |
570 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... | |
571 // If the delay is in milliseconds, the above formula is equivalent to: | |
572 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) | |
573 // which is equivalent to | |
574 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). | |
575 // Note that idle_notification_delay_in_ms_ would be reset to | |
576 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. | |
577 ScheduleIdleHandler(idle_notification_delay_in_ms_ + | |
578 1000000 / (idle_notification_delay_in_ms_ + 2000)); | |
579 | |
580 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); | |
581 } | |
582 | |
583 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { | |
584 return idle_notification_delay_in_ms_; | |
585 } | |
586 | |
587 void RenderThreadImpl::SetIdleNotificationDelayInMs( | |
588 int64 idle_notification_delay_in_ms) { | |
589 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; | |
590 } | 555 } |
591 | 556 |
592 #if defined(OS_WIN) | 557 #if defined(OS_WIN) |
593 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { | 558 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { |
594 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); | 559 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); |
595 } | 560 } |
596 | 561 |
597 void RenderThreadImpl::ReleaseCachedFonts() { | 562 void RenderThreadImpl::ReleaseCachedFonts() { |
598 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); | 563 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); |
599 } | 564 } |
(...skipping 16 matching lines...) Expand all Loading... | |
616 } | 581 } |
617 | 582 |
618 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { | 583 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { |
619 suspend_webkit_shared_timer_ = false; | 584 suspend_webkit_shared_timer_ = false; |
620 } | 585 } |
621 | 586 |
622 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() { | 587 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() { |
623 notify_webkit_of_modal_loop_ = false; | 588 notify_webkit_of_modal_loop_ = false; |
624 } | 589 } |
625 | 590 |
591 void RenderThreadImpl::IdleHandler() { | |
592 // Dampen the delay using the algorithm (if delay is in seconds): | |
593 // new_delay = delay + 1 / (delay + 2) | |
594 // Using floor(delay) has a dampening effect such as: | |
595 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... | |
596 // If the delay is in milliseconds, the above formula is equivalent to: | |
597 // new_delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) | |
598 // which is equivalent to | |
599 // new_delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). | |
600 int64 new_delay_ms = idle_delay_ms_ + 1000000 / (idle_delay_ms_ + 2000); | |
601 if (process_metrics_->GetCPUUsage() < kIdleCPUUsageThresholdInPercents) { | |
602 new_delay_ms = kShortIdleDelayMs; | |
603 // Make sure that CPU usage was sampled for short delay, not long delay. | |
604 if (idle_delay_ms_ == kShortIdleDelayMs) { | |
605 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) | |
606 MallocExtension::instance()->ReleaseFreeMemory(); | |
607 #endif | |
608 if (v8::V8::IdleNotification()) { | |
609 // V8 finished collecting garbage. | |
610 new_delay_ms = kLongIdleDelayMs; | |
611 } | |
612 } | |
613 } | |
614 ScheduleIdleHandler(new_delay_ms); | |
615 } | |
616 | |
626 void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const GURL& url, | 617 void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const GURL& url, |
627 double zoom_level) { | 618 double zoom_level) { |
628 RenderViewZoomer zoomer(url, zoom_level); | 619 RenderViewZoomer zoomer(url, zoom_level); |
629 content::RenderView::ForEach(&zoomer); | 620 content::RenderView::ForEach(&zoomer); |
630 } | 621 } |
631 | 622 |
632 void RenderThreadImpl::OnDOMStorageEvent( | 623 void RenderThreadImpl::OnDOMStorageEvent( |
633 const DOMStorageMsg_Event_Params& params) { | 624 const DOMStorageMsg_Event_Params& params) { |
634 if (!dom_storage_event_dispatcher_.get()) | 625 if (!dom_storage_event_dispatcher_.get()) |
635 dom_storage_event_dispatcher_.reset(WebStorageEventDispatcher::create()); | 626 dom_storage_event_dispatcher_.reset(WebStorageEventDispatcher::create()); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
776 void RenderThreadImpl::OnNetworkStateChanged(bool online) { | 767 void RenderThreadImpl::OnNetworkStateChanged(bool online) { |
777 EnsureWebKitInitialized(); | 768 EnsureWebKitInitialized(); |
778 WebNetworkStateNotifier::setOnLine(online); | 769 WebNetworkStateNotifier::setOnLine(online); |
779 } | 770 } |
780 | 771 |
781 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { | 772 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { |
782 content::GetContentClient()->SetActiveURL(data); | 773 content::GetContentClient()->SetActiveURL(data); |
783 CHECK(false); | 774 CHECK(false); |
784 } | 775 } |
785 | 776 |
777 void RenderThreadImpl::ScheduleIdleHandler(int64 delay_ms) { | |
778 idle_delay_ms_ = delay_ms; | |
779 idle_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), | |
780 this, &RenderThreadImpl::IdleHandler); | |
781 } | |
782 | |
786 scoped_refptr<base::MessageLoopProxy> | 783 scoped_refptr<base::MessageLoopProxy> |
787 RenderThreadImpl::GetFileThreadMessageLoopProxy() { | 784 RenderThreadImpl::GetFileThreadMessageLoopProxy() { |
788 DCHECK(message_loop() == MessageLoop::current()); | 785 DCHECK(message_loop() == MessageLoop::current()); |
789 if (!file_thread_.get()) { | 786 if (!file_thread_.get()) { |
790 file_thread_.reset(new base::Thread("Renderer::FILE")); | 787 file_thread_.reset(new base::Thread("Renderer::FILE")); |
791 file_thread_->Start(); | 788 file_thread_->Start(); |
792 } | 789 } |
793 return file_thread_->message_loop_proxy(); | 790 return file_thread_->message_loop_proxy(); |
794 } | 791 } |
OLD | NEW |