fixup!
Bug 1313864 - Make IdleRequest dispatch itself. r?bkelly
--- a/dom/base/IdleRequest.cpp
+++ b/dom/base/IdleRequest.cpp
@@ -73,16 +73,17 @@ IdleRequest::SetTimeout(uint32_t aTimeou
return rv;
}
void
IdleRequest::Dispatch()
{
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_DIAGNOSTIC_ASSERT(!mRunning);
RefPtr<IdleRequest> kungFuDeathGrip(this);
NS_IdleDispatchToCurrentThread(kungFuDeathGrip.forget());
mRunning = true;
}
nsresult
IdleRequest::Run()
@@ -124,22 +125,23 @@ nsresult
IdleRequest::RunIdleRequestCallback(bool aDidTimeout)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aDidTimeout) {
CancelTimeout();
}
- remove();
ErrorResult error;
RefPtr<IdleDeadline> deadline =
new IdleDeadline(mWindow, aDidTimeout, mDeadline);
mCallback->Call(*deadline, error, "requestIdleCallback handler");
mCallback = nullptr;
+
+ remove();
Release();
nsGlobalWindow::Cast(mWindow)->DispatchNextIdleRequest();
return error.StealNSResult();
}
void
--- a/dom/base/RunnableTimeoutHandler.cpp
+++ b/dom/base/RunnableTimeoutHandler.cpp
@@ -10,16 +10,17 @@
namespace mozilla {
namespace dom {
RunnableTimeoutHandler::RunnableTimeoutHandler(
already_AddRefed<nsIRunnable> aRunnable)
: mRunnable(Move(aRunnable))
{
+ MOZ_ASSERT(mRunnable);
}
nsresult
RunnableTimeoutHandler::Call()
{
return mRunnable->Run();
}
--- a/dom/base/RunnableTimeoutHandler.h
+++ b/dom/base/RunnableTimeoutHandler.h
@@ -15,17 +15,17 @@
class nsIRunnable;
namespace mozilla {
namespace dom {
class RunnableTimeoutHandler final : public nsITimeoutHandler
{
public:
- RunnableTimeoutHandler(already_AddRefed<nsIRunnable> aRunnable);
+ explicit RunnableTimeoutHandler(already_AddRefed<nsIRunnable> aRunnable);
virtual nsresult Call() override;
virtual void GetLocation(const char** aFileName, uint32_t* aLineNo,
uint32_t* aColumn) override;
virtual void MarkForCC() override {}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(RunnableTimeoutHandler)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -575,22 +575,28 @@ nsGlobalWindow::DispatchNextIdleRequest(
return;
}
nsGlobalWindow* outer = GetOuterWindowInternal();
if (outer && outer->AsOuter()->IsBackground()) {
int32_t dummy;
RefPtr<RunnableTimeoutHandler> timeout(new RunnableTimeoutHandler(
NewRunnableMethod(this, &nsGlobalWindow::DispatchIdleRequest)));
- SetTimeoutOrInterval(timeout, 0, false, Timeout::Reason::eInternalTimeout,
- &dummy);
- } else {
- RefPtr<IdleRequest> request(mIdleRequestCallbacks.getFirst());
- request->Dispatch();
- }
+ // We really want to re-use the mechanisms in SetTimeoutOrInterval
+ // to handle throttling, but due to Bug 1316871 we can't do that
+ // yet. When that is fixed we can instead of passing
+ // gMinBackgroundTimeoutValue just pass 0.
+ SetTimeoutOrInterval(timeout, gMinBackgroundTimeoutValue, false,
+ Timeout::Reason::eInternalTimeout, &dummy);
+
+ return;
+ }
+
+ RefPtr<IdleRequest> request(mIdleRequestCallbacks.getFirst());
+ request->Dispatch();
}
/* static */ void
nsGlobalWindow::InsertIdleCallbackIntoList(IdleRequest* aRequest,
IdleRequests& aList)
{
aList.insertBack(aRequest);
aRequest->AddRef();
@@ -612,16 +618,19 @@ nsGlobalWindow::RequestIdleCallback(JSCo
if (aOptions.mTimeout.WasPassed()) {
aError = request->SetTimeout(aOptions.mTimeout.Value());
if (NS_WARN_IF(aError.Failed())) {
return 0;
}
}
+ // If the list of idle callback requests is not empty it means that
+ // we've already dispatched the first idle request. It is the
+ // responsibility of that to dispatch the next.
bool needsScheduling = mIdleRequestCallbacks.isEmpty();
// mIdleRequestCallbacks now owns request
InsertIdleCallbackIntoList(request, mIdleRequestCallbacks);
if (needsScheduling) {
DispatchNextIdleRequest();
}
@@ -12481,18 +12490,19 @@ uint32_t sNestingLevel;
uint32_t
nsGlobalWindow::GetTimeoutId(Timeout::Reason aReason)
{
switch (aReason) {
case Timeout::Reason::eIdleCallbackTimeout:
return ++mIdleCallbackTimeoutCounter;
case Timeout::Reason::eTimeoutOrInterval:
return ++mTimeoutIdCounter;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unhandled timeout reason");
case Timeout::Reason::eInternalTimeout:
- default:
return 0;
}
}
nsGlobalWindow*
nsGlobalWindow::InnerForSetTimeoutOrInterval(ErrorResult& aError)
{
nsGlobalWindow* currentInner;