Bug 1897400 - prepare TimeoutManager for reuse in workers via nsIGlobalObject, r=smaug

- methods IsBackgroundInternal(), IsRunningTimeout(), TimeoutManager() were moved to nsIGlobalObject

Differential Revision: https://phabricator.services.mozilla.com/D211008
This commit is contained in:
aiunusov 2024-06-24 10:29:16 +00:00
parent 878964c6d3
commit f31528cc43
11 changed files with 166 additions and 90 deletions

View File

@ -208,9 +208,11 @@ static void SetTimeoutForGlobal(GlobalObject& aGlobal, TimeoutHandler& aHandler,
}
int32_t handle;
nsresult rv = innerWindow->TimeoutManager().SetTimeout(
&aHandler, timeout, /* aIsInterval */ false,
Timeout::Reason::eAbortSignalTimeout, &handle);
nsresult rv =
nsGlobalWindowInner::Cast(innerWindow)
->GetTimeoutManager()
->SetTimeout(&aHandler, timeout, /* aIsInterval */ false,
Timeout::Reason::eAbortSignalTimeout, &handle);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;

View File

@ -16719,15 +16719,17 @@ nsAutoSyncOperation::nsAutoSyncOperation(Document* aDoc,
}
void nsAutoSyncOperation::SuppressDocument(Document* aDoc) {
if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
win->TimeoutManager().BeginSyncOperation();
if (RefPtr<nsGlobalWindowInner> win =
nsGlobalWindowInner::Cast(aDoc->GetInnerWindow())) {
win->GetTimeoutManager()->BeginSyncOperation();
}
aDoc->SetIsInSyncOperation(true);
}
void nsAutoSyncOperation::UnsuppressDocument(Document* aDoc) {
if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
win->TimeoutManager().EndSyncOperation();
if (RefPtr<nsGlobalWindowInner> win =
nsGlobalWindowInner::Cast(aDoc->GetInnerWindow())) {
win->GetTimeoutManager()->EndSyncOperation();
}
aDoc->SetIsInSyncOperation(false);
}

View File

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TimeoutManager.h"
#include "nsGlobalWindowInner.h"
#include "nsIGlobalObject.h"
#include "mozilla/Logging.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/ScopeExit.h"
@ -86,7 +86,12 @@ TimeDuration GetMinBudget(bool aIsBackground) {
//
bool TimeoutManager::IsBackground() const {
return !IsActive() && mWindow.IsBackgroundInternal();
nsGlobalWindowInner* window = GetInnerWindow();
if (!window) {
// TODO(aiunusov): consider workers case here
return !IsActive();
}
return !IsActive() && window->IsBackgroundInternal();
}
bool TimeoutManager::IsActive() const {
@ -97,12 +102,18 @@ bool TimeoutManager::IsActive() const {
// Note that a window can be considered active if it is either in the
// foreground or in the background.
if (mWindow.IsChromeWindow()) {
nsGlobalWindowInner* window = GetInnerWindow();
if (!window) {
return true;
}
if (window->IsChromeWindow()) {
return true;
}
// Check if we're playing audio
if (mWindow.IsPlayingAudio()) {
if (window->IsPlayingAudio()) {
return true;
}
@ -144,19 +155,24 @@ void TimeoutManager::MoveIdleToActive() {
TimeDuration elapsed = now - timeout->SubmitTime();
TimeDuration target = timeout->When() - timeout->SubmitTime();
TimeDuration delta = now - timeout->When();
nsPrintfCString marker(
"Releasing deferred setTimeout() for %dms (original target time was "
"%dms (%dms delta))",
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
int(delta.ToMilliseconds()));
// don't have end before start...
PROFILER_MARKER_TEXT(
"setTimeout deferred release", DOM,
MarkerOptions(
MarkerTiming::Interval(
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
MarkerInnerWindowId(mWindow.WindowID())),
marker);
if (mGlobalObject.GetAsInnerWindow()) {
nsPrintfCString marker(
"Releasing deferred setTimeout() for %dms (original target time "
"was "
"%dms (%dms delta))",
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
int(delta.ToMilliseconds()));
// don't have end before start...
PROFILER_MARKER_TEXT(
"setTimeout deferred release", DOM,
MarkerOptions(
MarkerTiming::Interval(
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
MarkerInnerWindowId(
mGlobalObject.GetAsInnerWindow()->WindowID())),
marker);
}
// TODO: add separate marker for Workers case
}
num++;
}
@ -195,7 +211,8 @@ TimeDuration TimeoutManager::MinSchedulingDelay() const {
return TimeDuration();
}
bool isBackground = mWindow.IsBackgroundInternal();
nsGlobalWindowInner* window = GetInnerWindow();
bool isBackground = window && window->IsBackgroundInternal();
// If a window isn't active as defined by TimeoutManager::IsActive()
// and we're throttling timeouts using an execution budget, we
@ -244,7 +261,11 @@ TimeDuration TimeoutManager::MinSchedulingDelay() const {
bool budgetThrottlingEnabled = BudgetThrottlingEnabled(isBackground);
if (budgetThrottlingEnabled && mExecutionBudget < TimeDuration()) {
// Only throttle if execution budget is less than 0
double factor = 1.0 / GetRegenerationFactor(mWindow.IsBackgroundInternal());
// TODO(aiunusov): change the logic accordingly for the workers,
// once we have the "is in background" in workers
double factor =
1.0 / GetRegenerationFactor(window && window->IsBackgroundInternal());
return TimeDuration::Max(unthrottled, -mExecutionBudget.MultDouble(factor));
}
if (!budgetThrottlingEnabled && isBackground) {
@ -340,7 +361,12 @@ void TimeoutManager::RecordExecution(Timeout* aRunningTimeout,
void TimeoutManager::UpdateBudget(const TimeStamp& aNow,
const TimeDuration& aDuration) {
if (mWindow.IsChromeWindow()) {
nsGlobalWindowInner* window = GetInnerWindow();
if (!window) {
return;
}
if (window->IsChromeWindow()) {
return;
}
@ -351,7 +377,7 @@ void TimeoutManager::UpdateBudget(const TimeStamp& aNow,
// 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.
bool isBackground = mWindow.IsBackgroundInternal();
bool isBackground = window->IsBackgroundInternal();
if (BudgetThrottlingEnabled(isBackground)) {
double factor = GetRegenerationFactor(isBackground);
TimeDuration regenerated = (aNow - mLastBudgetUpdate).MultDouble(factor);
@ -381,9 +407,9 @@ void TimeoutManager::UpdateBudget(const TimeStamp& aNow,
uint32_t TimeoutManager::sNestingLevel = 0;
TimeoutManager::TimeoutManager(nsGlobalWindowInner& aWindow,
TimeoutManager::TimeoutManager(nsIGlobalObject& aHandle,
uint32_t aMaxIdleDeferMS)
: mWindow(aWindow),
: mGlobalObject(aHandle),
mExecutor(new TimeoutExecutor(this, false, 0)),
mIdleExecutor(new TimeoutExecutor(this, true, aMaxIdleDeferMS)),
mTimeouts(*this),
@ -397,7 +423,8 @@ TimeoutManager::TimeoutManager(nsGlobalWindowInner& aWindow,
mIdleTimeouts(*this),
mIdleCallbackTimeoutCounter(1),
mLastBudgetUpdate(TimeStamp::Now()),
mExecutionBudget(GetMaxBudget(mWindow.IsBackgroundInternal())),
mExecutionBudget(GetMaxBudget(GetInnerWindow() &&
GetInnerWindow()->IsBackgroundInternal())),
mThrottleTimeouts(false),
mThrottleTrackingTimeouts(false),
mBudgetThrottleTimeouts(false),
@ -410,7 +437,7 @@ TimeoutManager::TimeoutManager(nsGlobalWindowInner& aWindow,
}
TimeoutManager::~TimeoutManager() {
MOZ_DIAGNOSTIC_ASSERT(mWindow.IsDying());
MOZ_DIAGNOSTIC_ASSERT(mGlobalObject.IsDying());
MOZ_DIAGNOSTIC_ASSERT(!mThrottleTimeoutsTimer);
mExecutor->Shutdown();
@ -439,11 +466,15 @@ nsresult TimeoutManager::SetTimeout(TimeoutHandler* aHandler, int32_t interval,
int32_t* aReturn) {
// If we don't have a document (we could have been unloaded since
// the call to setTimeout was made), do nothing.
nsCOMPtr<Document> doc = mWindow.GetExtantDoc();
if (!doc || mWindow.IsDying()) {
return NS_OK;
if (mGlobalObject.GetAsInnerWindow()) {
nsCOMPtr<Document> doc = mGlobalObject.GetAsInnerWindow()->GetExtantDoc();
if (!doc || mGlobalObject.IsDying()) {
return NS_OK;
}
}
nsGlobalWindowInner* window = GetInnerWindow();
// Disallow negative intervals.
interval = std::max(0, interval);
@ -459,7 +490,7 @@ nsresult TimeoutManager::SetTimeout(TimeoutHandler* aHandler, int32_t interval,
#ifdef DEBUG
timeout->mFiringIndex = -1;
#endif
timeout->mWindow = &mWindow;
timeout->mWindow = window;
timeout->mIsInterval = aIsInterval;
timeout->mInterval = TimeDuration::FromMilliseconds(interval);
timeout->mScriptHandler = aHandler;
@ -483,7 +514,7 @@ nsresult TimeoutManager::SetTimeout(TimeoutHandler* aHandler, int32_t interval,
timeout->SetWhenOrTimeRemaining(now, realInterval);
// If we're not suspended, then set the timer.
if (!mWindow.IsSuspended()) {
if (window && !window->IsSuspended()) {
nsresult rv = MaybeSchedule(timeout->When(), now);
if (NS_FAILED(rv)) {
return rv;
@ -505,8 +536,9 @@ nsresult TimeoutManager::SetTimeout(TimeoutHandler* aHandler, int32_t interval,
}
}
Timeouts::SortBy sort(mWindow.IsFrozen() ? Timeouts::SortBy::TimeRemaining
: Timeouts::SortBy::TimeWhen);
Timeouts::SortBy sort(window && window->IsFrozen()
? Timeouts::SortBy::TimeRemaining
: Timeouts::SortBy::TimeWhen);
timeout->mTimeoutId = GetTimeoutId(aReason);
mTimeouts.Insert(timeout, sort);
@ -522,7 +554,7 @@ nsresult TimeoutManager::SetTimeout(TimeoutHandler* aHandler, int32_t interval,
(CalculateDelay(timeout) - timeout->mInterval).ToMilliseconds(),
mThrottleTimeouts ? "yes" : (mThrottleTimeoutsTimer ? "pending" : "no"),
IsActive() ? "active" : "inactive",
mWindow.IsBackgroundInternal() ? "background" : "foreground",
window && window->IsBackgroundInternal() ? "background" : "foreground",
realInterval.ToMilliseconds(), timeout->mTimeoutId,
int(mExecutionBudget.ToMilliseconds())));
@ -556,6 +588,8 @@ bool TimeoutManager::ClearTimeoutInternal(int32_t aTimerId,
}
bool firstTimeout = timeout == timeouts.GetFirst();
nsGlobalWindowInner* window = GetInnerWindow();
MOZ_LOG(gTimeoutLog, LogLevel::Debug,
("%s(TimeoutManager=%p, timeout=%p, ID=%u)\n",
timeout->mReason == Timeout::Reason::eIdleCallbackTimeout
@ -583,7 +617,7 @@ bool TimeoutManager::ClearTimeoutInternal(int32_t aTimerId,
// RunTimeout() will handle rescheduling the executor.
// * If the window has become suspended then we should not start executing
// Timeouts.
if (!firstTimeout || deferredDeletion || mWindow.IsSuspended()) {
if (!firstTimeout || deferredDeletion || (window && window->IsSuspended())) {
return true;
}
@ -608,8 +642,19 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
MOZ_DIAGNOSTIC_ASSERT(!aNow.IsNull());
MOZ_DIAGNOSTIC_ASSERT(!aTargetDeadline.IsNull());
MOZ_ASSERT_IF(mWindow.IsFrozen(), mWindow.IsSuspended());
if (mWindow.IsSuspended()) {
// Make sure that the window and the script context don't go away as
// a result of running timeouts
RefPtr<nsGlobalWindowInner> window = GetInnerWindow();
if (!window) {
// we have a workers case here
// TODO(aiunusov): change the code accordigly to cover workers usecase
return;
}
MOZ_ASSERT_IF(window->IsFrozen(), window->IsSuspended());
if (window->IsSuspended()) {
return;
}
@ -639,10 +684,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
uint32_t firingId = CreateFiringId();
auto guard = MakeScopeExit([&] { DestroyFiringId(firingId); });
// Make sure that the window and the script context don't go away as
// a result of running timeouts
RefPtr<nsGlobalWindowInner> window(&mWindow);
// Accessing members of mWindow here is safe, because the lifetime of
// Accessing members of mGlobalObject here is safe, because the lifetime of
// TimeoutManager is the same as the lifetime of the containing
// nsGlobalWindow.
@ -716,7 +758,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
// Note, we verified the window is not suspended at the top of
// 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_DIAGNOSTIC_ASSERT(!window->IsSuspended());
if (aProcessIdle) {
// We don't want to update timing budget for idle queue firings, and
// all timeouts in the IdleTimeouts list have hit their deadlines,
@ -803,8 +845,8 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
}
}
MOZ_ASSERT_IF(mWindow.IsFrozen(), mWindow.IsSuspended());
if (mWindow.IsSuspended()) {
MOZ_ASSERT_IF(window->IsFrozen(), window->IsSuspended());
if (window->IsSuspended()) {
break;
}
@ -851,7 +893,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
// Get the script context (a strong ref to prevent it going away)
// for this timeout and ensure the script language is enabled.
nsCOMPtr<nsIScriptContext> scx = mWindow.GetContextInternal();
nsCOMPtr<nsIScriptContext> scx = window->GetContextInternal();
if (!scx) {
// No context means this window was closed or never properly
@ -876,7 +918,10 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
mLastFiringIndex = timeout->mFiringIndex;
#endif
// This timeout is good to run.
bool timeout_was_cleared = window->RunTimeoutHandler(timeout, scx);
bool timeout_was_cleared = false;
if (window) {
timeout_was_cleared = window->RunTimeoutHandler(timeout, scx);
}
MOZ_LOG(gTimeoutLog, LogLevel::Debug,
("Run%s(TimeoutManager=%p, timeout=%p) returned %d\n",
timeout->mIsInterval ? "Interval" : "Timeout", this,
@ -914,7 +959,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
// Insert interval timeout onto the corresponding list sorted in
// deadline order. AddRefs timeout.
// Always re-insert into the normal time queue!
mTimeouts.Insert(timeout, mWindow.IsFrozen()
mTimeouts.Insert(timeout, window->IsFrozen()
? Timeouts::SortBy::TimeRemaining
: Timeouts::SortBy::TimeWhen);
}
@ -927,7 +972,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
// run immediately for the next timer, if it exists. Its possible,
// however, that the last timeout handler suspended the window. If
// that happened then we must skip this step.
if (!mWindow.IsSuspended()) {
if (!window->IsSuspended()) {
if (next) {
if (aProcessIdle) {
// We don't want to update timing budget for idle queue firings,
@ -990,8 +1035,9 @@ bool TimeoutManager::RescheduleTimeout(Timeout* aTimeout,
}
aTimeout->SetWhenOrTimeRemaining(aCurrentNow, delay);
nsGlobalWindowInner* window = GetInnerWindow();
if (mWindow.IsSuspended()) {
if (window && window->IsSuspended()) {
return true;
}
@ -1103,11 +1149,12 @@ void TimeoutManager::Suspend() {
void TimeoutManager::Resume() {
MOZ_LOG(gTimeoutLog, LogLevel::Debug, ("Resume(TimeoutManager=%p)\n", this));
nsGlobalWindowInner* window = GetInnerWindow();
// When Suspend() has been called after IsDocumentLoaded(), but the
// throttle tracking timer never managed to fire, start the timer
// again.
if (mWindow.IsDocumentLoaded() && !mThrottleTimeouts) {
if (window && window->IsDocumentLoaded() && !mThrottleTimeouts) {
MaybeStartThrottleTimeout();
}
@ -1167,13 +1214,14 @@ void TimeoutManager::Thaw() {
}
void TimeoutManager::UpdateBackgroundState() {
mExecutionBudget = GetMaxBudget(mWindow.IsBackgroundInternal());
nsGlobalWindowInner* window = GetInnerWindow();
mExecutionBudget = GetMaxBudget(window && window->IsBackgroundInternal());
// 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()) {
if (window && !window->IsSuspended()) {
Timeout* nextTimeout = mTimeouts.GetFirst();
if (nextTimeout) {
mExecutor->Cancel();
@ -1198,8 +1246,8 @@ namespace {
class ThrottleTimeoutsCallback final : public nsITimerCallback,
public nsINamed {
public:
explicit ThrottleTimeoutsCallback(nsGlobalWindowInner* aWindow)
: mWindow(aWindow) {}
explicit ThrottleTimeoutsCallback(nsIGlobalObject* aHandle)
: mGlobalObject(aHandle) {}
NS_DECL_ISUPPORTS
NS_DECL_NSITIMERCALLBACK
@ -1215,15 +1263,19 @@ class ThrottleTimeoutsCallback final : public nsITimerCallback,
private:
// The strong reference here keeps the Window and hence the TimeoutManager
// object itself alive.
RefPtr<nsGlobalWindowInner> mWindow;
RefPtr<nsIGlobalObject> mGlobalObject;
};
NS_IMPL_ISUPPORTS(ThrottleTimeoutsCallback, nsITimerCallback, nsINamed)
NS_IMETHODIMP
ThrottleTimeoutsCallback::Notify(nsITimer* aTimer) {
mWindow->TimeoutManager().StartThrottlingTimeouts();
mWindow = nullptr;
if (nsGlobalWindowInner::Cast(mGlobalObject->GetAsInnerWindow())) {
nsGlobalWindowInner::Cast(mGlobalObject->GetAsInnerWindow())
->GetTimeoutManager()
->StartThrottlingTimeouts();
}
mGlobalObject = nullptr;
return NS_OK;
}
@ -1249,17 +1301,19 @@ bool TimeoutManager::BudgetThrottlingEnabled(bool aIsBackground) const {
return false;
}
nsGlobalWindowInner* window = GetInnerWindow();
// Check if there are any active IndexedDB databases
if (mWindow.HasActiveIndexedDBDatabases()) {
if (window && window->HasActiveIndexedDBDatabases()) {
return false;
}
// Check if we have active PeerConnection
if (mWindow.HasActivePeerConnections()) {
if (window && window->HasActivePeerConnections()) {
return false;
}
if (mWindow.HasOpenWebSockets()) {
if (window && window->HasOpenWebSockets()) {
return false;
}
@ -1291,8 +1345,9 @@ void TimeoutManager::OnDocumentLoaded() {
}
void TimeoutManager::MaybeStartThrottleTimeout() {
if (StaticPrefs::dom_timeout_throttling_delay() <= 0 || mWindow.IsDying() ||
mWindow.IsSuspended()) {
nsGlobalWindowInner* win = GetInnerWindow();
if (StaticPrefs::dom_timeout_throttling_delay() <= 0 || !win ||
win->IsDying() || win->IsSuspended()) {
return;
}
@ -1302,7 +1357,8 @@ void TimeoutManager::MaybeStartThrottleTimeout() {
("TimeoutManager %p delaying tracking timeout throttling by %dms\n",
this, StaticPrefs::dom_timeout_throttling_delay()));
nsCOMPtr<nsITimerCallback> callback = new ThrottleTimeoutsCallback(&mWindow);
nsCOMPtr<nsITimerCallback> callback =
new ThrottleTimeoutsCallback(&mGlobalObject);
NS_NewTimerWithCallback(getter_AddRefs(mThrottleTimeoutsTimer), callback,
StaticPrefs::dom_timeout_throttling_delay(),
@ -1325,5 +1381,9 @@ void TimeoutManager::EndSyncOperation() {
}
nsIEventTarget* TimeoutManager::EventTarget() {
return mWindow.GetBrowsingContextGroup()->GetTimerEventQueue();
nsGlobalWindowInner* window = GetInnerWindow();
if (window) {
return window->GetBrowsingContextGroup()->GetTimerEventQueue();
}
return nullptr;
}

View File

@ -12,7 +12,7 @@
class nsIEventTarget;
class nsITimer;
class nsGlobalWindowInner;
class nsIGlobalObject;
namespace mozilla {
@ -27,7 +27,7 @@ class TimeoutManager final {
struct Timeouts;
public:
TimeoutManager(nsGlobalWindowInner& aWindow, uint32_t aMaxIdleDeferMS);
TimeoutManager(nsIGlobalObject& aHandle, uint32_t aMaxIdleDeferMS);
~TimeoutManager();
TimeoutManager(const TimeoutManager& rhs) = delete;
void operator=(const TimeoutManager& rhs) = delete;
@ -104,6 +104,13 @@ class TimeoutManager final {
private:
void MaybeStartThrottleTimeout();
// get nsGlobalWindowInner
// if the method returns nullptr, then we have a worker,
// which should be handled differently according to TimeoutManager logic
nsGlobalWindowInner* GetInnerWindow() const {
return nsGlobalWindowInner::Cast(mGlobalObject.GetAsInnerWindow());
}
// Return true if |aTimeout| needs to be reinserted into the timeout list.
bool RescheduleTimeout(mozilla::dom::Timeout* aTimeout,
const TimeStamp& aLastCallbackTime,
@ -204,9 +211,9 @@ class TimeoutManager final {
RefPtr<Timeout::TimeoutSet> mTimeouts;
};
// Each nsGlobalWindowInner object has a TimeoutManager member. This
// Each nsIGlobalObject object has a TimeoutManager member. This
// reference points to that holder object.
nsGlobalWindowInner& mWindow;
nsIGlobalObject& mGlobalObject;
// The executor is specific to the nsGlobalWindow/TimeoutManager, but it
// can live past the destruction of the window if its scheduled. Therefore
// it must be a separate ref-counted object.

View File

@ -191,7 +191,7 @@ void MarkDocumentViewer(nsIDocumentViewer* aViewer, bool aCleanupJS) {
if (elm) {
elm->MarkForCC();
}
win->TimeoutManager().UnmarkGrayTimers();
win->GetTimeoutManager()->UnmarkGrayTimers();
}
}
}

View File

@ -606,7 +606,7 @@ nsresult IdleRequestExecutor::Cancel() {
MOZ_ASSERT(NS_IsMainThread());
if (mDelayedExecutorHandle && mWindow) {
mWindow->TimeoutManager().ClearTimeout(
mWindow->GetTimeoutManager()->ClearTimeout(
mDelayedExecutorHandle.value(), Timeout::Reason::eIdleCallbackTimeout);
}
@ -671,7 +671,7 @@ void IdleRequestExecutor::DelayedDispatch(uint32_t aDelay) {
MOZ_ASSERT(mWindow);
MOZ_ASSERT(mDelayedExecutorHandle.isNothing());
int32_t handle;
mWindow->TimeoutManager().SetTimeout(
mWindow->GetTimeoutManager()->SetTimeout(
mDelayedExecutorDispatcher, aDelay, false,
Timeout::Reason::eIdleCallbackTimeout, &handle);
mDelayedExecutorHandle = Some(handle);
@ -2773,12 +2773,12 @@ bool nsPIDOMWindowInner::IsPlayingAudio() {
bool nsPIDOMWindowInner::IsDocumentLoaded() const { return mIsDocumentLoaded; }
mozilla::dom::TimeoutManager& nsPIDOMWindowInner::TimeoutManager() {
return *mTimeoutManager;
mozilla::dom::TimeoutManager* nsGlobalWindowInner::GetTimeoutManager() {
return mTimeoutManager.get();
}
bool nsPIDOMWindowInner::IsRunningTimeout() {
return TimeoutManager().IsRunningTimeout();
bool nsGlobalWindowInner::IsRunningTimeout() {
return GetTimeoutManager()->IsRunningTimeout();
}
void nsPIDOMWindowInner::TryToCacheTopInnerWindow() {

View File

@ -272,6 +272,10 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
virtual nsIPrincipal* PartitionedPrincipal() override;
mozilla::dom::TimeoutManager* GetTimeoutManager() override;
bool IsRunningTimeout() override;
// nsIDOMWindow
NS_DECL_NSIDOMWINDOW
@ -1168,7 +1172,7 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
friend class nsPIDOMWindowInner;
friend class nsPIDOMWindowOuter;
bool IsBackgroundInternal() const;
bool IsBackgroundInternal() const override;
// NOTE: Chrome Only
void DisconnectAndClearGroupMessageManagers() {

View File

@ -283,6 +283,9 @@ class nsIGlobalObject : public nsISupports {
* is not a suspendable worker.
*/
virtual bool IsEligibleForMessaging() { return false; };
virtual bool IsBackgroundInternal() const { return false; }
virtual mozilla::dom::TimeoutManager* GetTimeoutManager() { return nullptr; }
virtual bool IsRunningTimeout() { return false; }
protected:
virtual ~nsIGlobalObject();

View File

@ -354,10 +354,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
bool IsDocumentLoaded() const;
mozilla::dom::TimeoutManager& TimeoutManager();
bool IsRunningTimeout();
// To cache top inner-window if available after constructed for tab-wised
// indexedDB counters.
void TryToCacheTopInnerWindow();

View File

@ -38,9 +38,10 @@ nsresult WebTaskSchedulerMainThread::SetTimeoutForDelayedTask(WebTask* aTask,
int32_t delay = aDelay > INT32_MAX ? INT32_MAX : (int32_t)aDelay;
int32_t handle;
return global->GetAsInnerWindow()->TimeoutManager().SetTimeout(
handler, delay, /* aIsInterval */ false,
Timeout::Reason::eDelayedWebTaskTimeout, &handle);
return nsGlobalWindowInner::Cast(global->GetAsInnerWindow())
->GetTimeoutManager()
->SetTimeout(handler, delay, /* aIsInterval */ false,
Timeout::Reason::eDelayedWebTaskTimeout, &handle);
}
bool WebTaskSchedulerMainThread::DispatchEventLoopRunnable() {

View File

@ -297,7 +297,8 @@ static bool IsPresContextInScriptAnimationCallback(
}
// Treat timeouts/setintervals as scripted animation callbacks for our
// purposes.
nsPIDOMWindowInner* win = aPresContext->Document()->GetInnerWindow();
nsGlobalWindowInner* win =
nsGlobalWindowInner::Cast(aPresContext->Document()->GetInnerWindow());
return win && win->IsRunningTimeout();
}