Animations and Transitions should not start when globally suspended
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 May 2013 04:43:05 +0000 (04:43 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 May 2013 04:43:05 +0000 (04:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=114915

Reviewed by Sam Weinig.

.:

Export AnimationController::isSuspended().

* Source/autotools/symbols.filter:

Source/WebCore:

When the Document's AnimationController was suspended, we still
started new transitions and animations. Change this so that
animations enter a paused-but-new state, where they are frozen
until the AnimationController resumes. At that time, it is as
if they had just appeared: any delay counts down before
the animation starts.

For transitions, the change in value must still happen, but
it does so immediately. No transitionend event should be fired.
This produces a slightly confusing behaviour, because any
in-progress transitions are suspended, but any new style changes
happen instantly. This might sound contradictory, but in general
suspending the document is a rare (and dangerous) thing to do.

Previously, the Document would call resumeAnimations as it loaded,
effectively starting all the animations. This meant if you suspended
animations before loading a document, it was ignored as soon as the
load finished. Now there is a separate method startAnimationsIfNotSuspended
which checks to see if the document is suspended as it loads.

In order to handle this case, I added a new state to the Animation
machinery: AnimationStatePausedNew. This is an animation that was created
in the suspended state.

Tests: animations/added-while-suspended.html
       transitions/started-while-suspended.html

* WebCore.exp.in: Export AnimationController::isSuspended().

* dom/Document.cpp:
(WebCore::Document::implicitClose):
    resumeAnimationsForDocument() -> startAnimationsIfNotSuspended()

* page/animation/AnimationBase.cpp:
(WebCore::nameForState): New name for AnimationStatePausedNew.
(WebCore::AnimationBase::updateStateMachine): Handle new state AnimationStatePausedNew. The
    most important change is that when go from PausedNew to Running, we jump back into
    the New state and continue from there.
(WebCore::AnimationBase::updatePlayState): suspended -> isSuspended
* page/animation/AnimationBase.h: New state: AnimationStatePausedNew
(WebCore::AnimationBase::waitingToStart): Add AnimationStatePausedNew.
(WebCore::AnimationBase::paused): Add AnimationStatePausedNew.
(WebCore::AnimationBase::isNew): Add AnimationStatePausedNew.

* page/animation/AnimationController.cpp:
(WebCore::AnimationControllerPrivate::AnimationControllerPrivate): Initialise m_suspended.
(WebCore::AnimationControllerPrivate::clear): suspended -> isSuspended
(WebCore::AnimationControllerPrivate::updateAnimations): Ditto.
(WebCore::AnimationControllerPrivate::updateAnimationTimerForRenderer): Ditto.
(WebCore::AnimationControllerPrivate::suspendAnimations): Update m_suspended.
(WebCore::AnimationControllerPrivate::resumeAnimations): Ditto.
(WebCore::AnimationControllerPrivate::suspendAnimationsForDocument):
(WebCore::AnimationControllerPrivate::resumeAnimationsForDocument):
(WebCore::AnimationControllerPrivate::startAnimationsIfNotSuspended): New method that will
    only resume animations if we were not globally suspended.
(WebCore::AnimationController::isSuspended): New method.
(WebCore::AnimationController::suspendAnimations): Add logging.
(WebCore::AnimationController::resumeAnimations): Add logging.
(WebCore::AnimationController::suspendAnimationsForDocument): Add logging.
(WebCore::AnimationController::resumeAnimationsForDocument): Add logging.
(WebCore::AnimationController::startAnimationsIfNotSuspended): Calls private method.
* page/animation/AnimationController.h:
(AnimationController): Add isSuspended() and animationsForDocumentMayStart().
* page/animation/AnimationControllerPrivate.h:
(WebCore::AnimationControllerPrivate::isSuspended): New method.
(AnimationControllerPrivate): Add m_isSuspended member.

* page/animation/CompositeAnimation.cpp:
(WebCore::CompositeAnimation::CompositeAnimation): Moved from header - initialise m_isSuspended.
(WebCore::CompositeAnimation::updateTransitions): Do not create ImplicitAnimation if suspended.
(WebCore::CompositeAnimation::updateKeyframeAnimations): Move to AnimationStatePausedNew if suspended.
(WebCore::CompositeAnimation::suspendAnimations): m_suspended -> m_isSuspended
(WebCore::CompositeAnimation::resumeAnimations): Ditto.
* page/animation/CompositeAnimation.h:
(WebCore::CompositeAnimation::isSuspended): Renamed from suspended()

* page/animation/KeyframeAnimation.cpp:
(WebCore::KeyframeAnimation::animate): If we're in the AnimationStatePausedNew state, then
    we need to go to the first frame (to handle fill mode).

* testing/Internals.cpp:
(WebCore::Internals::animationsAreSuspended): New exposed method to reflect AnimationController.
* testing/Internals.h: Add animationsAreSuspended.
* testing/Internals.idl: Ditto.

Source/WebKit:

Export AnimationController::isSuspended

* WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in:

Source/WebKit/mac:

The WebView private API cssAnimationsSuspended did not necessarily
reflect the reality of the Frame's AnimationController value because it
was caching rather than asking directly. While the WebCore part of this
patch ensured loading the Document wouldn't resume all animations, it
is still better to ask directly.

* WebView/WebView.mm:
(-[WebView cssAnimationsSuspended]): Call into AnimationController.
(-[WebView setCSSAnimationsSuspended:]): Ditto.
* WebView/WebViewData.h: Remove cssAnimationsSuspended boolean.
* WebView/WebViewData.mm: Ditto.
(-[WebViewPrivate init]):

Source/WebKit/win:

Export AnimationController::isSuspended

* WebKit.vcproj/WebKitExports.def.in:

LayoutTests:

Two new tests. Add an animation or transition to
the document when the global animation controller is suspended.
In the animation case, nothing should happen until the
animations are resumed. In the transition case, the style
change should happen immediately and not fire any events.

* animations/added-while-suspended-expected.txt: Added.
* animations/added-while-suspended.html: Added.
* animations/suspend-transform-animation.html: Make sure to resume suspended animations
    before quitting the test.
* transitions/started-while-suspended-expected.txt: Added.
* transitions/started-while-suspended.html: Added.
* transitions/suspend-transform-transition.html: Make sure to resume suspended animations
    before quitting the test.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@149576 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
ChangeLog
LayoutTests/ChangeLog
LayoutTests/animations/added-while-suspended-expected.txt [new file with mode: 0644]
LayoutTests/animations/added-while-suspended.html [new file with mode: 0644]
LayoutTests/animations/suspend-transform-animation.html
LayoutTests/transitions/started-while-suspended-expected.txt [new file with mode: 0644]
LayoutTests/transitions/started-while-suspended.html [new file with mode: 0644]
LayoutTests/transitions/suspend-transform-transition.html
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/dom/Document.cpp
Source/WebCore/page/animation/AnimationBase.cpp
Source/WebCore/page/animation/AnimationBase.h
Source/WebCore/page/animation/AnimationController.cpp
Source/WebCore/page/animation/AnimationController.h
Source/WebCore/page/animation/AnimationControllerPrivate.h
Source/WebCore/page/animation/CompositeAnimation.cpp
Source/WebCore/page/animation/CompositeAnimation.h
Source/WebCore/page/animation/KeyframeAnimation.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/ChangeLog
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebView.mm
Source/WebKit/mac/WebView/WebViewData.h
Source/WebKit/mac/WebView/WebViewData.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebKit.vcproj/WebKitExports.def.in
Source/autotools/symbols.filter

index 999d90fbd932682f251487bbc56cbf861bea46db..93e20ab616e311b2d74dddc04cb1a060860beef8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-04-30  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        Export AnimationController::isSuspended().
+
+        * Source/autotools/symbols.filter:
+
 2013-05-01  Benjamin Poulain  <benjamin@webkit.org>
 
         Remove the remaining wscript
index f1af78fa9cae2aeeaa6b842aefba7c46b22d90b9..759d0dcf44688b4b40f4fb01c3c08075db104143 100644 (file)
@@ -1,3 +1,25 @@
+2013-04-30  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        Two new tests. Add an animation or transition to
+        the document when the global animation controller is suspended.
+        In the animation case, nothing should happen until the
+        animations are resumed. In the transition case, the style
+        change should happen immediately and not fire any events.
+
+        * animations/added-while-suspended-expected.txt: Added.
+        * animations/added-while-suspended.html: Added.
+        * animations/suspend-transform-animation.html: Make sure to resume suspended animations
+            before quitting the test.
+        * transitions/started-while-suspended-expected.txt: Added.
+        * transitions/started-while-suspended.html: Added.
+        * transitions/suspend-transform-transition.html: Make sure to resume suspended animations
+            before quitting the test.
+
 2013-04-30  Robert Hogan  <robert@webkit.org>
 
         REGRESSION(r140907): Incorrect baseline on cells after updating vertical-align
diff --git a/LayoutTests/animations/added-while-suspended-expected.txt b/LayoutTests/animations/added-while-suspended-expected.txt
new file mode 100644 (file)
index 0000000..6b01baa
--- /dev/null
@@ -0,0 +1,15 @@
+This test adds some elements to the document when animations should be paused. It will only have reproducible output when run in the test system
+
+Animations should not be suspended: PASS
+*** Suspending Animations
+Animations should be suspended: PASS
+*** Adding first box with animation
+*** Adding second box with animation and delay
+*** Resuming Animations
+Animation started on element with id: box
+Animation ended on element with id: box
+Animation started on element with id: box-with-delay
+Animation ended on element with id: box-with-delay
+Animations should not be suspended: PASS
+*** Animations finished
+
diff --git a/LayoutTests/animations/added-while-suspended.html b/LayoutTests/animations/added-while-suspended.html
new file mode 100644 (file)
index 0000000..de1c189
--- /dev/null
@@ -0,0 +1,127 @@
+<title>Test that new animations do not run while we are suspended</title>
+<style>
+#box {
+    position: relative;
+    height: 100px;
+    width: 100px;
+    background-color: blue;
+    -webkit-animation-name: move;
+    -webkit-animation-duration: 0.1s;
+}
+
+#box-with-delay {
+    position: relative;
+    height: 100px;
+    width: 100px;
+    background-color: blue;
+    -webkit-animation-name: move;
+    -webkit-animation-duration: 0.1s;
+    -webkit-animation-delay: 0.3s;
+}
+
+@-webkit-keyframes move {
+    from { left: 0; }
+    to { left: 500px; }
+}
+</style>
+<script>
+
+var animationsYetToEnd = 2;
+
+function suspend()
+{
+    if (window.internals)
+        internals.suspendAnimations(document);
+}
+
+function resume()
+{
+    if (window.internals)
+        internals.resumeAnimations(document);
+}
+
+function animationStarted(event)
+{
+    log("Animation started on element with id: " + event.target.id);
+}
+
+function animationEnded(event)
+{
+    log("Animation ended on element with id: " + event.target.id);
+    animationsYetToEnd--;
+    if (!animationsYetToEnd)
+        endTest();
+}
+
+function addDivWithId(id)
+{
+    var div = document.createElement("div");
+    div.id = id;
+    document.body.appendChild(div);
+}
+
+function addFirstBox()
+{
+    if (window.internals)
+        log("Animations should be suspended: " + (window.internals.animationsAreSuspended(document) ? "PASS" : "FAIL"));
+
+    log("*** Adding first box with animation");
+    addDivWithId("box");
+    setTimeout(addSecondBox, 100);
+}
+
+function addSecondBox()
+{
+    log("*** Adding second box with animation and delay");
+    addDivWithId("box-with-delay");
+    setTimeout(resumeAndContinue, 50);
+}
+
+function resumeAndContinue()
+{
+    log("*** Resuming Animations");
+    resume();
+}
+
+function endTest()
+{
+    if (window.internals)
+        log("Animations should not be suspended: " + (window.internals.animationsAreSuspended(document) ? "FAIL" : "PASS"));
+    log("*** Animations finished");
+    resume(); // Just in case.
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function startTest()
+{
+    document.addEventListener("webkitAnimationStart", animationStarted, false);
+    document.addEventListener("webkitAnimationEnd", animationEnded, false);
+
+    if (window.internals)
+        log("Animations should not be suspended: " + (window.internals.animationsAreSuspended(document) ? "FAIL" : "PASS"));
+
+    setTimeout(function() {
+        log("*** Suspending Animations");
+        suspend();
+        setTimeout(addFirstBox, 50);
+    }, 50);
+}
+
+function log(message)
+{
+    var results = document.getElementById("results");
+    results.innerHTML = results.innerHTML + message + "<br>";
+}
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+window.addEventListener("load", startTest, false);
+
+</script>
+<p>This test adds some elements to the document when animations should be paused. It will only have reproducible output when run in the test system</p>
+<div id="results">
+</div>
index c5b3f72c25ae069779b7b68155544649134601eb..46c6f71019fcaa22ed4b1ea7315f8545af535dd7 100644 (file)
             internals.suspendAnimations(document);
 
         window.setTimeout(function() {
-            if (window.testRunner)
+            if (window.testRunner) {
+                internals.resumeAnimations(document);
                 testRunner.notifyDone();
+            }
         }, 250);
     }
     
diff --git a/LayoutTests/transitions/started-while-suspended-expected.txt b/LayoutTests/transitions/started-while-suspended-expected.txt
new file mode 100644 (file)
index 0000000..bd8a6bf
--- /dev/null
@@ -0,0 +1,13 @@
+This test sets the left property on the box below. It will only have reproducible output when run in the test system
+
+*** Starting test.
+Transitions should not be suspended: PASS
+*** Setting left property to 100px. We should see transition events.
+Transition ended on element with id: box
+*** Suspending Animations/Transitions
+Transitions should be suspended: PASS
+*** Setting left property to 200px. We should NOT see transition events.
+*** Resuming Animations/Transitions
+Transitions should not be suspended: PASS
+*** Test finished
+
diff --git a/LayoutTests/transitions/started-while-suspended.html b/LayoutTests/transitions/started-while-suspended.html
new file mode 100644 (file)
index 0000000..6145315
--- /dev/null
@@ -0,0 +1,100 @@
+<title>Test that new transitions do not run while we are suspended</title>
+<style>
+#box {
+    position: relative;
+    left: 0px;
+    height: 100px;
+    width: 100px;
+    background-color: blue;
+    -webkit-transition: left 0.1s;
+}
+</style>
+<script>
+var box;
+
+function suspend()
+{
+    if (window.internals)
+        internals.suspendAnimations(document);
+}
+
+function resume()
+{
+    if (window.internals)
+        internals.resumeAnimations(document);
+}
+
+function transitionEnded(event)
+{
+    log("Transition ended on element with id: " + event.target.id);
+}
+
+function suspendAndContinue()
+{
+    log("*** Suspending Animations/Transitions");
+    suspend();
+    setTimeout(function() {
+        if (window.internals)
+            log("Transitions should be suspended: " + (window.internals.animationsAreSuspended(document) ? "PASS" : "FAIL"));
+        log("*** Setting left property to 200px. We should NOT see transition events.")
+        box.style.left = "200px";
+        setTimeout(function() {
+            endTest();
+        }, 200);
+    }, 100);
+}
+
+function resumeAndContinue()
+{
+}
+
+function endTest()
+{
+    log("*** Resuming Animations/Transitions");
+    resume();
+    if (window.internals)
+        log("Transitions should not be suspended: " + (window.internals.animationsAreSuspended(document) ? "FAIL" : "PASS"));
+
+    resume(); // Just in case.
+    log("*** Test finished");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function startTest()
+{
+    log("*** Starting test.")
+
+    box = document.getElementById("box");
+    document.addEventListener("webkitTransitionEnd", transitionEnded, false);
+
+    if (window.internals)
+        log("Transitions should not be suspended: " + (window.internals.animationsAreSuspended(document) ? "FAIL" : "PASS"));
+
+    setTimeout(function() {
+        log("*** Setting left property to 100px. We should see transition events.")
+        box.style.left = "100px";
+        setTimeout(function() {
+            suspendAndContinue();
+        }, 200);
+    }, 50);
+}
+
+function log(message)
+{
+    var results = document.getElementById("results");
+    results.innerHTML = results.innerHTML + message + "<br>";
+}
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+window.addEventListener("load", startTest, false);
+
+</script>
+<p>This test sets the left property on the box below. It will only have reproducible output when run in the test system</p>
+<div id="box"></div>
+<div id="results">
+</div>
index 208a95c65a89e09903435f8a92a2ee61860c317e..9d75a2c26d787d14b8403dcd1ebdbf43ff98ad31 100644 (file)
             internals.suspendAnimations(document);
 
         window.setTimeout(function() {
-            if (window.testRunner)
+            if (window.testRunner) {
+                internals.resumeAnimations(document);
                 testRunner.notifyDone();
+            }
         }, 250);
     }
     
index b63a2d159f03ac5454bb13afbcb47c41f92cc705..e1c5e2a66619b7d3f64adfb36f80ecc804d36a9f 100644 (file)
@@ -1,3 +1,95 @@
+2013-04-30  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        When the Document's AnimationController was suspended, we still
+        started new transitions and animations. Change this so that
+        animations enter a paused-but-new state, where they are frozen
+        until the AnimationController resumes. At that time, it is as
+        if they had just appeared: any delay counts down before
+        the animation starts.
+
+        For transitions, the change in value must still happen, but
+        it does so immediately. No transitionend event should be fired.
+        This produces a slightly confusing behaviour, because any
+        in-progress transitions are suspended, but any new style changes
+        happen instantly. This might sound contradictory, but in general
+        suspending the document is a rare (and dangerous) thing to do.
+
+        Previously, the Document would call resumeAnimations as it loaded,
+        effectively starting all the animations. This meant if you suspended
+        animations before loading a document, it was ignored as soon as the
+        load finished. Now there is a separate method startAnimationsIfNotSuspended
+        which checks to see if the document is suspended as it loads.
+
+        In order to handle this case, I added a new state to the Animation
+        machinery: AnimationStatePausedNew. This is an animation that was created
+        in the suspended state.
+
+        Tests: animations/added-while-suspended.html
+               transitions/started-while-suspended.html
+
+        * WebCore.exp.in: Export AnimationController::isSuspended().
+
+        * dom/Document.cpp:
+        (WebCore::Document::implicitClose):
+            resumeAnimationsForDocument() -> startAnimationsIfNotSuspended()
+
+        * page/animation/AnimationBase.cpp:
+        (WebCore::nameForState): New name for AnimationStatePausedNew.
+        (WebCore::AnimationBase::updateStateMachine): Handle new state AnimationStatePausedNew. The
+            most important change is that when go from PausedNew to Running, we jump back into
+            the New state and continue from there.
+        (WebCore::AnimationBase::updatePlayState): suspended -> isSuspended
+        * page/animation/AnimationBase.h: New state: AnimationStatePausedNew
+        (WebCore::AnimationBase::waitingToStart): Add AnimationStatePausedNew.
+        (WebCore::AnimationBase::paused): Add AnimationStatePausedNew.
+        (WebCore::AnimationBase::isNew): Add AnimationStatePausedNew.
+
+        * page/animation/AnimationController.cpp:
+        (WebCore::AnimationControllerPrivate::AnimationControllerPrivate): Initialise m_suspended.
+        (WebCore::AnimationControllerPrivate::clear): suspended -> isSuspended
+        (WebCore::AnimationControllerPrivate::updateAnimations): Ditto.
+        (WebCore::AnimationControllerPrivate::updateAnimationTimerForRenderer): Ditto.
+        (WebCore::AnimationControllerPrivate::suspendAnimations): Update m_suspended.
+        (WebCore::AnimationControllerPrivate::resumeAnimations): Ditto.
+        (WebCore::AnimationControllerPrivate::suspendAnimationsForDocument):
+        (WebCore::AnimationControllerPrivate::resumeAnimationsForDocument):
+        (WebCore::AnimationControllerPrivate::startAnimationsIfNotSuspended): New method that will
+            only resume animations if we were not globally suspended.
+        (WebCore::AnimationController::isSuspended): New method.
+        (WebCore::AnimationController::suspendAnimations): Add logging.
+        (WebCore::AnimationController::resumeAnimations): Add logging.
+        (WebCore::AnimationController::suspendAnimationsForDocument): Add logging.
+        (WebCore::AnimationController::resumeAnimationsForDocument): Add logging.
+        (WebCore::AnimationController::startAnimationsIfNotSuspended): Calls private method.
+        * page/animation/AnimationController.h:
+        (AnimationController): Add isSuspended() and animationsForDocumentMayStart().
+        * page/animation/AnimationControllerPrivate.h:
+        (WebCore::AnimationControllerPrivate::isSuspended): New method.
+        (AnimationControllerPrivate): Add m_isSuspended member.
+
+        * page/animation/CompositeAnimation.cpp:
+        (WebCore::CompositeAnimation::CompositeAnimation): Moved from header - initialise m_isSuspended.
+        (WebCore::CompositeAnimation::updateTransitions): Do not create ImplicitAnimation if suspended.
+        (WebCore::CompositeAnimation::updateKeyframeAnimations): Move to AnimationStatePausedNew if suspended.
+        (WebCore::CompositeAnimation::suspendAnimations): m_suspended -> m_isSuspended
+        (WebCore::CompositeAnimation::resumeAnimations): Ditto.
+        * page/animation/CompositeAnimation.h:
+        (WebCore::CompositeAnimation::isSuspended): Renamed from suspended()
+
+        * page/animation/KeyframeAnimation.cpp:
+        (WebCore::KeyframeAnimation::animate): If we're in the AnimationStatePausedNew state, then
+            we need to go to the first frame (to handle fill mode).
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::animationsAreSuspended): New exposed method to reflect AnimationController.
+        * testing/Internals.h: Add animationsAreSuspended.
+        * testing/Internals.idl: Ditto.
+
 2013-05-04  Sam Weinig  <sam@webkit.org>
 
         Move PopupMenuMac and SearchPopupMenuMac to Source/WebKit/mac
index b7f63fd6790236b088fb92fcea7210f50fea0f62..d401501b5d2af577bbe7f877fdb436de908c118b 100644 (file)
@@ -602,6 +602,7 @@ __ZN7WebCore18isStartOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCros
 __ZN7WebCore18makeAllDirectoriesERKN3WTF6StringE
 __ZN7WebCore18pluginScriptObjectEPN3JSC9ExecStateEPNS_13JSHTMLElementE
 __ZN7WebCore18proxyServersForURLERKNS_4KURLEPKNS_17NetworkingContextE
+__ZNK7WebCore19AnimationController11isSuspendedEv
 __ZN7WebCore19AnimationController16resumeAnimationsEv
 __ZN7WebCore19AnimationController17suspendAnimationsEv
 __ZN7WebCore19AnimationController20pauseAnimationAtTimeEPNS_12RenderObjectERKN3WTF12AtomicStringEd
index 1d6df8538f42f12ace27df488bd01d57e4cb4a7e..c23d3e8ee8e39b3c2bf1f0d379bc36ccb9994871 100644 (file)
@@ -2396,7 +2396,7 @@ void Document::implicitClose()
     Frame* f = frame();
     if (f) {
         f->loader()->icon()->startLoader();
-        f->animation()->resumeAnimationsForDocument(this);
+        f->animation()->startAnimationsIfNotSuspended(this);
     }
 
     ImageLoader::dispatchPendingBeforeLoadEvents();
index 796e7c75b1b1f84689dd9710392773c748f4bea9..8da678b492a6004af419b7ce49aa13394c9c1e74 100644 (file)
@@ -122,6 +122,7 @@ static const char* nameForState(AnimationBase::AnimState state)
     case AnimationBase::AnimationStateStartWaitResponse: return "StartWaitResponse";
     case AnimationBase::AnimationStateLooping: return "Looping";
     case AnimationBase::AnimationStateEnding: return "Ending";
+    case AnimationBase::AnimationStatePausedNew: return "PausedNew";
     case AnimationBase::AnimationStatePausedWaitTimer: return "PausedWaitTimer";
     case AnimationBase::AnimationStatePausedWaitStyleAvailable: return "PausedWaitStyleAvailable";
     case AnimationBase::AnimationStatePausedWaitResponse: return "PausedWaitResponse";
@@ -203,6 +204,10 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
                 m_requestedStartTime = beginAnimationUpdateTime();
                 LOG(Animations, "%p AnimationState %s -> StartWaitTimer", this, nameForState(m_animState));
                 m_animState = AnimationStateStartWaitTimer;
+            } else {
+                // We are pausing before we even started.
+                LOG(Animations, "%p AnimationState %s -> AnimationStatePausedNew", this, nameForState(m_animState));
+                m_animState = AnimationStatePausedNew;
             }
             break;
         case AnimationStateStartWaitTimer:
@@ -355,6 +360,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
             m_animState = AnimationStateNew;
             updateStateMachine(AnimationStateInputStartAnimation, 0);
             break;
+        case AnimationStatePausedNew:
         case AnimationStatePausedWaitResponse:
         case AnimationStatePausedWaitStyleAvailable:
         case AnimationStatePausedRun:
@@ -362,10 +368,19 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
             // AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation.
             // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice
             // that we have already set the startTime and will ignore it.
-            ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable);
+            ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable || input == AnimationStateInputStartAnimation);
             ASSERT(paused());
-            
+
             if (input == AnimationStateInputPlayStateRunning) {
+                if (m_animState == AnimationStatePausedNew) {
+                    // We were paused before we even started, and now we're supposed
+                    // to start, so jump back to the New state and reset.
+                    LOG(Animations, "%p AnimationState %s -> AnimationStateNew", this, nameForState(m_animState));
+                    m_animState = AnimationStateNew;
+                    updateStateMachine(input, param);
+                    break;
+                }
+
                 // Update the times
                 if (m_animState == AnimationStatePausedRun)
                     m_startTime += beginAnimationUpdateTime() - m_pauseTime;
@@ -410,7 +425,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
                 m_pauseTime += m_startTime;
                 break;
             }
-            
+
             ASSERT(m_animState == AnimationStatePausedWaitStyleAvailable);
             // We are paused but we got the callback that notifies us that style has been updated.
             // We move to the AnimationStatePausedWaitResponse state
@@ -491,11 +506,11 @@ void AnimationBase::updatePlayState(EAnimPlayState playState)
     // When we get here, we can have one of 4 desired states: running, paused, suspended, paused & suspended.
     // The state machine can be in one of two states: running, paused.
     // Set the state machine to the desired state.
-    bool pause = playState == AnimPlayStatePaused || m_compAnim->suspended();
-    
+    bool pause = playState == AnimPlayStatePaused || m_compAnim->isSuspended();
+
     if (pause == paused() && !isNew())
         return;
-    
+
     updateStateMachine(pause ?  AnimationStateInputPlayStatePaused : AnimationStateInputPlayStateRunning, -1);
 }
 
index 4a6b17dd010479e54d4eebcbb9673ab7bac4af3c..dee083603bff6beff6cefb06c8ce10d6ce09264c 100644 (file)
@@ -78,6 +78,7 @@ public:
         AnimationStateStartWaitResponse,    // animation started, waiting for response
         AnimationStateLooping,              // response received, animation running, loop timer running, waiting for fire
         AnimationStateEnding,               // received, animation running, end timer running, waiting for fire
+        AnimationStatePausedNew,            // in pause mode when animation was created
         AnimationStatePausedWaitTimer,      // in pause mode when animation started
         AnimationStatePausedWaitStyleAvailable, // in pause mode when waiting for style setup
         AnimationStatePausedWaitResponse,   // animation paused when in STARTING state
@@ -115,7 +116,7 @@ public:
     void updatePlayState(EAnimPlayState);
     bool playStatePlaying() const;
 
-    bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer; }
+    bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStatePausedNew; }
     bool preActive() const
     {
         return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStateStartWaitStyleAvailable || m_animState == AnimationStateStartWaitResponse;
@@ -124,8 +125,8 @@ public:
     bool postActive() const { return m_animState == AnimationStateDone; }
     bool active() const { return !postActive() && !preActive(); }
     bool running() const { return !isNew() && !postActive(); }
-    bool paused() const { return m_pauseTime >= 0; }
-    bool isNew() const { return m_animState == AnimationStateNew; }
+    bool paused() const { return m_pauseTime >= 0 || m_animState == AnimationStatePausedNew; }
+    bool isNew() const { return m_animState == AnimationStateNew || m_animState == AnimationStatePausedNew; }
     bool waitingForStartTime() const { return m_animState == AnimationStateStartWaitResponse; }
     bool waitingForStyleAvailable() const { return m_animState == AnimationStateStartWaitStyleAvailable; }
 
index 1c158701cb7210da982553bf331f62e406843b25..a484382322b96333dce2407175f09da82d5ce99b 100644 (file)
@@ -59,6 +59,7 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
     , m_animationsWaitingForStyle()
     , m_animationsWaitingForStartTimeResponse()
     , m_waitingForAsyncStartNotification(false)
+    , m_isSuspended(false)
 {
 }
 
@@ -84,7 +85,7 @@ bool AnimationControllerPrivate::clear(RenderObject* renderer)
     if (!animation)
         return false;
     animation->clearRenderer();
-    return animation->suspended();
+    return animation->isSuspended();
 }
 
 double AnimationControllerPrivate::updateAnimations(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
@@ -95,7 +96,7 @@ double AnimationControllerPrivate::updateAnimations(SetChanged callSetChanged/*
     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
         CompositeAnimation* compAnim = it->value.get();
-        if (!compAnim->suspended() && compAnim->hasAnimations()) {
+        if (!compAnim->isSuspended() && compAnim->hasAnimations()) {
             double t = compAnim->timeToNextService();
             if (t != -1 && (t < timeToNextService || timeToNextService == -1))
                 timeToNextService = t;
@@ -123,7 +124,7 @@ void AnimationControllerPrivate::updateAnimationTimerForRenderer(RenderObject* r
     double timeToNextService = 0;
 
     RefPtr<CompositeAnimation> compAnim = m_compositeAnimations.get(renderer);
-    if (!compAnim->suspended() && compAnim->hasAnimations())
+    if (!compAnim->isSuspended() && compAnim->hasAnimations())
         timeToNextService = compAnim->timeToNextService();
 
     if (m_animationTimer.isActive() && (m_animationTimer.repeatInterval() || m_animationTimer.nextFireInterval() <= timeToNextService))
@@ -264,26 +265,39 @@ bool AnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderO
 
 void AnimationControllerPrivate::suspendAnimations()
 {
+    if (isSuspended())
+        return;
+
     suspendAnimationsForDocument(m_frame->document());
-    
+
     // Traverse subframes
     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
         child->animation()->suspendAnimations();
+
+    m_isSuspended = true;
 }
 
 void AnimationControllerPrivate::resumeAnimations()
 {
+    if (!isSuspended())
+        return;
+
     resumeAnimationsForDocument(m_frame->document());
-    
+
     // Traverse subframes
     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
         child->animation()->resumeAnimations();
+
+    m_isSuspended = false;
 }
 
 void AnimationControllerPrivate::suspendAnimationsForDocument(Document* document)
 {
+    if (isSuspended())
+        return;
+
     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
-    
+
     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
         RenderObject* renderer = it->key;
@@ -292,14 +306,17 @@ void AnimationControllerPrivate::suspendAnimationsForDocument(Document* document
             compAnim->suspendAnimations();
         }
     }
-    
+
     updateAnimationTimer();
 }
 
 void AnimationControllerPrivate::resumeAnimationsForDocument(Document* document)
 {
+    if (!isSuspended())
+        return;
+
     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
-    
+
     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
         RenderObject* renderer = it->key;
@@ -308,10 +325,16 @@ void AnimationControllerPrivate::resumeAnimationsForDocument(Document* document)
             compAnim->resumeAnimations();
         }
     }
-    
+
     updateAnimationTimer();
 }
 
+void AnimationControllerPrivate::startAnimationsIfNotSuspended(Document* document)
+{
+    if (!isSuspended())
+        resumeAnimationsForDocument(document);
+}
+
 bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, const AtomicString& name, double t)
 {
     if (!renderer)
@@ -578,13 +601,20 @@ bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderObject*
     return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, isRunningNow);
 }
 
+bool AnimationController::isSuspended() const
+{
+    return m_data->isSuspended();
+}
+
 void AnimationController::suspendAnimations()
 {
+    LOG(Animations, "controller is suspending animations");
     m_data->suspendAnimations();
 }
 
 void AnimationController::resumeAnimations()
 {
+    LOG(Animations, "controller is resuming animations");
     m_data->resumeAnimations();
 }
 
@@ -597,14 +627,22 @@ void AnimationController::serviceAnimations()
 
 void AnimationController::suspendAnimationsForDocument(Document* document)
 {
+    LOG(Animations, "suspending animations for document %p", document);
     m_data->suspendAnimationsForDocument(document);
 }
 
 void AnimationController::resumeAnimationsForDocument(Document* document)
 {
+    LOG(Animations, "resuming animations for document %p", document);
     m_data->resumeAnimationsForDocument(document);
 }
 
+void AnimationController::startAnimationsIfNotSuspended(Document* document)
+{
+    LOG(Animations, "animations may start for document %p", document);
+    m_data->startAnimationsIfNotSuspended(document);
+}
+
 void AnimationController::beginAnimationUpdate()
 {
     if (!m_beginAnimationUpdateCount)
index 49d0854387a34fd4e80508dfb39ab0184ff8fb35..9a267d45b0bcd030fbc42a957989cf2f13fd5688 100644 (file)
@@ -63,6 +63,7 @@ public:
     bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const;
     bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const;
 
+    bool isSuspended() const;
     void suspendAnimations();
     void resumeAnimations();
 #if ENABLE(REQUEST_ANIMATION_FRAME)
@@ -71,6 +72,7 @@ public:
 
     void suspendAnimationsForDocument(Document*);
     void resumeAnimationsForDocument(Document*);
+    void startAnimationsIfNotSuspended(Document*);
 
     void beginAnimationUpdate();
     void endAnimationUpdate();
index 8a292f3699369180f46ab9a66ac4a2d97faf39d5..f0bea34421299ef8b10306f0161dea43552d1ba2 100644 (file)
@@ -75,6 +75,7 @@ public:
 
     bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); }
 
+    bool isSuspended() const { return m_isSuspended; }
     void suspendAnimations();
     void resumeAnimations();
 #if ENABLE(REQUEST_ANIMATION_FRAME)
@@ -83,6 +84,7 @@ public:
 
     void suspendAnimationsForDocument(Document*);
     void resumeAnimationsForDocument(Document*);
+    void startAnimationsIfNotSuspended(Document*);
 
     bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const;
     bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const;
@@ -139,6 +141,7 @@ private:
     WaitingAnimationsSet m_animationsWaitingForStyle;
     WaitingAnimationsSet m_animationsWaitingForStartTimeResponse;
     bool m_waitingForAsyncStartNotification;
+    bool m_isSuspended;
 };
 
 } // namespace WebCore
index 071dbcffd50c06081cc87932e4bba4e23b36b769..aeff0f00ded49bc621cd04b14f64182ccd3cafa6 100644 (file)
 
 namespace WebCore {
 
+CompositeAnimation::CompositeAnimation(AnimationControllerPrivate* animationController)
+    : m_animationController(animationController)
+{
+    m_suspended = animationController->isSuspended();
+}
+
 CompositeAnimation::~CompositeAnimation()
 {
     // Toss the refs to all animations, but make sure we remove them from
@@ -92,7 +98,7 @@ void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle*
     if (targetStyle->transitions()) {
         for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) {
             const Animation* anim = targetStyle->transitions()->animation(i);
-            bool isActiveTransition = anim->duration() || anim->delay() > 0;
+            bool isActiveTransition = !m_suspended && (anim->duration() || anim->delay() > 0);
 
             Animation::AnimationMode mode = anim->animationMode();
             if (mode == Animation::AnimateNone)
@@ -252,7 +258,11 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render
                     keyframeAnim->setIndex(i);
                 } else if ((anim->duration() || anim->delay()) && anim->iterationCount() && animationName != none) {
                     keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, targetStyle);
-                    LOG(Animations, "Creating KeyframeAnimation %p with keyframes %s duration %.2f delay %.2f, iterations %.2f", keyframeAnim.get(), anim->name().utf8().data(), anim->duration(), anim->delay(), anim->iterationCount());
+                    LOG(Animations, "Creating KeyframeAnimation %p with keyframes %s, duration %.2f, delay %.2f, iterations %.2f", keyframeAnim.get(), anim->name().utf8().data(), anim->duration(), anim->delay(), anim->iterationCount());
+                    if (m_suspended) {
+                        keyframeAnim->updatePlayState(AnimPlayStatePaused);
+                        LOG(Animations, "  (created in suspended/paused state)");
+                    }
 #if !LOG_DISABLED
                     HashSet<CSSPropertyID>::const_iterator endProperties = keyframeAnim->keyframes().endProperties();
                     for (HashSet<CSSPropertyID>::const_iterator it = keyframeAnim->keyframes().beginProperties(); it != endProperties; ++it)
index c95048e03e9a9faa35e26ce61c699ae9387b21b8..4f4919070c3247bb3870d7cff9a25b1cb9d6d7f9 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     void suspendAnimations();
     void resumeAnimations();
-    bool suspended() const { return m_suspended; }
+    bool isSuspended() const { return m_suspended; }
     
     bool hasAnimations() const  { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); }
 
@@ -80,11 +80,7 @@ public:
     unsigned numberOfActiveAnimations() const;
 
 private:
-    CompositeAnimation(AnimationControllerPrivate* animationController)
-        : m_animationController(animationController)
-        , m_suspended(false)
-    {
-    }
+    CompositeAnimation(AnimationControllerPrivate*);
 
     void updateTransitions(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle);
     void updateKeyframeAnimations(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle);
index 6cb827e9781e25db65b6e5f876547eac7ebee4e2..f888c8a4ef0065c89a7610f12f4e71c6b36b9063 100644 (file)
@@ -140,13 +140,13 @@ void KeyframeAnimation::fetchIntervalEndpointsForProperty(CSSPropertyID property
     prog = progress(scale, offset, timingFunction);
 }
 
-void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+void KeyframeAnimation::animate(CompositeAnimation* compositeAnimation, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
 {
     // Fire the start timeout if needed
     fireAnimationEventsIfNeeded();
     
     // If we have not yet started, we will not have a valid start time, so just start the animation if needed.
-    if (isNew() && m_animation->playState() == AnimPlayStatePlaying)
+    if (isNew() && m_animation->playState() == AnimPlayStatePlaying && !compositeAnimation->isSuspended())
         updateStateMachine(AnimationStateInputStartAnimation, -1);
 
     // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
index 85e95efa826e287c8ab5fbe86ca9d4da0e689dfa..330714aad278d43b93905b333367301927f833fb 100644 (file)
@@ -467,6 +467,20 @@ unsigned Internals::numberOfActiveAnimations() const
     return 0;
 }
 
+bool Internals::animationsAreSuspended(Document* document, ExceptionCode& ec) const
+{
+    if (!document || !document->frame()) {
+        ec = INVALID_ACCESS_ERR;
+        return false;
+    }
+
+    AnimationController* controller = document->frame()->animation();
+    if (!controller)
+        return false;
+
+    return controller->isSuspended();
+}
+
 void Internals::suspendAnimations(Document* document, ExceptionCode& ec) const
 {
     if (!document || !document->frame()) {
index b416e32af4a6d3d2acde6631e362c37764a7ff98..8476a5f597f3621d0491f58ca9c7b9d815c54527 100644 (file)
@@ -99,6 +99,7 @@ public:
 
     // CSS Animation testing.
     unsigned numberOfActiveAnimations() const;
+    bool animationsAreSuspended(Document*, ExceptionCode&) const;
     void suspendAnimations(Document*, ExceptionCode&) const;
     void resumeAnimations(Document*, ExceptionCode&) const;
     bool pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element*, ExceptionCode&);
index 0d4e536ea5032547739ccd4e5ccdc04e787a7ff4..e398241217111f696147890530beb854d5535cf0 100644 (file)
@@ -65,6 +65,7 @@
     unsigned long numberOfActiveAnimations();
     void suspendAnimations(Document document) raises (DOMException);
     void resumeAnimations(Document document) raises (DOMException);
+    boolean animationsAreSuspended(in Document document) raises (DOMException);
     boolean pauseAnimationAtTimeOnElement(DOMString animationName, double pauseTime, Element element) raises (DOMException);
     boolean pauseAnimationAtTimeOnPseudoElement(DOMString animationName, double pauseTime, Element element, DOMString pseudoId) raises (DOMException);
 
index 3fcb3b35a08c995892a785d10fb71f184c78e79a..0e05833bbb2367b3f3546affaea7d8e96ff1e752 100644 (file)
@@ -1,3 +1,14 @@
+2013-05-04  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        Export AnimationController::isSuspended
+
+        * WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in:
+
 2013-05-04  Sam Weinig  <sam@webkit.org>
 
         Move PopupMenuMac and SearchPopupMenuMac to Source/WebKit/mac
index 2876b01e2d975d58130c2444904b27d5854e24ae..e90ac485b8976db90cff0060edaf07bac5073203 100644 (file)
@@ -1,3 +1,23 @@
+2013-05-04  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        The WebView private API cssAnimationsSuspended did not necessarily
+        reflect the reality of the Frame's AnimationController value because it
+        was caching rather than asking directly. While the WebCore part of this
+        patch ensured loading the Document wouldn't resume all animations, it
+        is still better to ask directly.
+
+        * WebView/WebView.mm:
+        (-[WebView cssAnimationsSuspended]): Call into AnimationController.
+        (-[WebView setCSSAnimationsSuspended:]): Ditto.
+        * WebView/WebViewData.h: Remove cssAnimationsSuspended boolean.
+        * WebView/WebViewData.mm: Ditto.
+        (-[WebViewPrivate init]):
+
 2013-05-04  Sam Weinig  <sam@webkit.org>
 
         Move PopupMenuMac and SearchPopupMenuMac to Source/WebKit/mac
index 57f997671e11248bc32eb9a8e6191b5227a66bf0..ccbb4b0c3e126c1dd20394b5e6c4bac0ce437057 100644 (file)
@@ -2769,17 +2769,20 @@ static Vector<String> toStringVector(NSArray* patterns)
 
 - (BOOL)cssAnimationsSuspended
 {
-    return _private->cssAnimationsSuspended;
+    // should ask the page!
+    Frame* frame = core([self mainFrame]);
+    if (frame)
+        return frame->animation()->isSuspended();
+
+    return false;
 }
 
 - (void)setCSSAnimationsSuspended:(BOOL)suspended
 {
-    if (suspended == _private->cssAnimationsSuspended)
+    Frame* frame = core([self mainFrame]);
+    if (suspended == frame->animation()->isSuspended())
         return;
         
-    _private->cssAnimationsSuspended = suspended;
-    
-    Frame* frame = core([self mainFrame]);
     if (suspended)
         frame->animation()->suspendAnimations();
     else
index 347aba45785f180e8c9746cccb62a4e6780e94c0..89f7321e81c3dd9d3308ac9613adbb112bd097c2 100644 (file)
@@ -137,7 +137,6 @@ private:
     BOOL becomingFirstResponder;
     BOOL becomingFirstResponderFromOutside;
     BOOL usesPageCache;
-    BOOL cssAnimationsSuspended;
 
     NSColor *backgroundColor;
 
index c681f09ba7216d8d216e597526af8581d003de7c..4d108f0ac6d51230bbe9f154edf1390286602dbe 100644 (file)
@@ -80,7 +80,6 @@ LayerFlushController::LayerFlushController(WebView* webView)
     allowsUndo = YES;
     usesPageCache = YES;
     shouldUpdateWhileOffscreen = YES;
-    cssAnimationsSuspended = NO;
 
     zoomMultiplier = 1;
     zoomsTextOnly = NO;
index fed3ef27b6d9c5f4bf8e858100ef83b410924f69..81508de7add6c11ef0983e16ad327d75abcacb91 100644 (file)
@@ -1,3 +1,14 @@
+2013-05-04  Dean Jackson  <dino@apple.com>
+
+        Animations and Transitions should not start when globally suspended
+        https://bugs.webkit.org/show_bug.cgi?id=114915
+
+        Reviewed by Sam Weinig.
+
+        Export AnimationController::isSuspended
+
+        * WebKit.vcproj/WebKitExports.def.in:
+
 2013-05-01  Sergio Villar Senin  <svillar@igalia.com>
 
         Show a block cursor in overtype mode
index 3f8212859ece795a600f80fce8a3a72aa77f54b1..15ef021601d0ffc7b30d66f7e8d14aa737dc1cc1 100644 (file)
@@ -333,6 +333,7 @@ EXPORTS
         ?viewportArguments@Page@WebCore@@QBE?AUViewportArguments@2@XZ
         ?isPageBoxVisible@Document@WebCore@@QAE_NH@Z
         ?isActive@InsertionPoint@WebCore@@QBE_NXZ
+        ?isSuspended@AnimationController@WebCore@@QBE_NXZ
         ?suspendAnimations@AnimationController@WebCore@@QAEXXZ
         ?resumeAnimations@AnimationController@WebCore@@QAEXXZ
         ?setAllowsRoundingHacks@TextRun@WebCore@@SAX_N@Z
index 868bde4f2de1f73388b5897c7200859a610c11f8..9069cdd9f69d56445dc53f3d03929106cc60ae57 100644 (file)
@@ -184,6 +184,7 @@ _ZN7WebCore22counterValueForElementEPNS_7ElementE;
 _ZNK7WebCore14DocumentMarker11descriptionEv;
 _ZN7WebCore8Document16isPageBoxVisibleEi;
 _ZN7WebCore18ContentDistributor22ensureSelectFeatureSetEPNS_13ElementShadowE;
+_ZNK7WebCore19AnimationController11isSuspendedEv;
 _ZN7WebCore19AnimationController17suspendAnimationsEv;
 _ZN7WebCore19AnimationController16resumeAnimationsEv;
 _ZN7WebCore19AnimationController20pauseAnimationAtTimeEPNS_12RenderObjectERKN3WTF12AtomicStringEd;