Title: [214322] trunk
Revision
214322
Author
cdu...@apple.com
Date
2017-03-23 15:40:50 -0700 (Thu, 23 Mar 2017)

Log Message

SVG animations are not paused when inserted into a hidden page
https://bugs.webkit.org/show_bug.cgi?id=170026
<rdar://problem/31228704>

Reviewed by Andreas Kling.

Source/WebCore:

SVG animations were not paused when inserted into a hidden page. We would pause
animations in a page when the page becomes hidden. However, new animations
inserted in the page after this point would start, despite the page being
hidden.

Tests:
- svg/animations/animations-paused-when-inserted-in-hidden-document.html
- svg/animations/animations-paused-when-inserted-in-hidden-document2.html

* dom/Document.cpp:
(WebCore::Document::accessSVGExtensions):
* svg/SVGDocumentExtensions.cpp:
(WebCore::SVGDocumentExtensions::SVGDocumentExtensions):
(WebCore::SVGDocumentExtensions::addTimeContainer):
(WebCore::reportMessage):
* svg/SVGDocumentExtensions.h:
* testing/Internals.cpp:
(WebCore::Internals::areSVGAnimationsPaused):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Add layout test coverage.

* svg/animations/animations-paused-when-inserted-in-hidden-document-expected.txt: Added.
* svg/animations/animations-paused-when-inserted-in-hidden-document.html: Added.
* svg/animations/animations-paused-when-inserted-in-hidden-document2-expected.txt: Added.
* svg/animations/animations-paused-when-inserted-in-hidden-document2.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (214321 => 214322)


--- trunk/LayoutTests/ChangeLog	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/LayoutTests/ChangeLog	2017-03-23 22:40:50 UTC (rev 214322)
@@ -1 +1,16 @@
+2017-03-23  Chris Dumez  <cdu...@apple.com>
+
+        SVG animations are not paused when inserted into a hidden page
+        https://bugs.webkit.org/show_bug.cgi?id=170026
+        <rdar://problem/31228704>
+
+        Reviewed by Andreas Kling.
+
+        Add layout test coverage.
+
+        * svg/animations/animations-paused-when-inserted-in-hidden-document-expected.txt: Added.
+        * svg/animations/animations-paused-when-inserted-in-hidden-document.html: Added.
+        * svg/animations/animations-paused-when-inserted-in-hidden-document2-expected.txt: Added.
+        * svg/animations/animations-paused-when-inserted-in-hidden-document2.html: Added.
+
 == Rolled over to ChangeLog-2017-03-23 ==

Added: trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document-expected.txt (0 => 214322)


--- trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document-expected.txt	2017-03-23 22:40:50 UTC (rev 214322)
@@ -0,0 +1,20 @@
+Tests that SVG animations are properly paused in iframes that are inserted into hidden pages.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Setting page visibility to hidden
+Inserting frame in document
+PASS frame.contentWindow.internals.areSVGAnimationsPaused is true
+PASS frame.contentDocument.getElementsByTagName('svg')[0].animationsPaused() is true
+PASS grandChildFrame.contentWindow.internals.areSVGAnimationsPaused is true
+PASS grandChildFrame.contentDocument.getElementsByTagName('svg')[0].animationsPaused() is true
+Setting page visibility to visible
+PASS frame.contentWindow.internals.areSVGAnimationsPaused is false
+PASS frame.contentDocument.getElementsByTagName('svg')[0].animationsPaused() is false
+PASS grandChildFrame.contentWindow.internals.areSVGAnimationsPaused is false
+PASS grandChildFrame.contentDocument.getElementsByTagName('svg')[0].animationsPaused() is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document.html (0 => 214322)


--- trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document.html	2017-03-23 22:40:50 UTC (rev 214322)
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests that SVG animations are properly paused in iframes that are inserted into hidden pages.");
+jsTestIsAsync = true;
+
+document.addEventListener("visibilitychange", function() {
+    if (document.hidden) {
+        frame = document.createElement("iframe");
+        frame._onload_ = function() {
+            setTimeout(function() {
+                shouldBeTrue("frame.contentWindow.internals.areSVGAnimationsPaused");
+                shouldBeTrue("frame.contentDocument.getElementsByTagName('svg')[0].animationsPaused()");
+                grandChildFrame = frame.contentDocument.getElementById('grandChildFrame');
+                shouldBeTrue("grandChildFrame.contentWindow.internals.areSVGAnimationsPaused");
+                shouldBeTrue("grandChildFrame.contentDocument.getElementsByTagName('svg')[0].animationsPaused()");
+
+                debug("Setting page visibility to visible"); 
+                if (window.testRunner)
+                    testRunner.setPageVisibility("visible");
+            }, 0);
+        }
+        frame.src = ""
+        debug("Inserting frame in document");
+        document.body.appendChild(frame);
+    } else {
+        shouldBeFalse("frame.contentWindow.internals.areSVGAnimationsPaused");
+        shouldBeFalse("frame.contentDocument.getElementsByTagName('svg')[0].animationsPaused()");
+        grandChildFrame = frame.contentDocument.getElementById('grandChildFrame');
+        shouldBeFalse("grandChildFrame.contentWindow.internals.areSVGAnimationsPaused");
+        shouldBeFalse("grandChildFrame.contentDocument.getElementsByTagName('svg')[0].animationsPaused()");
+        finishJSTest();
+    }
+});
+
+window._onload_ = function() {
+    debug("Setting page visibility to hidden");
+    if (window.testRunner)
+        testRunner.setPageVisibility("hidden");
+}
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2-expected.txt (0 => 214322)


--- trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2-expected.txt	2017-03-23 22:40:50 UTC (rev 214322)
@@ -0,0 +1,16 @@
+Tests that SVG animations are properly paused in iframes that are inserted into hidden pages.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Setting page visibility to hidden
+Inserting SVG animation in the document
+PASS internals.areSVGAnimationsPaused is true
+PASS svgElement.animationsPaused() is true
+Setting page visibility to visible
+PASS internals.areSVGAnimationsPaused is false
+PASS svgElement.animationsPaused() is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2.html (0 => 214322)


--- trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/animations-paused-when-inserted-in-hidden-document2.html	2017-03-23 22:40:50 UTC (rev 214322)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests that SVG animations are properly paused in iframes that are inserted into hidden pages.");
+jsTestIsAsync = true;
+
+var animationAsText = '<svg width="300px" height="100px"><rect x="0" y="0" width="300" height="100" stroke="black" stroke-width="1" /><circle cx="0" cy="50" r="15" fill="blue" stroke="black" stroke-width="1"><animate attributeName="cx" from="0" to="100" dur="5s" repeatCount="indefinite" /></circle></svg>';
+
+document.addEventListener("visibilitychange", function() {
+    if (document.hidden) {
+        debug("Inserting SVG animation in the document");
+        testDiv.innerHTML = animationAsText;
+        svgElement = document.getElementsByTagName("svg")[0];
+        
+        setTimeout(function() {
+            shouldBeTrue("internals.areSVGAnimationsPaused");
+            shouldBeTrue("svgElement.animationsPaused()");
+
+            debug("Setting page visibility to visible"); 
+            if (window.testRunner)
+                testRunner.setPageVisibility("visible");
+            }, 0);
+    } else {
+        shouldBeFalse("internals.areSVGAnimationsPaused");
+        shouldBeFalse("svgElement.animationsPaused()");
+        finishJSTest();
+    }
+});
+
+window._onload_ = function() {
+    debug("Setting page visibility to hidden");
+    if (window.testRunner)
+        testRunner.setPageVisibility("hidden");
+}
+</script>
+<div id="testDiv"></div>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (214321 => 214322)


--- trunk/Source/WebCore/ChangeLog	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/ChangeLog	2017-03-23 22:40:50 UTC (rev 214322)
@@ -1 +1,30 @@
+2017-03-23  Chris Dumez  <cdu...@apple.com>
+
+        SVG animations are not paused when inserted into a hidden page
+        https://bugs.webkit.org/show_bug.cgi?id=170026
+        <rdar://problem/31228704>
+
+        Reviewed by Andreas Kling.
+
+        SVG animations were not paused when inserted into a hidden page. We would pause
+        animations in a page when the page becomes hidden. However, new animations
+        inserted in the page after this point would start, despite the page being
+        hidden.
+
+        Tests:
+        - svg/animations/animations-paused-when-inserted-in-hidden-document.html
+        - svg/animations/animations-paused-when-inserted-in-hidden-document2.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::accessSVGExtensions):
+        * svg/SVGDocumentExtensions.cpp:
+        (WebCore::SVGDocumentExtensions::SVGDocumentExtensions):
+        (WebCore::SVGDocumentExtensions::addTimeContainer):
+        (WebCore::reportMessage):
+        * svg/SVGDocumentExtensions.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::areSVGAnimationsPaused):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 == Rolled over to ChangeLog-2017-03-23 ==

Modified: trunk/Source/WebCore/dom/Document.cpp (214321 => 214322)


--- trunk/Source/WebCore/dom/Document.cpp	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/dom/Document.cpp	2017-03-23 22:40:50 UTC (rev 214322)
@@ -4873,7 +4873,7 @@
 SVGDocumentExtensions& Document::accessSVGExtensions()
 {
     if (!m_svgExtensions)
-        m_svgExtensions = std::make_unique<SVGDocumentExtensions>(this);
+        m_svgExtensions = std::make_unique<SVGDocumentExtensions>(*this);
     return *m_svgExtensions;
 }
 

Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp (214321 => 214322)


--- trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp	2017-03-23 22:40:50 UTC (rev 214322)
@@ -27,6 +27,7 @@
 #include "EventListener.h"
 #include "Frame.h"
 #include "FrameLoader.h"
+#include "Page.h"
 #include "SMILTimeContainer.h"
 #include "SVGElement.h"
 #include "SVGResourcesCache.h"
@@ -39,9 +40,10 @@
 
 namespace WebCore {
 
-SVGDocumentExtensions::SVGDocumentExtensions(Document* document)
+SVGDocumentExtensions::SVGDocumentExtensions(Document& document)
     : m_document(document)
     , m_resourcesCache(std::make_unique<SVGResourcesCache>())
+    , m_areAnimationsPaused(!document.page() || !document.page()->isVisible())
 {
 }
 
@@ -52,6 +54,8 @@
 void SVGDocumentExtensions::addTimeContainer(SVGSVGElement* element)
 {
     m_timeContainers.add(element);
+    if (m_areAnimationsPaused)
+        element->pauseAnimations();
 }
 
 void SVGDocumentExtensions::removeTimeContainer(SVGSVGElement* element)
@@ -124,10 +128,10 @@
     }
 }
 
-static void reportMessage(Document* document, MessageLevel level, const String& message)
+static void reportMessage(Document& document, MessageLevel level, const String& message)
 {
-    if (document->frame())
-        document->addConsoleMessage(MessageSource::Rendering, level, message);
+    if (document.frame())
+        document.addConsoleMessage(MessageSource::Rendering, level, message);
 }
 
 void SVGDocumentExtensions::reportWarning(const String& message)

Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.h (214321 => 214322)


--- trunk/Source/WebCore/svg/SVGDocumentExtensions.h	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.h	2017-03-23 22:40:50 UTC (rev 214322)
@@ -40,7 +40,7 @@
     WTF_MAKE_NONCOPYABLE(SVGDocumentExtensions); WTF_MAKE_FAST_ALLOCATED;
 public:
     typedef HashSet<Element*> PendingElements;
-    explicit SVGDocumentExtensions(Document*);
+    explicit SVGDocumentExtensions(Document&);
     ~SVGDocumentExtensions();
     
     void addTimeContainer(SVGSVGElement*);
@@ -77,7 +77,7 @@
 #endif
 
 private:
-    Document* m_document; // weak reference
+    Document& m_document;
     HashSet<SVGSVGElement*> m_timeContainers; // For SVG 1.2 support this will need to be made more general.
 #if ENABLE(SVG_FONTS)
     HashSet<SVGFontFaceElement*> m_svgFontFaceElements;
@@ -89,7 +89,7 @@
     std::unique_ptr<SVGResourcesCache> m_resourcesCache;
 
     Vector<SVGElement*> m_rebuildElements;
-    bool m_areAnimationsPaused { false }; // For testing.
+    bool m_areAnimationsPaused;
 
 public:
     // This HashMap contains a list of pending resources. Pending resources, are such

Modified: trunk/Source/WebCore/testing/Internals.cpp (214321 => 214322)


--- trunk/Source/WebCore/testing/Internals.cpp	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/testing/Internals.cpp	2017-03-23 22:40:50 UTC (rev 214322)
@@ -517,14 +517,14 @@
     return WorkerThread::workerThreadCount();
 }
 
-bool Internals::areSVGAnimationsPaused() const
+ExceptionOr<bool> Internals::areSVGAnimationsPaused() const
 {
     auto* document = contextDocument();
     if (!document)
-        return false;
+        return Exception { INVALID_ACCESS_ERR, ASCIILiteral("No context document") };
 
     if (!document->svgExtensions())
-        return false;
+        return Exception { NOT_FOUND_ERR, ASCIILiteral("No SVG animations") };
 
     return document->accessSVGExtensions().areAnimationsPaused();
 }

Modified: trunk/Source/WebCore/testing/Internals.h (214321 => 214322)


--- trunk/Source/WebCore/testing/Internals.h	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/testing/Internals.h	2017-03-23 22:40:50 UTC (rev 214322)
@@ -266,7 +266,7 @@
 
     InternalSettings* settings() const;
     unsigned workerThreadCount() const;
-    bool areSVGAnimationsPaused() const;
+    ExceptionOr<bool> areSVGAnimationsPaused() const;
     ExceptionOr<double> svgAnimationsInterval(SVGSVGElement&) const;
 
     ExceptionOr<void> setDeviceProximity(const String& eventType, double value, double min, double max);

Modified: trunk/Source/WebCore/testing/Internals.idl (214321 => 214322)


--- trunk/Source/WebCore/testing/Internals.idl	2017-03-23 22:39:57 UTC (rev 214321)
+++ trunk/Source/WebCore/testing/Internals.idl	2017-03-23 22:40:50 UTC (rev 214322)
@@ -249,7 +249,7 @@
     readonly attribute InternalSettings settings;
     readonly attribute unsigned long workerThreadCount;
 
-    readonly attribute boolean areSVGAnimationsPaused;
+    [MayThrowException] readonly attribute boolean areSVGAnimationsPaused;
     [MayThrowException] double svgAnimationsInterval(SVGSVGElement element);
 
     // Flags for layerTreeAsText.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to