Commit 895f39e1 authored by rmcilroy@chromium.org's avatar rmcilroy@chromium.org

Implementation of the requestIdleCallback API

Initial implementation of the requestIdleCallback API based on
the spec at https://w3c.github.io/requestidlecallback/.

This API is behind a flag and is not enabled by default.

BUG=514651
TBR=jochen@chromium.org
NOTRY=true

Review URL: https://codereview.chromium.org/1119683003

git-svn-id: svn://svn.chromium.org/blink/trunk@200992 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent f311b74a
......@@ -163,5 +163,10 @@
"prefix": "trustedeventsdefaultaction",
"base": "fast/events",
"args": ["--enable-blink-features=TrustedEventsDefaultAction"]
},
{
"prefix": "threaded",
"base": "fast/idle-callback",
"args": ["--enable-threaded-compositing"]
}
]
# This suite runs the tests in virtual/threaded/fast/idle-callback with
# --enable-threaded-compositing since the tests require threaded compositing
<!DOCTYPE html>
<title>window.requestIdleCallback exists</title>
<link rel="author" title="Ross McIlroy" href="mailto:rmcilroy@chromium.org" />
<link rel="help" href="http://www.w3.org/TR/requestidlecallback/"/>
<script src="../../../../resources/testharness.js"></script>
<script src="../../../../resources/testharnessreport.js"></script>
<link rel="stylesheet" href="../../resources/testharness.css" />
<script>
test(function() {
assert_equals(typeof window.requestIdleCallback, "function");
}, "window.requestIdleCallback is defined", {assert: "The window.requestIdleCallback function is used to request callbacks during browser-defined idle time."});
test(function() {
assert_equals(typeof window.cancelIdleCallback, "function");
}, "window.cancelIdleCallback is defined", {assert: "The window.cancelIdleCallback function is used to cancel callbacks scheduled via requestIdleCallback."});
test(function() {
assert_equals(typeof window.requestIdleCallback(function() {}), "number");
}, "window.requestIdleCallback() returns a number", {assert: "The requestIdleCallback method MUST return a long"});
test(function() {
assert_equals(typeof window.cancelIdleCallback(1), "undefined");
}, "window.cancelIdleCallback() returns undefined", {assert: "The cancelIdleCallback method MUST return void"});
async_test(function() {
// Check whether requestIdleCallback schedules a callback which gets executed
// and the deadline argument is passed correctly.
requestIdleCallback(this.step_func(function(deadline) {
assert_equals(typeof deadline, "object", "IdleDeadline MUST be passed to callback.");
assert_equals(typeof deadline.timeRemaining, "number", "IdleDeadline.timeRemaining MUST be a double time remaining in milliseconds");
assert_true(deadline.timeRemaining <= 50, "IdleDeadline.timeRemaining() MUST be less than or equal to 50ms in the future.");
assert_equals(typeof deadline.didTimeout, "boolean", "IdleDeadline.didTimeout MUST be a boolean");
assert_false(deadline.didTimeout, "IdleDeadline.didTimeout MUST be false if requestIdleCallback wasn't scheduled due to a timeout");
this.done();
}));
}, 'requestIdleCallback schedules callbacks');
async_test(function() {
// Check whether requestIdleCallback schedules a callback which gets executed
// and the deadline argument is passed correctly.
var handle = requestIdleCallback(this.step_func(function(deadline) {
assert_unreached("callback should not be called if canceled with cancelIdleCallback");
}));
cancelIdleCallback(handle);
setTimeout(this.step_func(function() {
this.done();
}), 200);
}, 'cancelIdleCallback cancels callbacks');
</script>
<h1>Description</h1>
<p>This test validates that window.requestIdleCallback and window.cancelIdleCallback exist and are a functions.</p>
<div id="log"></div>
<!DOCTYPE html>
<title>window.requestIdleCallback deals with timeouts correctly</title>
<link rel="author" title="Ross McIlroy" href="mailto:rmcilroy@chromium.org" />
<link rel="help" href="http://www.w3.org/TR/requestidlecallback/"/>
<script src="../../../../resources/testharness.js"></script>
<script src="../../../../resources/testharnessreport.js"></script>
<link rel="stylesheet" href="../../resources/testharness.css" />
<script>
async_test(function() {
// Check whether requestIdleCallback with a timeout works when the event loop
// is busy.
var busy_raf_loop_iterations_remaining = 10; // Should take 20 * 40 = 400ms
var idle_callback_scheduled;
var idle_callback = this.step_func(function(deadline) {
assert_false(deadline.didTimeout, "IdleDeadline.didTimeout MUST be false if requestIdleCallback wasn't scheduled due to a timeout");
assert_equals(busy_raf_loop_iterations_remaining, 0, "Busy rAF loop should be finished by the time we get scheduled");
this.done();
});
var busy_raf_loop_iterations_remaining = 10; // Should take 20 * 40 = 400ms
requestAnimationFrame(this.step_func(function busyRAFLoop() {
var start_time = performance.now();
if (!idle_callback_scheduled) {
idle_callback_scheduled = start_time;
requestIdleCallback(idle_callback);
}
// Use up the whole frame budget.
while (performance.now() - start_time < 40) { }
if (busy_raf_loop_iterations_remaining > 0) {
busy_raf_loop_iterations_remaining--;
requestAnimationFrame(busyRAFLoop);
}
}));
}, 'requestIdleCallback not scheduled when event loop is busy.');
async_test(function() {
// Check whether requestIdleCallback with a timeout works when the event loop
// is busy.
var busy_raf_loop_iterations_remaining = 10; // Should take 20 * 40 = 400ms
var timeout = 200;
var idle_callback_scheduled;
var idle_callback = this.step_func(function(deadline) {
var time_delta = performance.now() - idle_callback_scheduled;
assert_true(time_delta >= timeout, "Should only have been run after timeout");
assert_true(time_delta - timeout <= 80, "Should have been scheduled close to timeout");
assert_true(deadline.timeRemaining == 0, "IdleDeadline.timeRemaining MUST be equal to zero if requestIdleCallback was scheduled due to a timeout");
assert_true(deadline.didTimeout, "IdleDeadline.didTimeout MUST be true if requestIdleCallback was scheduled due to a timeout");
assert_true(busy_raf_loop_iterations_remaining > 0, "Busy rAF loop should still be going");
this.done();
});
requestAnimationFrame(this.step_func(function busyRAFLoop() {
var start_time = performance.now();
if (!idle_callback_scheduled) {
idle_callback_scheduled = start_time;
requestIdleCallback(idle_callback, timeout);
}
// Use up the whole frame budget.
while (performance.now() - start_time < 40) { }
if (busy_raf_loop_iterations_remaining > 0) {
busy_raf_loop_iterations_remaining--;
requestAnimationFrame(busyRAFLoop);
}
}));
}, 'requestIdleCallback scheduled with timeout when event loop is busy.');
</script>
<h1>Description</h1>
<p>This test validates that window.requestIdleCallback deals with timeouts correctly.</p>
<div id="log"></div>
......@@ -3054,6 +3054,10 @@ interface IDBVersionChangeEvent
getter newVersion
getter oldVersion
method constructor
interface IdleCallbackDeadline
getter didTimeout
getter timeRemaining
method constructor
interface Image
method constructor
interface ImageBitmap
......@@ -6296,6 +6300,7 @@ interface Window
method blur
method btoa
method cancelAnimationFrame
method cancelIdleCallback
method captureEvents
method clearInterval
method clearTimeout
......@@ -6320,6 +6325,7 @@ interface Window
method prompt
method releaseEvents
method requestAnimationFrame
method requestIdleCallback
method resizeBy
method resizeTo
method scroll
......
......@@ -69,6 +69,8 @@
'dom/Float32Array.idl',
'dom/Float64Array.idl',
'dom/FrameRequestCallback.idl',
'dom/IdleCallbackDeadline.idl',
'dom/IdleRequestCallback.idl',
'dom/Int16Array.idl',
'dom/Int32Array.idl',
'dom/Int8Array.idl',
......@@ -2310,6 +2312,9 @@
'dom/GlobalEventHandlers.h',
'dom/IconURL.cpp',
'dom/IconURL.h',
'dom/IdleCallbackDeadline.cpp',
'dom/IdleCallbackDeadline.h',
'dom/IdleRequestCallback.h',
'dom/IdTargetObserver.cpp',
'dom/IdTargetObserver.h',
'dom/IdTargetObserverRegistry.cpp',
......@@ -2390,6 +2395,8 @@
'dom/ScriptableDocumentParser.h',
'dom/ScriptedAnimationController.cpp',
'dom/ScriptedAnimationController.h',
'dom/ScriptedIdleTaskController.cpp',
'dom/ScriptedIdleTaskController.h',
'dom/SecurityContext.cpp',
'dom/SecurityContext.h',
'dom/SelectorQuery.cpp',
......
......@@ -91,6 +91,7 @@
#include "core/dom/ProcessingInstruction.h"
#include "core/dom/ScriptRunner.h"
#include "core/dom/ScriptedAnimationController.h"
#include "core/dom/ScriptedIdleTaskController.h"
#include "core/dom/SelectorQuery.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/StyleEngine.h"
......@@ -586,6 +587,8 @@ void Document::dispose()
m_scriptedAnimationController->clearDocumentPointer();
m_scriptedAnimationController.clear();
m_scriptedIdleTaskController.clear();
if (svgExtensions())
accessSVGExtensions().pauseAnimations();
......@@ -2136,6 +2139,8 @@ void Document::detach(const AttachContext& context)
m_scriptedAnimationController->clearDocumentPointer();
m_scriptedAnimationController.clear();
m_scriptedIdleTaskController.clear();
if (svgExtensions())
accessSVGExtensions().pauseAnimations();
......@@ -5130,6 +5135,25 @@ void Document::serviceScriptedAnimations(double monotonicAnimationStartTime)
m_scriptedAnimationController->serviceScriptedAnimations(monotonicAnimationStartTime);
}
ScriptedIdleTaskController& Document::ensureScriptedIdleTaskController()
{
if (!m_scriptedIdleTaskController)
m_scriptedIdleTaskController = ScriptedIdleTaskController::create(this, loader()->timing());
return *m_scriptedIdleTaskController;
}
int Document::requestIdleCallback(IdleRequestCallback* callback, double timeoutMillis)
{
return ensureScriptedIdleTaskController().registerCallback(callback, timeoutMillis);
}
void Document::cancelIdleCallback(int id)
{
if (!m_scriptedIdleTaskController)
return;
m_scriptedIdleTaskController->cancelCallback(id);
}
PassRefPtrWillBeRawPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, double pageX, double pageY, double screenX, double screenY, double radiusX, double radiusY, float rotationAngle, float force) const
{
// Match behavior from when these types were integers, and avoid surprises from someone explicitly
......@@ -5660,6 +5684,7 @@ DEFINE_TRACE(Document)
visitor->trace(m_documentTiming);
visitor->trace(m_mediaQueryMatcher);
visitor->trace(m_scriptedAnimationController);
visitor->trace(m_scriptedIdleTaskController);
visitor->trace(m_taskRunner);
visitor->trace(m_textAutosizer);
visitor->trace(m_registrationContext);
......
......@@ -122,6 +122,7 @@ class HTMLImportsController;
class HTMLLinkElement;
class HTMLScriptElement;
class HitTestRequest;
class IdleRequestCallback;
class InputDeviceCapabilities;
class LayoutPoint;
class LiveNodeListBase;
......@@ -146,6 +147,7 @@ class SVGUseElement;
class ScriptRunner;
class ScriptableDocumentParser;
class ScriptedAnimationController;
class ScriptedIdleTaskController;
class SecurityOrigin;
class SegmentedString;
class SelectorQueryCache;
......@@ -914,6 +916,9 @@ public:
void cancelAnimationFrame(int id);
void serviceScriptedAnimations(double monotonicAnimationStartTime);
int requestIdleCallback(IdleRequestCallback*, double timeoutMillis);
void cancelIdleCallback(int id);
EventTarget* errorEventTarget() final;
void logExceptionToConsole(const String& errorMessage, int scriptId, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack>) final;
......@@ -1065,6 +1070,7 @@ private:
bool isElementNode() const = delete; // This will catch anyone doing an unnecessary check.
ScriptedAnimationController& ensureScriptedAnimationController();
ScriptedIdleTaskController& ensureScriptedIdleTaskController();
SecurityContext& securityContext() final { return *this; }
EventQueue* eventQueue() const final;
......@@ -1333,6 +1339,7 @@ private:
unsigned m_writeRecursionDepth;
RefPtrWillBeMember<ScriptedAnimationController> m_scriptedAnimationController;
RefPtrWillBeMember<ScriptedIdleTaskController> m_scriptedIdleTaskController;
OwnPtrWillBeMember<MainThreadTaskRunner> m_taskRunner;
OwnPtrWillBeMember<TextAutosizer> m_textAutosizer;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/dom/IdleCallbackDeadline.h"
#include "core/loader/DocumentLoadTiming.h"
#include "wtf/CurrentTime.h"
namespace blink {
IdleCallbackDeadline::IdleCallbackDeadline(double deadlineMillis, CallbackType callbackType, const DocumentLoadTiming& timing)
: m_deadlineMillis(deadlineMillis)
, m_callbackType(callbackType)
, m_timing(timing)
{
}
double IdleCallbackDeadline::timeRemaining() const
{
double timeRemaining = m_deadlineMillis - (1000 * m_timing.monotonicTimeToZeroBasedDocumentTime(monotonicallyIncreasingTime()));
if (timeRemaining < 0)
timeRemaining = 0;
return timeRemaining;
}
} // namespace blink
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IdleCallbackDeadline_h
#define IdleCallbackDeadline_h
#include "bindings/core/v8/ScriptWrappable.h"
#include "platform/heap/Handle.h"
namespace blink {
class DocumentLoadTiming;
class IdleCallbackDeadline : public GarbageCollected<IdleCallbackDeadline>, public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
enum class CallbackType {
CalledWhenIdle,
CalledByTimeout
};
DEFINE_INLINE_TRACE() {}
static IdleCallbackDeadline* create(double deadlineMillis, CallbackType callbackType, const DocumentLoadTiming& timing)
{
return new IdleCallbackDeadline(deadlineMillis, callbackType, timing);
}
double timeRemaining() const;
bool didTimeout() const
{
return m_callbackType == CallbackType::CalledByTimeout;
}
private:
IdleCallbackDeadline(double deadlineMillis, CallbackType, const DocumentLoadTiming&);
double m_deadlineMillis;
CallbackType m_callbackType;
const DocumentLoadTiming& m_timing;
};
}
#endif // IdleCallbackDeadline_h
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
GarbageCollected,
RuntimeEnabled=RequestIdleCallback,
] interface IdleCallbackDeadline {
readonly attribute double timeRemaining;
readonly attribute boolean didTimeout;
};
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IdleRequestCallback_h
#define IdleRequestCallback_h
#include "core/dom/ScriptedIdleTaskController.h"
#include "platform/Timer.h"
#include "platform/heap/Handle.h"
namespace blink {
class IdleCallbackDeadline;
class IdleRequestCallback : public GarbageCollectedFinalized<IdleRequestCallback> {
public:
DEFINE_INLINE_VIRTUAL_TRACE() {}
virtual ~IdleRequestCallback() {}
virtual void handleEvent(IdleCallbackDeadline*) = 0;
};
}
#endif // IdleRequestCallback_h
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
GarbageCollected,
RuntimeEnabled=RequestIdleCallback,
] callback interface IdleRequestCallback {
void handleEvent(IdleCallbackDeadline deadline);
};
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/dom/ScriptedIdleTaskController.h"
#include "core/dom/ExecutionContext.h"
#include "core/dom/IdleRequestCallback.h"
#include "core/loader/DocumentLoadTiming.h"
#include "platform/Logging.h"
#include "platform/TraceEvent.h"
#include "public/platform/Platform.h"
#include "public/platform/WebScheduler.h"
#include "public/platform/WebTraceLocation.h"
#include "wtf/CurrentTime.h"
#include "wtf/Functional.h"
namespace blink {
namespace internal {
class IdleRequestCallbackWrapper : public RefCounted<IdleRequestCallbackWrapper> {
public:
static PassRefPtr<IdleRequestCallbackWrapper> create(ScriptedIdleTaskController::CallbackId id, PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller)
{
return adoptRef(new IdleRequestCallbackWrapper(id, controller));
}
virtual ~IdleRequestCallbackWrapper()
{
}
static void idleTaskFired(PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper, double deadlineSeconds)
{
// TODO(rmcilroy): Implement clamping of deadline in some form.
callbackWrapper->controller()->callbackFired(callbackWrapper->id(), deadlineSeconds, IdleCallbackDeadline::CallbackType::CalledWhenIdle);
}
static void timeoutFired(PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper)
{
callbackWrapper->controller()->callbackFired(callbackWrapper->id(), monotonicallyIncreasingTime(), IdleCallbackDeadline::CallbackType::CalledByTimeout);
}
ScriptedIdleTaskController::CallbackId id() const { return m_id; }
PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller() const { return m_controller; }
private:
explicit IdleRequestCallbackWrapper(ScriptedIdleTaskController::CallbackId id, PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller)
: m_id(id)
, m_controller(controller)
{
}
ScriptedIdleTaskController::CallbackId m_id;
RefPtrWillBePersistent<ScriptedIdleTaskController> m_controller;
};
} // namespace internal
ScriptedIdleTaskController::ScriptedIdleTaskController(ExecutionContext* context, const DocumentLoadTiming& timing)
: ActiveDOMObject(context)
, m_timing(timing)
, m_scheduler(Platform::current()->currentThread()->scheduler())
, m_nextCallbackId(0)
, m_suspended(false)
{
suspendIfNeeded();
}
DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptedIdleTaskController);
DEFINE_TRACE(ScriptedIdleTaskController)
{
ActiveDOMObject::trace(visitor);
visitor->trace(m_callbacks);
}
ScriptedIdleTaskController::CallbackId ScriptedIdleTaskController::registerCallback(IdleRequestCallback* callback, double timeoutMillis)
{
CallbackId id = ++m_nextCallbackId;
m_callbacks.set(id, callback);
RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = internal::IdleRequestCallbackWrapper::create(id, this);
m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&internal::IdleRequestCallbackWrapper::idleTaskFired, callbackWrapper));
if (timeoutMillis > 0)
m_scheduler->postTimerTask(FROM_HERE, WTF::bind(&internal::IdleRequestCallbackWrapper::timeoutFired, callbackWrapper), static_cast<long long>(timeoutMillis));
// TODO(rmcilroy): Add devtools tracing.
return id;
}
void ScriptedIdleTaskController::cancelCallback(CallbackId id)
{
// TODO(rmcilroy): Add devtools tracing.
m_callbacks.remove(id);
}
void ScriptedIdleTaskController::callbackFired(CallbackId id, double deadlineSeconds, IdleCallbackDeadline::CallbackType callbackType)
{
if (!m_callbacks.contains(id))
return;
if (m_suspended) {
if (callbackType == IdleCallbackDeadline::CallbackType::CalledByTimeout) {
// Queue for execution when we are resumed.
m_pendingTimeouts.append(id);
}
// Just drop callbacks called while suspended, these will be reposted on the idle task queue when we are resumed.
return;
}
double deadlineMillis = 1000.0 * m_timing.monotonicTimeToZeroBasedDocumentTime(deadlineSeconds);
runCallback(id, deadlineMillis, callbackType);
}
void ScriptedIdleTaskController::runCallback(CallbackId id, double deadlineMillis, IdleCallbackDeadline::CallbackType callbackType)
{
ASSERT(!m_suspended);
auto callback = m_callbacks.take(id);
if (!callback)
return;
// TODO(rmcilroy): Add devtools tracing.
callback->handleEvent(IdleCallbackDeadline::create(deadlineMillis, callbackType, m_timing));
}
void ScriptedIdleTaskController::stop()
{
m_callbacks.clear();
}
void ScriptedIdleTaskController::suspend()
{
m_suspended = true;
}
void ScriptedIdleTaskController::resume()
{
ASSERT(m_suspended);
m_suspended = false;
// Run any pending timeouts.
Vector<CallbackId> pendingTimeouts;
m_pendingTimeouts.swap(pendingTimeouts);
for (auto& id : pendingTimeouts)
runCallback(id, monotonicallyIncreasingTime(), IdleCallbackDeadline::CallbackType::CalledByTimeout);
// Repost idle tasks for any remaining callbacks.
for (auto& callback : m_callbacks) {
RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = internal::IdleRequestCallbackWrapper::create(callback.key, this);
m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&internal::IdleRequestCallbackWrapper::idleTaskFired, callbackWrapper));
}
}
bool ScriptedIdleTaskController::hasPendingActivity() const
{
return !m_callbacks.isEmpty();
}
} // namespace blink
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ScriptedIdleTaskController_h
#define ScriptedIdleTaskController_h
#include "core/dom/ActiveDOMObject.h"
#include "core/dom/IdleCallbackDeadline.h"
#include "platform/Timer.h"
#include "platform/heap/Handle.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
namespace blink {
class ExecutionContext;
class IdleRequestCallback;
class DocumentLoadTiming;
class ScriptedIdleTaskController : public RefCountedWillBeGarbageCollected<ScriptedIdleTaskController>, public ActiveDOMObject {
DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptedIdleTaskController);
public:
static PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> create(ExecutionContext* context, const DocumentLoadTiming& timing)
{
return adoptRefWillBeNoop(new ScriptedIdleTaskController(context, timing));
}
DECLARE_TRACE();
using CallbackId = int;
int registerCallback(IdleRequestCallback*, double timeoutMillis);
void cancelCallback(CallbackId);
// ActiveDOMObject interface.
void stop() override;
void suspend() override;
void resume() override;
bool hasPendingActivity() const override;
void callbackFired(CallbackId, double deadlineSeconds, IdleCallbackDeadline::CallbackType);
private:
ScriptedIdleTaskController(ExecutionContext*, const DocumentLoadTiming&);
void runCallback(CallbackId, double deadlineMillis, IdleCallbackDeadline::CallbackType);
const DocumentLoadTiming& m_timing;
WebScheduler* m_scheduler; // Not owned.
PersistentHeapHashMapWillBeHeapHashMap<CallbackId, Member<IdleRequestCallback>> m_callbacks;
Vector<CallbackId> m_pendingTimeouts;
CallbackId m_nextCallbackId;
bool m_suspended;
};
} // namespace blink
#endif // ScriptedIdleTaskController_h
......@@ -28,6 +28,7 @@ class Element;
class Frame;
class FrameRequestCallback;
class History;
class IdleRequestCallback;
class LocalDOMWindow;
class MediaQueryList;
class Navigator;
......@@ -168,6 +169,10 @@ public:
virtual int webkitRequestAnimationFrame(FrameRequestCallback*) = 0;
virtual void cancelAnimationFrame(int id) = 0;
// Idle callback extensions
virtual int requestIdleCallback(IdleRequestCallback*, double timeoutMillis) = 0;
virtual void cancelIdleCallback(int id) = 0;
void captureEvents() { }
void releaseEvents() { }
......
......@@ -1264,23 +1264,36 @@ void LocalDOMWindow::resizeTo(int width, int height) const
int LocalDOMWindow::requestAnimationFrame(FrameRequestCallback* callback)
{
callback->m_useLegacyTimeBase = false;
if (Document* d = document())
return d->requestAnimationFrame(callback);
if (Document* doc = document())
return doc->requestAnimationFrame(callback);
return 0;
}
int LocalDOMWindow::webkitRequestAnimationFrame(FrameRequestCallback* callback)
{
callback->m_useLegacyTimeBase = true;
if (Document* d = document())
return d->requestAnimationFrame(callback);
if (Document* document = this->document())
return document->requestAnimationFrame(callback);
return 0;
}
void LocalDOMWindow::cancelAnimationFrame(int id)
{
if (Document* d = document())
d->cancelAnimationFrame(id);
if (Document* document = this->document())
document->cancelAnimationFrame(id);
}
int LocalDOMWindow::requestIdleCallback(IdleRequestCallback* callback, double timeoutMillis)
{
if (Document* document = this->document())
return document->requestIdleCallback(callback, timeoutMillis);
return 0;
}
void LocalDOMWindow::cancelIdleCallback(int id)
{
if (Document* document = this->document())
document->cancelIdleCallback(id);
}
bool LocalDOMWindow::addEventListener(const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> prpListener, bool useCapture)
......
......@@ -144,6 +144,8 @@ public:
int requestAnimationFrame(FrameRequestCallback*) override;
int webkitRequestAnimationFrame(FrameRequestCallback*) override;
void cancelAnimationFrame(int id) override;
int requestIdleCallback(IdleRequestCallback*, double timeoutMillis) override;
void cancelIdleCallback(int id) override;
void schedulePostMessage(PassRefPtrWillBeRawPtr<MessageEvent>, LocalDOMWindow* source, SecurityOrigin* target, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace);
void registerProperty(DOMWindowProperty*);
......
......@@ -328,6 +328,17 @@ void RemoteDOMWindow::cancelAnimationFrame(int id)
ASSERT_NOT_REACHED();
}
int RemoteDOMWindow::requestIdleCallback(IdleRequestCallback*, double timeoutMillis)
{
ASSERT_NOT_REACHED();
return 0;
}
void RemoteDOMWindow::cancelIdleCallback(int id)
{
ASSERT_NOT_REACHED();
}
RemoteDOMWindow::RemoteDOMWindow(RemoteFrame& frame)
: m_frame(&frame)
{
......
......@@ -77,6 +77,8 @@ public:
int requestAnimationFrame(FrameRequestCallback*) override;
int webkitRequestAnimationFrame(FrameRequestCallback*) override;
void cancelAnimationFrame(int id) override;
int requestIdleCallback(IdleRequestCallback*, double timeoutMillis) override;
void cancelIdleCallback(int id) override;
private:
explicit RemoteDOMWindow(RemoteFrame&);
......
......@@ -83,6 +83,9 @@
[MeasureAs=UnprefixedRequestAnimationFrame] long requestAnimationFrame(FrameRequestCallback callback);
void cancelAnimationFrame(long handle);
[RuntimeEnabled=RequestIdleCallback] long requestIdleCallback(IdleRequestCallback callback, optional double timeout = 0);
[RuntimeEnabled=RequestIdleCallback] void cancelIdleCallback(long handle);
[DoNotCheckSecurity, Custom, RaisesException] void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
// HTML obsolete features
......
......@@ -132,6 +132,7 @@ PushMessaging status=stable
PushMessagingData status=test
QuotaPromise status=experimental
ReducedReferrerGranularity
RequestIdleCallback status=experimental
RequestAutocomplete status=test
RestrictIFramePermissions
SandboxBlocksModals status=stable
......
......@@ -59,4 +59,9 @@ void WebScheduler::postLoadingTask(const WebTraceLocation& location, PassOwnPtr<
postLoadingTask(location, new blink::Task(task));
}
void WebScheduler::postTimerTask(const WebTraceLocation& location, PassOwnPtr<Task> task, long long delayMs)
{
postTimerTask(location, new blink::Task(task), delayMs);
}
} // namespace blink
......@@ -92,6 +92,7 @@ public:
void postNonNestableIdleTask(const WebTraceLocation&, PassOwnPtr<IdleTask>);
void postIdleTaskAfterWakeup(const WebTraceLocation&, PassOwnPtr<IdleTask>);
void postLoadingTask(const WebTraceLocation&, PassOwnPtr<Task>);
void postTimerTask(const WebTraceLocation&, PassOwnPtr<Task>, long long delayMs);
#endif
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment