| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 kInitialIdleHandlerDelayMs = 1000; |
| 104 static const int64 kShortIdleHandlerDelayMs = 1000; |
| 105 static const int64 kLongIdleHandlerDelayMs = 30*1000; |
| 106 static const int kIdleCPUUsageThresholdInPercents = 3; |
| 104 | 107 |
| 105 #if defined(TOUCH_UI) | 108 #if defined(TOUCH_UI) |
| 106 static const int kPopupListBoxMinimumRowHeight = 60; | 109 static const int kPopupListBoxMinimumRowHeight = 60; |
| 107 #endif | 110 #endif |
| 108 | 111 |
| 109 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access | 112 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access |
| 110 // incorrectly from the wrong thread. | 113 // incorrectly from the wrong thread. |
| 111 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > | 114 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > |
| 112 lazy_tls = LAZY_INSTANCE_INITIALIZER; | 115 lazy_tls = LAZY_INSTANCE_INITIALIZER; |
| 113 | 116 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 initialize_com_.reset(new base::win::ScopedCOMInitializer()); | 189 initialize_com_.reset(new base::win::ScopedCOMInitializer()); |
| 187 #endif | 190 #endif |
| 188 | 191 |
| 189 // In single process the single process is all there is. | 192 // In single process the single process is all there is. |
| 190 suspend_webkit_shared_timer_ = true; | 193 suspend_webkit_shared_timer_ = true; |
| 191 notify_webkit_of_modal_loop_ = true; | 194 notify_webkit_of_modal_loop_ = true; |
| 192 plugin_refresh_allowed_ = true; | 195 plugin_refresh_allowed_ = true; |
| 193 widget_count_ = 0; | 196 widget_count_ = 0; |
| 194 hidden_widget_count_ = 0; | 197 hidden_widget_count_ = 0; |
| 195 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; | 198 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; |
| 199 idle_notifications_to_skip_ = 0; |
| 200 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
| 201 #if defined(OS_MACOSX) |
| 202 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle, |
| 203 NULL)); |
| 204 #else |
| 205 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); |
| 206 #endif |
| 207 process_metrics_->GetCPUUsage(); // Initialize CPU usage counters. |
| 196 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); | 208 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); |
| 197 | 209 |
| 198 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); | 210 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); |
| 199 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); | 211 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); |
| 200 | 212 |
| 201 db_message_filter_ = new DBMessageFilter(); | 213 db_message_filter_ = new DBMessageFilter(); |
| 202 AddFilter(db_message_filter_.get()); | 214 AddFilter(db_message_filter_.get()); |
| 203 | 215 |
| 204 vc_manager_ = new VideoCaptureImplManager(); | 216 vc_manager_ = new VideoCaptureImplManager(); |
| 205 AddFilter(vc_manager_->video_capture_message_filter()); | 217 AddFilter(vc_manager_->video_capture_message_filter()); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 } | 420 } |
| 409 | 421 |
| 410 void RenderThreadImpl::WidgetRestored() { | 422 void RenderThreadImpl::WidgetRestored() { |
| 411 DCHECK_GT(hidden_widget_count_, 0); | 423 DCHECK_GT(hidden_widget_count_, 0); |
| 412 hidden_widget_count_--; | 424 hidden_widget_count_--; |
| 413 if (!content::GetContentClient()->renderer()-> | 425 if (!content::GetContentClient()->renderer()-> |
| 414 RunIdleHandlerWhenWidgetsHidden()) { | 426 RunIdleHandlerWhenWidgetsHidden()) { |
| 415 return; | 427 return; |
| 416 } | 428 } |
| 417 | 429 |
| 418 idle_timer_.Stop(); | 430 ScheduleIdleHandler(kLongIdleHandlerDelayMs); |
| 419 } | 431 } |
| 420 | 432 |
| 421 void RenderThreadImpl::EnsureWebKitInitialized() { | 433 void RenderThreadImpl::EnsureWebKitInitialized() { |
| 422 if (webkit_platform_support_.get()) | 434 if (webkit_platform_support_.get()) |
| 423 return; | 435 return; |
| 424 | 436 |
| 425 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); | 437 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); |
| 426 v8::V8::SetCreateHistogramFunction(CreateHistogram); | 438 v8::V8::SetCreateHistogramFunction(CreateHistogram); |
| 427 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); | 439 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); |
| 428 | 440 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 529 |
| 518 WebRuntimeFeatures::enableFileSystem( | 530 WebRuntimeFeatures::enableFileSystem( |
| 519 !command_line.HasSwitch(switches::kDisableFileSystem)); | 531 !command_line.HasSwitch(switches::kDisableFileSystem)); |
| 520 | 532 |
| 521 WebRuntimeFeatures::enableJavaScriptI18NAPI( | 533 WebRuntimeFeatures::enableJavaScriptI18NAPI( |
| 522 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); | 534 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); |
| 523 | 535 |
| 524 WebRuntimeFeatures::enableQuota(true); | 536 WebRuntimeFeatures::enableQuota(true); |
| 525 | 537 |
| 526 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); | 538 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); |
| 539 |
| 540 if (content::GetContentClient()->renderer()-> |
| 541 RunIdleHandlerWhenWidgetsHidden()) { |
| 542 ScheduleIdleHandler(kLongIdleHandlerDelayMs); |
| 543 } |
| 527 } | 544 } |
| 528 | 545 |
| 529 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { | 546 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { |
| 530 Send(new ViewHostMsg_UserMetricsRecordAction(action)); | 547 Send(new ViewHostMsg_UserMetricsRecordAction(action)); |
| 531 } | 548 } |
| 532 | 549 |
| 533 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( | 550 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( |
| 534 uint32 buffer_size) { | 551 uint32 buffer_size) { |
| 535 base::SharedMemoryHandle mem_handle; | 552 base::SharedMemoryHandle mem_handle; |
| 536 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( | 553 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 550 | 567 |
| 551 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { | 568 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { |
| 552 idle_notification_delay_in_ms_ = initial_delay_ms; | 569 idle_notification_delay_in_ms_ = initial_delay_ms; |
| 553 idle_timer_.Stop(); | 570 idle_timer_.Stop(); |
| 554 idle_timer_.Start(FROM_HERE, | 571 idle_timer_.Start(FROM_HERE, |
| 555 base::TimeDelta::FromMilliseconds(initial_delay_ms), | 572 base::TimeDelta::FromMilliseconds(initial_delay_ms), |
| 556 this, &RenderThreadImpl::IdleHandler); | 573 this, &RenderThreadImpl::IdleHandler); |
| 557 } | 574 } |
| 558 | 575 |
| 559 void RenderThreadImpl::IdleHandler() { | 576 void RenderThreadImpl::IdleHandler() { |
| 560 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) | 577 bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) && |
| 578 content::GetContentClient()->renderer()-> |
| 579 RunIdleHandlerWhenWidgetsHidden(); |
| 580 if (run_in_foreground_tab) { |
| 581 IdleHandlerInForegroundTab(); |
| 582 return; |
| 583 } |
| 584 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) |
| 561 MallocExtension::instance()->ReleaseFreeMemory(); | 585 MallocExtension::instance()->ReleaseFreeMemory(); |
| 562 #endif | 586 #endif |
| 563 | 587 |
| 564 v8::V8::IdleNotification(); | 588 v8::V8::IdleNotification(); |
| 565 | 589 |
| 566 // Schedule next invocation. | 590 // Schedule next invocation. |
| 567 // Dampen the delay using the algorithm (if delay is in seconds): | 591 // Dampen the delay using the algorithm (if delay is in seconds): |
| 568 // delay = delay + 1 / (delay + 2) | 592 // delay = delay + 1 / (delay + 2) |
| 569 // Using floor(delay) has a dampening effect such as: | 593 // Using floor(delay) has a dampening effect such as: |
| 570 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... | 594 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... |
| 571 // If the delay is in milliseconds, the above formula is equivalent to: | 595 // If the delay is in milliseconds, the above formula is equivalent to: |
| 572 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) | 596 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) |
| 573 // which is equivalent to | 597 // which is equivalent to |
| 574 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). | 598 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). |
| 575 // Note that idle_notification_delay_in_ms_ would be reset to | 599 // Note that idle_notification_delay_in_ms_ would be reset to |
| 576 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. | 600 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. |
| 577 ScheduleIdleHandler(idle_notification_delay_in_ms_ + | 601 ScheduleIdleHandler(idle_notification_delay_in_ms_ + |
| 578 1000000 / (idle_notification_delay_in_ms_ + 2000)); | 602 1000000 / (idle_notification_delay_in_ms_ + 2000)); |
| 579 | 603 |
| 580 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); | 604 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); |
| 581 } | 605 } |
| 582 | 606 |
| 607 void RenderThreadImpl::IdleHandlerInForegroundTab() { |
| 608 // Increase the delay in the same way as in IdleHandler, |
| 609 // but make it periodic by reseting it once it is too big. |
| 610 int64 new_delay_ms = idle_notification_delay_in_ms_ + |
| 611 1000000 / (idle_notification_delay_in_ms_ + 2000); |
| 612 if (new_delay_ms >= kLongIdleHandlerDelayMs) |
| 613 new_delay_ms = kShortIdleHandlerDelayMs; |
| 614 |
| 615 // Sample the CPU usage on each timer event, so that it is more accurate. |
| 616 double cpu_usage = process_metrics_->GetCPUUsage(); |
| 617 |
| 618 if (idle_notifications_to_skip_ > 0) { |
| 619 idle_notifications_to_skip_--; |
| 620 } else if (cpu_usage < kIdleCPUUsageThresholdInPercents) { |
| 621 if (v8::V8::IdleNotification()) { |
| 622 // V8 finished collecting garbage. |
| 623 new_delay_ms = kLongIdleHandlerDelayMs; |
| 624 } |
| 625 } |
| 626 |
| 627 ScheduleIdleHandler(new_delay_ms); |
| 628 } |
| 629 |
| 583 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { | 630 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { |
| 584 return idle_notification_delay_in_ms_; | 631 return idle_notification_delay_in_ms_; |
| 585 } | 632 } |
| 586 | 633 |
| 587 void RenderThreadImpl::SetIdleNotificationDelayInMs( | 634 void RenderThreadImpl::SetIdleNotificationDelayInMs( |
| 588 int64 idle_notification_delay_in_ms) { | 635 int64 idle_notification_delay_in_ms) { |
| 589 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; | 636 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; |
| 590 } | 637 } |
| 591 | 638 |
| 639 void RenderThreadImpl::PostponeIdleNotification() { |
| 640 idle_notifications_to_skip_ = 2; |
| 641 } |
| 642 |
| 592 #if defined(OS_WIN) | 643 #if defined(OS_WIN) |
| 593 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { | 644 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { |
| 594 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); | 645 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); |
| 595 } | 646 } |
| 596 | 647 |
| 597 void RenderThreadImpl::ReleaseCachedFonts() { | 648 void RenderThreadImpl::ReleaseCachedFonts() { |
| 598 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); | 649 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); |
| 599 } | 650 } |
| 600 | 651 |
| 601 #endif // OS_WIN | 652 #endif // OS_WIN |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 | 836 |
| 786 scoped_refptr<base::MessageLoopProxy> | 837 scoped_refptr<base::MessageLoopProxy> |
| 787 RenderThreadImpl::GetFileThreadMessageLoopProxy() { | 838 RenderThreadImpl::GetFileThreadMessageLoopProxy() { |
| 788 DCHECK(message_loop() == MessageLoop::current()); | 839 DCHECK(message_loop() == MessageLoop::current()); |
| 789 if (!file_thread_.get()) { | 840 if (!file_thread_.get()) { |
| 790 file_thread_.reset(new base::Thread("Renderer::FILE")); | 841 file_thread_.reset(new base::Thread("Renderer::FILE")); |
| 791 file_thread_->Start(); | 842 file_thread_->Start(); |
| 792 } | 843 } |
| 793 return file_thread_->message_loop_proxy(); | 844 return file_thread_->message_loop_proxy(); |
| 794 } | 845 } |
| OLD | NEW |