Index: components/scheduler/renderer/renderer_scheduler_impl.cc |
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc |
index 4b565314a7996816887d0a71aaca51161fe5515c..a13d862d9c3bade50f8fada56c0934673ad6ecbc 100644 |
--- a/components/scheduler/renderer/renderer_scheduler_impl.cc |
+++ b/components/scheduler/renderer/renderer_scheduler_impl.cc |
@@ -54,6 +54,10 @@ RendererSchedulerImpl::RendererSchedulerImpl( |
end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
&RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
+ suspend_timers_when_backgrounded_closure_.Reset( |
+ base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, |
+ weak_factory_.GetWeakPtr())); |
+ |
timer_task_runner_->AddTaskObserver( |
&MainThreadOnly().timer_task_cost_estimator_); |
@@ -81,6 +85,8 @@ RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() |
current_policy_(Policy::NORMAL), |
timer_queue_suspend_count_(0), |
renderer_hidden_(false), |
+ renderer_backgrounded_(false), |
+ timer_queue_suspended_for_backgrounded_renderer_(false), |
was_shutdown_(false) {} |
RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
@@ -231,6 +237,41 @@ void RendererSchedulerImpl::OnRendererVisible() { |
this, AsValue(helper_.Now())); |
} |
+void RendererSchedulerImpl::OnRendererBackgrounded() { |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::OnRendererBackgrounded"); |
+ helper_.CheckOnValidThread(); |
+ if (helper_.IsShutdown() || MainThreadOnly().renderer_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().renderer_backgrounded_ = false; |
+ if (kSuspendTimersWhenBackgroundedDelayMillis < 0) |
+ return; |
+ |
+ suspend_timers_when_backgrounded_closure_.Cancel(); |
+ base::TimeDelta suspend_timers_when_backgrounded_delay = |
+ base::TimeDelta::FromMilliseconds( |
+ kSuspendTimersWhenBackgroundedDelayMillis); |
+ control_task_runner_->PostDelayedTask( |
+ FROM_HERE, suspend_timers_when_backgrounded_closure_.callback(), |
+ suspend_timers_when_backgrounded_delay); |
+} |
+ |
+void RendererSchedulerImpl::OnRendererForegrounded() { |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::OnRendererVisible"); |
+ helper_.CheckOnValidThread(); |
+ if (helper_.IsShutdown() || !MainThreadOnly().renderer_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().renderer_backgrounded_ = false; |
+ if (kSuspendTimersWhenBackgroundedDelayMillis < 0) |
+ return; |
+ |
+ suspend_timers_when_backgrounded_closure_.Cancel(); |
+ ResumeTimerQueueWhenForegrounded(); |
+} |
+ |
void RendererSchedulerImpl::EndIdlePeriod() { |
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
"RendererSchedulerImpl::EndIdlePeriod"); |
@@ -238,6 +279,28 @@ void RendererSchedulerImpl::EndIdlePeriod() { |
idle_helper_.EndIdlePeriod(); |
} |
+void RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded() { |
+ DCHECK(MainThreadOnly().renderer_backgrounded_); |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded"); |
+ if (MainThreadOnly().timer_queue_suspended_for_backgrounded_renderer_) |
+ return; |
+ |
+ MainThreadOnly().timer_queue_suspended_for_backgrounded_renderer_ = true; |
+ SuspendTimerQueue(); |
+} |
+ |
+void RendererSchedulerImpl::ResumeTimerQueueWhenForegrounded() { |
+ DCHECK(!MainThreadOnly().renderer_backgrounded_); |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::ResumeTimerQueueWhenForegrounded"); |
+ if (!MainThreadOnly().timer_queue_suspended_for_backgrounded_renderer_) |
+ return; |
+ |
+ MainThreadOnly().timer_queue_suspended_for_backgrounded_renderer_ = false; |
+ ResumeTimerQueue(); |
+} |
+ |
// static |
bool RendererSchedulerImpl::ShouldPrioritizeInputEvent( |
const blink::WebInputEvent& web_input_event) { |
@@ -649,6 +712,11 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
IdleHelper::IdlePeriodStateToString( |
idle_helper_.SchedulerIdlePeriodState())); |
state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); |
+ state->SetBoolean("renderer_backgrounded", |
+ MainThreadOnly().renderer_backgrounded_); |
+ state->SetBoolean( |
+ "timer_queue_suspended_for_backgrounded_renderer_", |
+ MainThreadOnly().timer_queue_suspended_for_backgrounded_renderer_); |
state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
state->SetDouble("last_input_signal_time", |
(AnyThread().last_input_signal_time_ - base::TimeTicks()) |