diff --git a/dom/base/TimeoutExecutor.h b/dom/base/TimeoutExecutor.h index 06f775b8e968..e8ec2967a5ba 100644 --- a/dom/base/TimeoutExecutor.h +++ b/dom/base/TimeoutExecutor.h @@ -75,8 +75,7 @@ public: Shutdown(); nsresult - MaybeSchedule(const TimeStamp& aDeadline, - const TimeDuration& aMinDelay = TimeDuration()); + MaybeSchedule(const TimeStamp& aDeadline, const TimeDuration& aMinDelay); void Cancel(); diff --git a/dom/base/TimeoutManager.cpp b/dom/base/TimeoutManager.cpp index e7b18e75fa01..76459c2a1989 100644 --- a/dom/base/TimeoutManager.cpp +++ b/dom/base/TimeoutManager.cpp @@ -177,6 +177,15 @@ TimeoutManager::IsValidFiringId(uint32_t aFiringId) const return !IsInvalidFiringId(aFiringId); } +TimeDuration +TimeoutManager::MinSchedulingDelay() const +{ + if (IsBackground()) { + return TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue); + } + return TimeDuration(); +} + bool TimeoutManager::IsInvalidFiringId(uint32_t aFiringId) const { @@ -424,7 +433,8 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler, // If we're not suspended, then set the timer. if (!mWindow.IsSuspended()) { - nsresult rv = mExecutor->MaybeSchedule(timeout->When()); + nsresult rv = mExecutor->MaybeSchedule(timeout->When(), + MinSchedulingDelay()); if (NS_FAILED(rv)) { return rv; } @@ -535,7 +545,8 @@ TimeoutManager::ClearTimeout(int32_t aTimerId, Timeout::Reason aReason) OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts); Timeout* nextTimeout = iter.Next(); if (nextTimeout) { - MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When())); + MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When(), + MinSchedulingDelay())); } } @@ -653,7 +664,8 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli // method and the window should not have been suspended while // executing the loop above since it doesn't call out to js. MOZ_DIAGNOSTIC_ASSERT(!mWindow.IsSuspended()); - MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextDeadline)); + MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextDeadline, + MinSchedulingDelay())); } // Maybe the timeout that the event was fired for has been deleted @@ -777,7 +789,8 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli if (!mWindow.IsSuspended()) { RefPtr timeout = runIter.Next(); if (timeout) { - MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(timeout->When())); + MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(timeout->When(), + MinSchedulingDelay())); } } break; @@ -818,7 +831,8 @@ TimeoutManager::RescheduleTimeout(Timeout* aTimeout, const TimeStamp& now) return true; } - nsresult rv = mExecutor->MaybeSchedule(aTimeout->When()); + nsresult rv = mExecutor->MaybeSchedule(aTimeout->When(), + MinSchedulingDelay()); NS_ENSURE_SUCCESS(rv, false); return true; @@ -852,7 +866,7 @@ TimeoutManager::ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts); Timeout* firstTimeout = iter.Next(); if (firstTimeout) { - rv = mExecutor->MaybeSchedule(firstTimeout->When()); + rv = mExecutor->MaybeSchedule(firstTimeout->When(), MinSchedulingDelay()); NS_ENSURE_SUCCESS(rv, rv); } @@ -1112,7 +1126,8 @@ TimeoutManager::Resume() }); if (!nextWakeUp.IsNull()) { - MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextWakeUp)); + MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextWakeUp, + MinSchedulingDelay())); } } @@ -1158,6 +1173,20 @@ TimeoutManager::UpdateBackgroundState() if (!IsBackground()) { ResetTimersForThrottleReduction(); } + + // When the window moves to the background or foreground we should + // reschedule the TimeoutExecutor in case the MinSchedulingDelay() + // changed. Only do this if the window is not suspended and we + // actually have a timeout. + if (!mWindow.IsSuspended()) { + OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts); + Timeout* nextTimeout = iter.Next(); + if (nextTimeout) { + mExecutor->Cancel(); + MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When(), + MinSchedulingDelay())); + } + } } bool diff --git a/dom/base/TimeoutManager.h b/dom/base/TimeoutManager.h index c7878b262f53..d0b8e8b2894f 100644 --- a/dom/base/TimeoutManager.h +++ b/dom/base/TimeoutManager.h @@ -137,6 +137,9 @@ private: bool IsInvalidFiringId(uint32_t aFiringId) const; + TimeDuration + MinSchedulingDelay() const; + private: struct Timeouts { explicit Timeouts(const TimeoutManager& aManager)