Bug 1382254 - Only disallow budget throttling. r=ehsan

Don't consider WebSockets, IndexedDB, etc when considering background
tabs for ordinary throttling since that makes us throttle way less
than we used to.
This commit is contained in:
Andreas Farre 2017-07-20 17:06:20 +02:00
Родитель 8aab64fd68
Коммит 4a297f87de
2 изменённых файлов: 65 добавлений и 45 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/ThrottledEventQueue.h"
#include "mozilla/TimeStamp.h"
#include "nsIDocShell.h"
#include "nsITimeoutHandler.h"
#include "mozilla/dom/TabGroup.h"
#include "OrderedTimeoutIterator.h"
@ -107,10 +108,6 @@ TimeoutManager::IsActive() const
// A window is considered active if:
// * It is a chrome window
// * It is playing audio
// * If it is using user media
// * If it is using WebRTC
// * If it has open WebSockets
// * If it has active IndexedDB databases
//
// Note that a window can be considered active if it is either in the
// foreground or in the background.
@ -124,45 +121,6 @@ TimeoutManager::IsActive() const
return true;
}
// Check if there are any active IndexedDB databases
if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
return true;
}
// Check if we have active GetUserMedia
if (MediaManager::Exists() &&
MediaManager::Get()->IsWindowStillActive(mWindow.WindowID())) {
return true;
}
bool active = false;
#if 0
// Check if we have active PeerConnections This doesn't actually
// work, since we sometimes call IsActive from Resume, which in turn
// is sometimes called from nsGlobalWindow::LeaveModalState. The
// problem here is that LeaveModalState can be called with pending
// exeptions on the js context, and the following call to
// HasActivePeerConnection is a JS call, which will assert on that
// exception. Also, calling JS is expensive so we should try to fix
// this in some other way.
nsCOMPtr<IPeerConnectionManager> pcManager =
do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID);
if (pcManager && NS_SUCCEEDED(pcManager->HasActivePeerConnection(
mWindow.WindowID(), &active)) &&
active) {
return true;
}
#endif // MOZ_WEBRTC
// Check if we have web sockets
RefPtr<WebSocketEventService> eventService = WebSocketEventService::Get();
if (eventService &&
NS_SUCCEEDED(eventService->HasListenerFor(mWindow.WindowID(), &active)) &&
active) {
return true;
}
return false;
}
@ -246,7 +204,7 @@ TimeoutManager::MinSchedulingDelay() const
TimeDuration unthrottled =
isBackground ? TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)
: TimeDuration();
if (mBudgetThrottleTimeouts && mExecutionBudget < TimeDuration()) {
if (BudgetThrottlingEnabled() && mExecutionBudget < TimeDuration()) {
// Only throttle if execution budget is less than 0
double factor = 1.0 / GetRegenerationFactor(mWindow.IsBackgroundInternal());
return TimeDuration::Min(
@ -373,7 +331,7 @@ TimeoutManager::UpdateBudget(const TimeStamp& aNow, const TimeDuration& aDuratio
// window is active or not. If throttling is enabled and the window
// is active and then becomes inactive, an overdrawn budget will
// still be counted against the minimum delay.
if (mBudgetThrottleTimeouts) {
if (BudgetThrottlingEnabled()) {
bool isBackground = mWindow.IsBackgroundInternal();
double factor = GetRegenerationFactor(isBackground);
TimeDuration regenerated = (aNow - mLastBudgetUpdate).MultDouble(factor);
@ -1241,6 +1199,66 @@ ThrottleTimeoutsCallback::Notify(nsITimer* aTimer)
}
bool
TimeoutManager::BudgetThrottlingEnabled() const
{
// A window can be throttled using budget if
// * It isn't active
// * If it isn't using user media
// * If it isn't using WebRTC
// * If it hasn't got open WebSockets
// * If it hasn't got active IndexedDB databases
//
// Note that we allow both foreground and background to be
// considered for budget throttling. What determines if they are if
// budget throttling is enabled is the regeneration factor.
if (!mBudgetThrottleTimeouts || IsActive()) {
return false;
}
// Check if there are any active IndexedDB databases
if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
return false;
}
// Check if we have active GetUserMedia
if (MediaManager::Exists() &&
MediaManager::Get()->IsWindowStillActive(mWindow.WindowID())) {
return false;
}
bool active = false;
#if 0
// Check if we have active PeerConnections This doesn't actually
// work, since we sometimes call IsActive from Resume, which in turn
// is sometimes called from nsGlobalWindow::LeaveModalState. The
// problem here is that LeaveModalState can be called with pending
// exeptions on the js context, and the following call to
// HasActivePeerConnection is a JS call, which will assert on that
// exception. Also, calling JS is expensive so we should try to fix
// this in some other way.
nsCOMPtr<IPeerConnectionManager> pcManager =
do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID);
if (pcManager && NS_SUCCEEDED(pcManager->HasActivePeerConnection(
mWindow.WindowID(), &active)) &&
active) {
return false;
}
#endif // MOZ_WEBRTC
// Check if we have web sockets
RefPtr<WebSocketEventService> eventService = WebSocketEventService::Get();
if (eventService &&
NS_SUCCEEDED(eventService->HasListenerFor(mWindow.WindowID(), &active)) &&
active) {
return false;
}
return true;
}
void
TimeoutManager::StartThrottlingTimeouts()
{

Просмотреть файл

@ -148,6 +148,8 @@ private:
void UpdateBudget(const TimeStamp& aNow,
const TimeDuration& aDuration = TimeDuration());
bool BudgetThrottlingEnabled() const;
private:
struct Timeouts {
explicit Timeouts(const TimeoutManager& aManager)