mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-19 05:37:30 +09:00
moebius#73: DOM - window.requestIdleCallback - improvements (basic)
https://github.com/MoonchildProductions/moebius/pull/73
This commit is contained in:
parent
ec18bcca97
commit
da2320b2ef
11 changed files with 558 additions and 200 deletions
|
|
@ -9,7 +9,6 @@
|
||||||
#include "mozilla/Function.h"
|
#include "mozilla/Function.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/dom/IdleDeadline.h"
|
#include "mozilla/dom/IdleDeadline.h"
|
||||||
#include "mozilla/dom/Performance.h"
|
|
||||||
#include "mozilla/dom/PerformanceTiming.h"
|
#include "mozilla/dom/PerformanceTiming.h"
|
||||||
#include "mozilla/dom/WindowBinding.h"
|
#include "mozilla/dom/WindowBinding.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
|
|
@ -20,138 +19,56 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
IdleRequest::IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow,
|
IdleRequest::IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle)
|
||||||
IdleRequestCallback& aCallback, uint32_t aHandle)
|
: mCallback(aCallback)
|
||||||
: mWindow(aWindow)
|
|
||||||
, mCallback(&aCallback)
|
|
||||||
, mHandle(aHandle)
|
, mHandle(aHandle)
|
||||||
, mTimeoutHandle(Nothing())
|
, mTimeoutHandle(Nothing())
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aWindow);
|
MOZ_DIAGNOSTIC_ASSERT(mCallback);
|
||||||
|
|
||||||
// Get the calling location.
|
|
||||||
nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdleRequest::~IdleRequest()
|
IdleRequest::~IdleRequest()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequest)
|
NS_IMPL_CYCLE_COLLECTION(IdleRequest, mCallback)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequest)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequest)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequest)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequest)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequest)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequest)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequest)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequest)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
|
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimeoutHandler)
|
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
nsresult
|
|
||||||
IdleRequest::SetTimeout(uint32_t aTimeout)
|
|
||||||
{
|
|
||||||
int32_t handle;
|
|
||||||
nsresult rv = nsGlobalWindow::Cast(mWindow)->SetTimeoutOrInterval(
|
|
||||||
this, aTimeout, false, Timeout::Reason::eIdleCallbackTimeout, &handle);
|
|
||||||
mTimeoutHandle = Some(handle);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
IdleRequest::Run()
|
|
||||||
{
|
|
||||||
if (mCallback) {
|
|
||||||
RunIdleRequestCallback(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
IdleRequest::Cancel()
|
|
||||||
{
|
|
||||||
mCallback = nullptr;
|
|
||||||
CancelTimeout();
|
|
||||||
if (isInList()) {
|
|
||||||
remove();
|
|
||||||
}
|
|
||||||
Release();
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IdleRequest::SetDeadline(TimeStamp aDeadline)
|
IdleRequest::SetTimeoutHandle(int32_t aHandle)
|
||||||
{
|
{
|
||||||
mozilla::dom::Performance* perf = mWindow->GetPerformance();
|
mTimeoutHandle = Some(aHandle);
|
||||||
mDeadline =
|
}
|
||||||
perf ? perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline) : 0.0;
|
|
||||||
|
int32_t
|
||||||
|
IdleRequest::GetTimeoutHandle() const
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mTimeoutHandle.isSome());
|
||||||
|
return mTimeoutHandle.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IdleRequest::RunIdleRequestCallback(bool aDidTimeout)
|
IdleRequest::IdleRun(nsPIDOMWindowInner* aWindow,
|
||||||
|
DOMHighResTimeStamp aDeadline,
|
||||||
|
bool aDidTimeout)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mCallback);
|
||||||
|
|
||||||
if (!aDidTimeout) {
|
|
||||||
CancelTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
remove();
|
|
||||||
ErrorResult error;
|
ErrorResult error;
|
||||||
RefPtr<IdleDeadline> deadline =
|
RefPtr<IdleDeadline> deadline =
|
||||||
new IdleDeadline(mWindow, aDidTimeout, mDeadline);
|
new IdleDeadline(aWindow, aDidTimeout, aDeadline);
|
||||||
mCallback->Call(*deadline, error, "requestIdleCallback handler");
|
mCallback->Call(*deadline, error, "requestIdleCallback handler");
|
||||||
|
|
||||||
mCallback = nullptr;
|
mCallback = nullptr;
|
||||||
Release();
|
error.SuppressException();
|
||||||
|
|
||||||
return error.StealNSResult();
|
return error.StealNSResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
IdleRequest::CancelTimeout()
|
|
||||||
{
|
|
||||||
if (mTimeoutHandle.isSome()) {
|
|
||||||
nsGlobalWindow::Cast(mWindow)->ClearTimeoutOrInterval(
|
|
||||||
mTimeoutHandle.value(), Timeout::Reason::eIdleCallbackTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
IdleRequest::Call()
|
|
||||||
{
|
|
||||||
SetDeadline(TimeStamp::Now());
|
|
||||||
return RunIdleRequestCallback(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
IdleRequest::GetLocation(const char** aFileName, uint32_t* aLineNo,
|
|
||||||
uint32_t* aColumn)
|
|
||||||
{
|
|
||||||
*aFileName = mFileName.get();
|
|
||||||
*aLineNo = mLineNo;
|
|
||||||
*aColumn = mColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
IdleRequest::MarkForCC()
|
|
||||||
{
|
|
||||||
mCallback->MarkForCC();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsDOMNavigationTiming.h"
|
#include "nsDOMNavigationTiming.h"
|
||||||
#include "nsITimeoutHandler.h"
|
|
||||||
|
|
||||||
class nsPIDOMWindowInner;
|
class nsPIDOMWindowInner;
|
||||||
|
|
||||||
|
|
@ -21,28 +20,19 @@ namespace dom {
|
||||||
|
|
||||||
class IdleRequestCallback;
|
class IdleRequestCallback;
|
||||||
|
|
||||||
class IdleRequest final : public nsITimeoutHandler
|
class IdleRequest final : public nsISupports,
|
||||||
, public nsIRunnable
|
public LinkedListElement<IdleRequest>
|
||||||
, public nsICancelableRunnable
|
|
||||||
, public nsIIncrementalRunnable
|
|
||||||
, public LinkedListElement<IdleRequest>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IdleRequest(JSContext* aCx, nsPIDOMWindowInner* aWindow,
|
IdleRequest(IdleRequestCallback* aCallback, uint32_t aHandle);
|
||||||
IdleRequestCallback& aCallback, uint32_t aHandle);
|
|
||||||
|
|
||||||
virtual nsresult Call() override;
|
nsresult IdleRun(nsPIDOMWindowInner* aWindow,
|
||||||
virtual void GetLocation(const char** aFileName, uint32_t* aLineNo,
|
DOMHighResTimeStamp aDeadline,
|
||||||
uint32_t* aColumn) override;
|
bool aDidTimeout);
|
||||||
virtual void MarkForCC() override;
|
|
||||||
|
|
||||||
nsresult SetTimeout(uint32_t aTimout);
|
void SetTimeoutHandle(int32_t aHandle);
|
||||||
nsresult RunIdleRequestCallback(bool aDidTimeout);
|
bool HasTimeout() const { return mTimeoutHandle.isSome(); }
|
||||||
void CancelTimeout();
|
uint32_t GetTimeoutHandle() const;
|
||||||
|
|
||||||
NS_DECL_NSIRUNNABLE;
|
|
||||||
virtual nsresult Cancel() override;
|
|
||||||
virtual void SetDeadline(mozilla::TimeStamp aDeadline) override;
|
|
||||||
|
|
||||||
uint32_t Handle() const
|
uint32_t Handle() const
|
||||||
{
|
{
|
||||||
|
|
@ -50,22 +40,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequest, nsITimeoutHandler)
|
NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequest)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~IdleRequest();
|
~IdleRequest();
|
||||||
|
|
||||||
// filename, line number and JS language version string of the
|
|
||||||
// caller of setTimeout()
|
|
||||||
nsCString mFileName;
|
|
||||||
uint32_t mLineNo;
|
|
||||||
uint32_t mColumn;
|
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
|
||||||
RefPtr<IdleRequestCallback> mCallback;
|
RefPtr<IdleRequestCallback> mCallback;
|
||||||
uint32_t mHandle;
|
const uint32_t mHandle;
|
||||||
mozilla::Maybe<int32_t> mTimeoutHandle;
|
mozilla::Maybe<int32_t> mTimeoutHandle;
|
||||||
DOMHighResTimeStamp mDeadline;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,11 @@ public:
|
||||||
// default main thread being used.
|
// default main thread being used.
|
||||||
nsresult InitTimer(nsIEventTarget* aTarget, uint32_t aDelay);
|
nsresult InitTimer(nsIEventTarget* aTarget, uint32_t aDelay);
|
||||||
|
|
||||||
enum class Reason { eTimeoutOrInterval, eIdleCallbackTimeout };
|
enum class Reason
|
||||||
|
{
|
||||||
|
eTimeoutOrInterval,
|
||||||
|
eIdleCallbackTimeout,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool HasRefCntOne() const;
|
bool HasRefCntOne() const;
|
||||||
|
|
@ -62,6 +66,8 @@ public:
|
||||||
// True if this is a repeating/interval timer
|
// True if this is a repeating/interval timer
|
||||||
bool mIsInterval;
|
bool mIsInterval;
|
||||||
|
|
||||||
|
// Used to allow several reasons for setting a timeout, where each
|
||||||
|
// 'Reason' value is using a possibly overlapping set of id:s.
|
||||||
Reason mReason;
|
Reason mReason;
|
||||||
|
|
||||||
// Returned as value of setTimeout()
|
// Returned as value of setTimeout()
|
||||||
|
|
|
||||||
43
dom/base/TimeoutHandler.cpp
Normal file
43
dom/base/TimeoutHandler.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "TimeoutHandler.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
TimeoutHandler::TimeoutHandler(JSContext* aCx)
|
||||||
|
: TimeoutHandler()
|
||||||
|
{
|
||||||
|
nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
TimeoutHandler::Call()
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimeoutHandler::GetLocation(const char** aFileName, uint32_t* aLineNo,
|
||||||
|
uint32_t* aColumn)
|
||||||
|
{
|
||||||
|
*aFileName = mFileName.get();
|
||||||
|
*aLineNo = mLineNo;
|
||||||
|
*aColumn = mColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_0(TimeoutHandler)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeoutHandler)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeoutHandler)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
50
dom/base/TimeoutHandler.h
Normal file
50
dom/base/TimeoutHandler.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_timeout_handler_h
|
||||||
|
#define mozilla_dom_timeout_handler_h
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "nsITimeoutHandler.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for implementing nsITimeoutHandlers, designed to be subclassed.
|
||||||
|
*/
|
||||||
|
class TimeoutHandler : public nsITimeoutHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// TimeoutHandler doesn't actually contain cycles, but subclasses
|
||||||
|
// probably will.
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS(TimeoutHandler)
|
||||||
|
|
||||||
|
virtual nsresult Call() override;
|
||||||
|
virtual void GetLocation(const char** aFileName, uint32_t* aLineNo,
|
||||||
|
uint32_t* aColumn) override;
|
||||||
|
virtual void MarkForCC() override {}
|
||||||
|
protected:
|
||||||
|
TimeoutHandler() : mFileName(""), mLineNo(0), mColumn(0) {}
|
||||||
|
explicit TimeoutHandler(JSContext *aCx);
|
||||||
|
|
||||||
|
virtual ~TimeoutHandler() {}
|
||||||
|
private:
|
||||||
|
TimeoutHandler(const TimeoutHandler&) = delete;
|
||||||
|
TimeoutHandler& operator=(const TimeoutHandler&) = delete;
|
||||||
|
TimeoutHandler& operator=(const TimeoutHandler&&) = delete;
|
||||||
|
|
||||||
|
nsCString mFileName;
|
||||||
|
uint32_t mLineNo;
|
||||||
|
uint32_t mColumn;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_timeout_handler_h
|
||||||
|
|
@ -217,6 +217,7 @@ EXPORTS.mozilla.dom += [
|
||||||
'TabGroup.h',
|
'TabGroup.h',
|
||||||
'Text.h',
|
'Text.h',
|
||||||
'Timeout.h',
|
'Timeout.h',
|
||||||
|
'TimeoutHandler.h',
|
||||||
'TreeWalker.h',
|
'TreeWalker.h',
|
||||||
'WebKitCSSMatrix.h',
|
'WebKitCSSMatrix.h',
|
||||||
'WebSocket.h',
|
'WebSocket.h',
|
||||||
|
|
@ -364,6 +365,7 @@ UNIFIED_SOURCES += [
|
||||||
'TextInputProcessor.cpp',
|
'TextInputProcessor.cpp',
|
||||||
'ThirdPartyUtil.cpp',
|
'ThirdPartyUtil.cpp',
|
||||||
'Timeout.cpp',
|
'Timeout.cpp',
|
||||||
|
'TimeoutHandler.cpp',
|
||||||
'TimerClamping.cpp',
|
'TimerClamping.cpp',
|
||||||
'TreeWalker.cpp',
|
'TreeWalker.cpp',
|
||||||
'WebKitCSSMatrix.cpp',
|
'WebKitCSSMatrix.cpp',
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "mozilla/dom/StorageEvent.h"
|
#include "mozilla/dom/StorageEvent.h"
|
||||||
#include "mozilla/dom/StorageEventBinding.h"
|
#include "mozilla/dom/StorageEventBinding.h"
|
||||||
#include "mozilla/dom/Timeout.h"
|
#include "mozilla/dom/Timeout.h"
|
||||||
|
#include "mozilla/dom/TimeoutHandler.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||||
#include "mozilla/dom/WindowOrientationObserver.h"
|
#include "mozilla/dom/WindowOrientationObserver.h"
|
||||||
|
|
@ -552,29 +553,283 @@ DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
class IdleRequestExecutor final : public nsIRunnable
|
||||||
nsGlobalWindow::PostThrottledIdleCallback()
|
, public nsICancelableRunnable
|
||||||
|
, public nsIIncrementalRunnable
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
public:
|
||||||
|
explicit IdleRequestExecutor(nsGlobalWindow* aWindow)
|
||||||
|
: mDispatched(false)
|
||||||
|
, mDeadline(TimeStamp::Now())
|
||||||
|
, mWindow(aWindow)
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWindow);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow());
|
||||||
|
}
|
||||||
|
|
||||||
if (mThrottledIdleRequestCallbacks.isEmpty())
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
|
||||||
|
|
||||||
|
NS_DECL_NSIRUNNABLE
|
||||||
|
nsresult Cancel() override;
|
||||||
|
void SetDeadline(TimeStamp aDeadline) override;
|
||||||
|
|
||||||
|
void MaybeDispatch();
|
||||||
|
private:
|
||||||
|
~IdleRequestExecutor() {}
|
||||||
|
|
||||||
|
bool mDispatched;
|
||||||
|
TimeStamp mDeadline;
|
||||||
|
RefPtr<nsGlobalWindow> mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IdleRequestExecutor::Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
mDispatched = false;
|
||||||
|
if (mWindow) {
|
||||||
|
return mWindow->ExecuteIdleRequest(mDeadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IdleRequestExecutor::Cancel()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
mWindow = nullptr;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IdleRequestExecutor::SetDeadline(TimeStamp aDeadline)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!mWindow) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst());
|
mDeadline = aDeadline;
|
||||||
// ownership transferred from mThrottledIdleRequestCallbacks to
|
}
|
||||||
// mIdleRequestCallbacks
|
|
||||||
mIdleRequestCallbacks.insertBack(request);
|
void
|
||||||
|
IdleRequestExecutor::MaybeDispatch()
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWindow);
|
||||||
|
|
||||||
|
if (mDispatched) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDispatched = true;
|
||||||
|
RefPtr<IdleRequestExecutor> request = this;
|
||||||
NS_IdleDispatchToCurrentThread(request.forget());
|
NS_IdleDispatchToCurrentThread(request.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
|
||||||
nsGlobalWindow::InsertIdleCallbackIntoList(IdleRequest* aRequest,
|
|
||||||
IdleRequests& aList)
|
|
||||||
{
|
{
|
||||||
aList.insertBack(aRequest);
|
public:
|
||||||
|
explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
|
||||||
|
: mExecutor(aExecutor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,
|
||||||
|
TimeoutHandler)
|
||||||
|
|
||||||
|
nsresult Call() override
|
||||||
|
{
|
||||||
|
mExecutor->MaybeDispatch();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
~IdleRequestExecutorTimeoutHandler() {}
|
||||||
|
RefPtr<IdleRequestExecutor> mExecutor;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler, mExecutor)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::ScheduleIdleRequestDispatch()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
if (mIdleRequestCallbacks.isEmpty()) {
|
||||||
|
if (mIdleRequestExecutor) {
|
||||||
|
mIdleRequestExecutor->Cancel();
|
||||||
|
mIdleRequestExecutor = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mIdleRequestExecutor) {
|
||||||
|
mIdleRequestExecutor = new IdleRequestExecutor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsPIDOMWindowOuter* outer = GetOuterWindow();
|
||||||
|
if (outer && outer->AsOuter()->IsBackground()) {
|
||||||
|
nsCOMPtr<nsITimeoutHandler> handler = new IdleRequestExecutorTimeoutHandler(mIdleRequestExecutor);
|
||||||
|
int32_t dummy;
|
||||||
|
// Set a timeout handler with a timeout of 0 ms to throttle idle
|
||||||
|
// callback requests coming from a backround window using
|
||||||
|
// background timeout throttling.
|
||||||
|
SetTimeoutOrInterval(handler, 0, false,
|
||||||
|
Timeout::Reason::eIdleCallbackTimeout, &dummy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIdleRequestExecutor->MaybeDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::SuspendIdleRequests()
|
||||||
|
{
|
||||||
|
if (mIdleRequestExecutor) {
|
||||||
|
mIdleRequestExecutor->Cancel();
|
||||||
|
mIdleRequestExecutor = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::ResumeIdleRequests()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mIdleRequestExecutor);
|
||||||
|
|
||||||
|
ScheduleIdleRequestDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::InsertIdleCallback(IdleRequest* aRequest)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
mIdleRequestCallbacks.insertBack(aRequest);
|
||||||
aRequest->AddRef();
|
aRequest->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
if (aRequest->HasTimeout()) {
|
||||||
|
ClearTimeoutOrInterval(aRequest->GetTimeoutHandle(),
|
||||||
|
Timeout::Reason::eIdleCallbackTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
aRequest->removeFrom(mIdleRequestCallbacks);
|
||||||
|
aRequest->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsGlobalWindow::RunIdleRequest(IdleRequest* aRequest,
|
||||||
|
DOMHighResTimeStamp aDeadline,
|
||||||
|
bool aDidTimeout)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
RefPtr<IdleRequest> request(aRequest);
|
||||||
|
nsresult result = request->IdleRun(AsInner(), aDeadline, aDidTimeout);
|
||||||
|
RemoveIdleCallback(request);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsGlobalWindow::ExecuteIdleRequest(TimeStamp aDeadline)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
// There are no more idle requests, so stop scheduling idle
|
||||||
|
// request callbacks.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp deadline = 0.0;
|
||||||
|
|
||||||
|
if (Performance* perf = GetPerformance()) {
|
||||||
|
deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult result = RunIdleRequest(request, deadline, false);
|
||||||
|
|
||||||
|
ScheduleIdleRequestDispatch();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
class IdleRequestTimeoutHandler final : public TimeoutHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdleRequestTimeoutHandler(JSContext* aCx,
|
||||||
|
IdleRequest* aIdleRequest,
|
||||||
|
nsPIDOMWindowInner* aWindow)
|
||||||
|
: TimeoutHandler(aCx)
|
||||||
|
, mIdleRequest(aIdleRequest)
|
||||||
|
, mWindow(aWindow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,
|
||||||
|
TimeoutHandler)
|
||||||
|
|
||||||
|
nsresult Call() override
|
||||||
|
{
|
||||||
|
return nsGlobalWindow::Cast(mWindow)->RunIdleRequest(mIdleRequest, 0.0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~IdleRequestTimeoutHandler() {}
|
||||||
|
|
||||||
|
RefPtr<IdleRequest> mIdleRequest;
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler,
|
||||||
|
TimeoutHandler,
|
||||||
|
mIdleRequest,
|
||||||
|
mWindow)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsITimeoutHandler)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
|
nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
|
||||||
IdleRequestCallback& aCallback,
|
IdleRequestCallback& aCallback,
|
||||||
|
|
@ -584,33 +839,36 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
|
||||||
MOZ_RELEASE_ASSERT(IsInnerWindow());
|
MOZ_RELEASE_ASSERT(IsInnerWindow());
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
uint32_t handle = ++mIdleRequestCallbackCounter;
|
uint32_t handle = mIdleRequestCallbackCounter++;
|
||||||
|
|
||||||
RefPtr<IdleRequest> request =
|
RefPtr<IdleRequest> request =
|
||||||
new IdleRequest(aCx, AsInner(), aCallback, handle);
|
new IdleRequest(&aCallback, handle);
|
||||||
|
|
||||||
if (aOptions.mTimeout.WasPassed()) {
|
if (aOptions.mTimeout.WasPassed()) {
|
||||||
aError = request->SetTimeout(aOptions.mTimeout.Value());
|
int32_t timeoutHandle;
|
||||||
if (NS_WARN_IF(aError.Failed())) {
|
nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, AsInner()));
|
||||||
|
|
||||||
|
nsresult rv = SetTimeoutOrInterval(
|
||||||
|
handler, aOptions.mTimeout.Value(), false,
|
||||||
|
Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request->SetTimeoutHandle(timeoutHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsGlobalWindow* outer = GetOuterWindowInternal();
|
// If the list of idle callback requests is not empty it means that
|
||||||
if (outer && outer->AsOuter()->IsBackground()) {
|
// we've already dispatched the first idle request. If we're
|
||||||
// mThrottledIdleRequestCallbacks now owns request
|
// suspended we should only queue the idle callback and not schedule
|
||||||
InsertIdleCallbackIntoList(request, mThrottledIdleRequestCallbacks);
|
// it to run, that will be done in ResumeIdleRequest.
|
||||||
|
bool needsScheduling = !IsSuspended() && mIdleRequestCallbacks.isEmpty();
|
||||||
|
// mIdleRequestCallbacks now owns request
|
||||||
|
InsertIdleCallback(request);
|
||||||
|
|
||||||
NS_DelayedDispatchToCurrentThread(
|
if (needsScheduling) {
|
||||||
NewRunnableMethod(this, &nsGlobalWindow::PostThrottledIdleCallback),
|
ScheduleIdleRequestDispatch();
|
||||||
10000);
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(mThrottledIdleRequestCallbacks.isEmpty());
|
|
||||||
|
|
||||||
// mIdleRequestCallbacks now owns request
|
|
||||||
InsertIdleCallbackIntoList(request, mIdleRequestCallbacks);
|
|
||||||
|
|
||||||
NS_IdleDispatchToCurrentThread(request.forget());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
|
|
@ -623,7 +881,7 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
|
||||||
|
|
||||||
for (IdleRequest* r : mIdleRequestCallbacks) {
|
for (IdleRequest* r : mIdleRequestCallbacks) {
|
||||||
if (r->Handle() == aHandle) {
|
if (r->Handle() == aHandle) {
|
||||||
r->Cancel();
|
RemoveIdleCallback(r);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -632,29 +890,17 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
|
||||||
void
|
void
|
||||||
nsGlobalWindow::DisableIdleCallbackRequests()
|
nsGlobalWindow::DisableIdleCallbackRequests()
|
||||||
{
|
{
|
||||||
|
if (mIdleRequestExecutor) {
|
||||||
|
mIdleRequestExecutor->Cancel();
|
||||||
|
mIdleRequestExecutor = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
while (!mIdleRequestCallbacks.isEmpty()) {
|
while (!mIdleRequestCallbacks.isEmpty()) {
|
||||||
RefPtr<IdleRequest> request = mIdleRequestCallbacks.popFirst();
|
RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
|
||||||
request->Cancel();
|
RemoveIdleCallback(request);
|
||||||
}
|
|
||||||
|
|
||||||
while (!mThrottledIdleRequestCallbacks.isEmpty()) {
|
|
||||||
RefPtr<IdleRequest> request = mThrottledIdleRequestCallbacks.popFirst();
|
|
||||||
request->Cancel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsGlobalWindow::UnthrottleIdleCallbackRequests()
|
|
||||||
{
|
|
||||||
AssertIsOnMainThread();
|
|
||||||
|
|
||||||
while (!mThrottledIdleRequestCallbacks.isEmpty()) {
|
|
||||||
RefPtr<IdleRequest> request(mThrottledIdleRequestCallbacks.popFirst());
|
|
||||||
mIdleRequestCallbacks.insertBack(request);
|
|
||||||
NS_IdleDispatchToCurrentThread(request.forget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
extern uint64_t
|
extern uint64_t
|
||||||
|
|
@ -1306,6 +1552,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
||||||
mSerial(0),
|
mSerial(0),
|
||||||
mIdleCallbackTimeoutCounter(1),
|
mIdleCallbackTimeoutCounter(1),
|
||||||
mIdleRequestCallbackCounter(1),
|
mIdleRequestCallbackCounter(1),
|
||||||
|
mIdleRequestExecutor(nullptr),
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mSetOpenerWindowCalled(false),
|
mSetOpenerWindowCalled(false),
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2033,14 +2280,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
|
||||||
for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
|
for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
|
||||||
cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
|
cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdleRequest* request : tmp->mThrottledIdleRequestCallbacks) {
|
|
||||||
cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
||||||
|
|
||||||
#ifdef MOZ_GAMEPAD
|
#ifdef MOZ_GAMEPAD
|
||||||
|
|
@ -2147,6 +2391,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||||
|
|
||||||
tmp->UnlinkHostObjectURIs();
|
tmp->UnlinkHostObjectURIs();
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
|
||||||
tmp->DisableIdleCallbackRequests();
|
tmp->DisableIdleCallbackRequests();
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||||
|
|
@ -10237,12 +10482,6 @@ void nsGlobalWindow::SetIsBackground(bool aIsBackground)
|
||||||
ResetTimersForThrottleReduction(gMinBackgroundTimeoutValue);
|
ResetTimersForThrottleReduction(gMinBackgroundTimeoutValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aIsBackground) {
|
|
||||||
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
|
|
||||||
if (inner) {
|
|
||||||
inner->UnthrottleIdleCallbackRequests();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef MOZ_GAMEPAD
|
#ifdef MOZ_GAMEPAD
|
||||||
if (!aIsBackground) {
|
if (!aIsBackground) {
|
||||||
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
|
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
|
||||||
|
|
@ -12036,6 +12275,8 @@ nsGlobalWindow::Suspend()
|
||||||
|
|
||||||
mozilla::dom::workers::SuspendWorkersForWindow(AsInner());
|
mozilla::dom::workers::SuspendWorkersForWindow(AsInner());
|
||||||
|
|
||||||
|
SuspendIdleRequests();
|
||||||
|
|
||||||
for (Timeout* t = mTimeouts.getFirst(); t; t = t->getNext()) {
|
for (Timeout* t = mTimeouts.getFirst(); t; t = t->getNext()) {
|
||||||
// Leave the timers with the current time remaining. This will
|
// Leave the timers with the current time remaining. This will
|
||||||
// cause the timers to potentially fire when the window is
|
// cause the timers to potentially fire when the window is
|
||||||
|
|
@ -12146,6 +12387,8 @@ nsGlobalWindow::Resume()
|
||||||
t->AddRef();
|
t->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResumeIdleRequests();
|
||||||
|
|
||||||
// Resume all of the workers for this window. We must do this
|
// Resume all of the workers for this window. We must do this
|
||||||
// after timeouts since workers may have queued events that can trigger
|
// after timeouts since workers may have queued events that can trigger
|
||||||
// a setTimeout().
|
// a setTimeout().
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ struct nsRect;
|
||||||
|
|
||||||
class nsWindowSizes;
|
class nsWindowSizes;
|
||||||
|
|
||||||
|
class IdleRequestExecutor;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class DOMEventTargetHelper;
|
class DOMEventTargetHelper;
|
||||||
class ThrottledEventQueue;
|
class ThrottledEventQueue;
|
||||||
|
|
@ -118,6 +120,7 @@ class Gamepad;
|
||||||
enum class ImageBitmapFormat : uint32_t;
|
enum class ImageBitmapFormat : uint32_t;
|
||||||
class IdleRequest;
|
class IdleRequest;
|
||||||
class IdleRequestCallback;
|
class IdleRequestCallback;
|
||||||
|
class IncrementalRunnable;
|
||||||
class Location;
|
class Location;
|
||||||
class MediaQueryList;
|
class MediaQueryList;
|
||||||
class MozSelfSupport;
|
class MozSelfSupport;
|
||||||
|
|
@ -1097,7 +1100,6 @@ public:
|
||||||
mozilla::ErrorResult& aError);
|
mozilla::ErrorResult& aError);
|
||||||
void CancelIdleCallback(uint32_t aHandle);
|
void CancelIdleCallback(uint32_t aHandle);
|
||||||
|
|
||||||
|
|
||||||
#ifdef MOZ_WEBSPEECH
|
#ifdef MOZ_WEBSPEECH
|
||||||
mozilla::dom::SpeechSynthesis*
|
mozilla::dom::SpeechSynthesis*
|
||||||
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
||||||
|
|
@ -1762,6 +1764,21 @@ private:
|
||||||
mozilla::dom::TabGroup* TabGroupInner();
|
mozilla::dom::TabGroup* TabGroupInner();
|
||||||
mozilla::dom::TabGroup* TabGroupOuter();
|
mozilla::dom::TabGroup* TabGroupOuter();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void DisableIdleCallbackRequests();
|
||||||
|
uint32_t IdleRequestHandle() const { return mIdleRequestCallbackCounter; }
|
||||||
|
nsresult RunIdleRequest(mozilla::dom::IdleRequest* aRequest,
|
||||||
|
DOMHighResTimeStamp aDeadline, bool aDidTimeout);
|
||||||
|
nsresult ExecuteIdleRequest(TimeStamp aDeadline);
|
||||||
|
void ScheduleIdleRequestDispatch();
|
||||||
|
void SuspendIdleRequests();
|
||||||
|
void ResumeIdleRequests();
|
||||||
|
|
||||||
|
typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests;
|
||||||
|
void InsertIdleCallback(mozilla::dom::IdleRequest* aRequest);
|
||||||
|
|
||||||
|
void RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// These members are only used on outer window objects. Make sure
|
// These members are only used on outer window objects. Make sure
|
||||||
// you never set any of these on an inner object!
|
// you never set any of these on an inner object!
|
||||||
|
|
@ -1912,21 +1929,12 @@ protected:
|
||||||
|
|
||||||
uint32_t mSerial;
|
uint32_t mSerial;
|
||||||
|
|
||||||
void DisableIdleCallbackRequests();
|
|
||||||
void UnthrottleIdleCallbackRequests();
|
|
||||||
|
|
||||||
void PostThrottledIdleCallback();
|
|
||||||
|
|
||||||
typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests;
|
|
||||||
static void InsertIdleCallbackIntoList(mozilla::dom::IdleRequest* aRequest,
|
|
||||||
IdleRequests& aList);
|
|
||||||
|
|
||||||
// The current idle request callback timeout handle
|
// The current idle request callback timeout handle
|
||||||
uint32_t mIdleCallbackTimeoutCounter;
|
uint32_t mIdleCallbackTimeoutCounter;
|
||||||
// The current idle request callback handle
|
// The current idle request callback handle
|
||||||
uint32_t mIdleRequestCallbackCounter;
|
uint32_t mIdleRequestCallbackCounter;
|
||||||
IdleRequests mIdleRequestCallbacks;
|
IdleRequests mIdleRequestCallbacks;
|
||||||
IdleRequests mThrottledIdleRequestCallbacks;
|
RefPtr<IdleRequestExecutor> mIdleRequestExecutor;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool mSetOpenerWindowCalled;
|
bool mSetOpenerWindowCalled;
|
||||||
|
|
@ -2002,6 +2010,7 @@ protected:
|
||||||
friend class nsDOMWindowUtils;
|
friend class nsDOMWindowUtils;
|
||||||
friend class mozilla::dom::PostMessageEvent;
|
friend class mozilla::dom::PostMessageEvent;
|
||||||
friend class DesktopNotification;
|
friend class DesktopNotification;
|
||||||
|
friend class IdleRequestExecutor;
|
||||||
|
|
||||||
static WindowByIdTable* sWindowsById;
|
static WindowByIdTable* sWindowsById;
|
||||||
static bool sWarnedAboutWindowInternal;
|
static bool sWarnedAboutWindowInternal;
|
||||||
|
|
|
||||||
|
|
@ -38674,6 +38674,12 @@
|
||||||
"url": "/html/webappapis/idle-callbacks/callback-multiple-calls.html"
|
"url": "/html/webappapis/idle-callbacks/callback-multiple-calls.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"html/webappapis/idle-callbacks/callback-suspended.html": [
|
||||||
|
{
|
||||||
|
"path": "html/webappapis/idle-callbacks/callback-suspended.html",
|
||||||
|
"url": "/html/webappapis/idle-callbacks/callback-suspended.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"html/webappapis/idle-callbacks/callback-timeout.html": [
|
"html/webappapis/idle-callbacks/callback-timeout.html": [
|
||||||
{
|
{
|
||||||
"path": "html/webappapis/idle-callbacks/callback-timeout.html",
|
"path": "html/webappapis/idle-callbacks/callback-timeout.html",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Dispatching idle callbacks should be able to be suspended and then resumed</title>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
function withEventListener(target, event, handler) {
|
||||||
|
handler = handler || (e => e);
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let wrapper = function(e) {
|
||||||
|
let result = handler(e);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
target.addEventListener(event, wrapper, { once: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePostBackUrl(name) {
|
||||||
|
return new URL('resources/post_name_on_load.html?name=' + name,
|
||||||
|
window.location).href;
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForMessage(message, handler) {
|
||||||
|
return withEventListener(window, 'message', e => (e.data === message) && handler(e));;
|
||||||
|
}
|
||||||
|
|
||||||
|
function withWindow(name) {
|
||||||
|
let win = window.open(makePostBackUrl(name))
|
||||||
|
return waitForMessage(name, _ => win);
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateWindow(win, name) {
|
||||||
|
win.location = makePostBackUrl(name);
|
||||||
|
return waitForMessage(name, _ => win);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitDuration(delay) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(resolve, delay);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function goBack(win) {
|
||||||
|
var p = withEventListener(win, 'pagehide');
|
||||||
|
win.history.back();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_test(t => {
|
||||||
|
let idleCalled = false;
|
||||||
|
let running = true;
|
||||||
|
return withWindow('foo')
|
||||||
|
.then(win => {
|
||||||
|
let callback = function(d) {
|
||||||
|
idleCalled = true;
|
||||||
|
if (running) {
|
||||||
|
win.requestIdleCallback(callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
win.requestIdleCallback(callback);
|
||||||
|
|
||||||
|
return navigateWindow(win, 'bar')
|
||||||
|
.then(_ => idleCalled = false)
|
||||||
|
.then(_ => waitDuration(2000))
|
||||||
|
.then(_ => {
|
||||||
|
assert_false(idleCalled, "idle callback shouldn't have been called yet");
|
||||||
|
return goBack(win);
|
||||||
|
})
|
||||||
|
.then(_ => Promise.race([
|
||||||
|
// At this point it's a matter of having bfcache ...
|
||||||
|
waitDuration(2000)
|
||||||
|
.then(_ => {
|
||||||
|
assert_true(idleCalled, "idle callback should've been called by now");
|
||||||
|
running = false;
|
||||||
|
}),
|
||||||
|
// ... or not. If not, we expect a load event.
|
||||||
|
waitForMessage("foo")
|
||||||
|
]))
|
||||||
|
.then(_ => win.close())
|
||||||
|
.catch(e => {
|
||||||
|
win.close();
|
||||||
|
throw e;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!doctype html>
|
||||||
|
<script>
|
||||||
|
addEventListener('load', _ => {
|
||||||
|
let params = new URLSearchParams(window.location.search);
|
||||||
|
window.opener.postMessage(params.get('name'), '*');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue