Bug 647518 part 2. Allow canceling requestAnimationFrame requests. r=roc
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1526,16 +1526,17 @@ public:
* elements set using mozSetImageElement have higher priority.
* @param aId the ID associated the element we want to lookup
* @return the element associated with |aId|
*/
virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
nsresult ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback,
PRInt32 *aHandle);
+ void CancelFrameRequestCallback(PRInt32 aHandle);
typedef nsTArray< nsCOMPtr<nsIFrameRequestCallback> > FrameRequestCallbackList;
/**
* Put this document's frame request callbacks into the provided
* list, and forget about them.
*/
void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks);
@@ -1827,16 +1828,25 @@ protected:
PRInt32 aHandle) :
mCallback(aCallback),
mHandle(aHandle)
{}
// Conversion operator so that we can append these to a
// FrameRequestCallbackList
operator nsIFrameRequestCallback* const () const { return mCallback; }
+
+ // Comparator operators to allow RemoveElementSorted with an
+ // integer argument on arrays of FrameRequest
+ bool operator==(PRInt32 aHandle) const {
+ return mHandle == aHandle;
+ }
+ bool operator<(PRInt32 aHandle) const {
+ return mHandle < aHandle;
+ }
nsCOMPtr<nsIFrameRequestCallback> mCallback;
PRInt32 mHandle;
};
nsTArray<FrameRequest> mFrameRequestCallbacks;
// This object allows us to evict ourself from the back/forward cache. The
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8059,16 +8059,27 @@ nsIDocument::ScheduleFrameRequestCallbac
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleFrameRequestCallbacks(this);
}
*aHandle = newHandle;
return NS_OK;
}
+void
+nsIDocument::CancelFrameRequestCallback(PRInt32 aHandle)
+{
+ // mFrameRequestCallbacks is stored sorted by handle
+ mFrameRequestCallbacks.RemoveElementSorted(aHandle);
+
+ // Not going to worry about unscheduling our refresh driver
+ // callback. It'll just be a no-op when it happens, if we have no
+ // more frame request callbacks.
+}
+
nsresult
nsDocument::GetStateObject(nsIVariant** aState)
{
// Get the document's current state object. This is the object backing both
// history.state and popStateEvent.state.
//
// mStateObjectContainer may be null; this just means that there's no
// current state object.
--- a/content/base/test/test_bug647518.html
+++ b/content/base/test/test_bug647518.html
@@ -13,15 +13,33 @@ https://bugzilla.mozilla.org/show_bug.cg
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 647518 **/
-var handle1 = window.mozRequestAnimationFrame(function() {});
+SimpleTest.waitForExplicitFinish();
+var counter = 3;
+
+var called = false;
+var handle1 = window.mozRequestAnimationFrame(function() {
+ called = true;
+});
ok(handle1 > 0, "Should get back a nonzero handle");
+function checker() {
+ --counter;
+ if (counter == 0) {
+ is(called, false, "Canceled callback should not have been called");
+ SimpleTest.finish();
+ } else {
+ window.mozRequestAnimationFrame(checker);
+ }
+}
+window.mozRequestAnimationFrame(checker);
+window.mozCancelRequestAnimationFrame(handle1);
+
</script>
</pre>
</body>
</html>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3887,16 +3887,30 @@ nsGlobalWindow::MozRequestAnimationFrame
if (!aCallback) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
return mDoc->ScheduleFrameRequestCallback(aCallback, aHandle);
}
NS_IMETHODIMP
+nsGlobalWindow::MozCancelRequestAnimationFrame(PRInt32 aHandle)
+{
+ FORWARD_TO_INNER(MozCancelRequestAnimationFrame, (aHandle),
+ NS_ERROR_NOT_INITIALIZED);
+
+ if (!mDoc) {
+ return NS_OK;
+ }
+
+ mDoc->CancelFrameRequestCallback(aHandle);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsGlobalWindow::GetMozAnimationStartTime(PRInt64 *aTime)
{
FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
if (mDoc) {
nsIPresShell* presShell = mDoc->GetShell();
if (presShell) {
*aTime = presShell->GetPresContext()->RefreshDriver()->
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -65,17 +65,17 @@ interface nsIDOMMozURLProperty : nsISupp
* The nsIDOMWindow interface is the primary interface for a DOM
* window object. It represents a single window object that may
* contain child windows if the document in the window contains a
* HTML frameset document or if the document contains iframe elements.
*
* @see <http://www.whatwg.org/html/#window>
*/
-[scriptable, uuid(57b7ed24-c340-4994-a023-56ba578b78ab)]
+[scriptable, uuid(973e7219-40d5-4f94-b78d-53c2a0b8a13c)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
readonly attribute nsIDOMWindow window;
/* [replaceable] self */
readonly attribute nsIDOMWindow self;
@@ -416,16 +416,21 @@ interface nsIDOMWindow : nsISupports
* Request a refresh of this browser window.
*
* @see <http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>
*/
long
mozRequestAnimationFrame(in nsIFrameRequestCallback aCallback);
/**
+ * Cancel a refresh callback.
+ */
+ void mozCancelRequestAnimationFrame(in long aHandle);
+
+ /**
* The current animation start time in milliseconds since the epoch.
*/
readonly attribute long long mozAnimationStartTime;
/**
* @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
*/
readonly attribute nsIDOMMozURLProperty URL;