Title: [218747] trunk
Revision
218747
Author
[email protected]
Date
2017-06-23 08:44:30 -0700 (Fri, 23 Jun 2017)

Log Message

[mac-wk1] requestAnimationFrame callbacks may not get serviced
https://bugs.webkit.org/show_bug.cgi?id=173628

Reviewed by Simon Fraser.

Source/WebCore:

Page::setIsVisibleInternal() was firing the 'visibilitychange' event
synchronously while in the middle of updating its visibility/activity
state. This allowed the _javascript_ to re-enter the method by calling
testRunner.setPageVisibility() / resetPageVisiblity() and we would
end up in an inconsistent state.

No new tests, extended existing test.

* dom/Document.cpp:
(WebCore::Document::visibilityStateChanged):
Do no fire the visibilitychange event synchronously as we are in the
middle of updating the page's activity state. Instead fire the
event asynchronously.

* page/Page.cpp:
(WebCore::Page::setIsVisibleInternal):
Move the calling of Document::visibilityStateChanged() until after we're
done updating the page's visibility state.

* testing/Internals.cpp:
(WebCore::Internals::scriptedAnimationsAreSuspended):
* testing/Internals.h:
* testing/Internals.idl:
Add test infrastructure to check if scripted animations are suspended.

LayoutTests:

Extend layout test coverage.

* fast/events/page-visibility-transition-test-expected.txt:
* fast/events/page-visibility-transition-test.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (218746 => 218747)


--- trunk/LayoutTests/ChangeLog	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/LayoutTests/ChangeLog	2017-06-23 15:44:30 UTC (rev 218747)
@@ -1,3 +1,15 @@
+2017-06-23  Chris Dumez  <[email protected]>
+
+        [mac-wk1] requestAnimationFrame callbacks may not get serviced
+        https://bugs.webkit.org/show_bug.cgi?id=173628
+
+        Reviewed by Simon Fraser.
+
+        Extend layout test coverage.
+
+        * fast/events/page-visibility-transition-test-expected.txt:
+        * fast/events/page-visibility-transition-test.html:
+
 2017-06-23  Zan Dobersek  <[email protected]>
 
         [GCrypt] Drop the AES-CFB support

Modified: trunk/LayoutTests/fast/events/page-visibility-transition-test-expected.txt (218746 => 218747)


--- trunk/LayoutTests/fast/events/page-visibility-transition-test-expected.txt	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/LayoutTests/fast/events/page-visibility-transition-test-expected.txt	2017-06-23 15:44:30 UTC (rev 218747)
@@ -5,12 +5,16 @@
 
 PASS document.visibilityState is "visible"
 PASS document.hidden is false
+PASS internals.scriptedAnimationsAreSuspended is false
 PASS document.visibilityState is "hidden"
 PASS document.hidden is true
+PASS internals.scriptedAnimationsAreSuspended is true
 PASS document.visibilityState is "hidden"
 PASS document.hidden is true
+PASS internals.scriptedAnimationsAreSuspended is true
 PASS document.visibilityState is "visible"
 PASS document.hidden is false
+PASS internals.scriptedAnimationsAreSuspended is false
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/events/page-visibility-transition-test.html (218746 => 218747)


--- trunk/LayoutTests/fast/events/page-visibility-transition-test.html	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/LayoutTests/fast/events/page-visibility-transition-test.html	2017-06-23 15:44:30 UTC (rev 218747)
@@ -32,11 +32,13 @@
 function checkIsPageVisible() {
     shouldBeEqualToString("document.visibilityState", "visible");
     shouldBeFalse("document.hidden");
+    shouldBeFalse("internals.scriptedAnimationsAreSuspended");
 }
 
 function checkIsPageHidden() {
     shouldBeEqualToString("document.visibilityState", "hidden");
     shouldBeTrue("document.hidden");
+    shouldBeTrue("internals.scriptedAnimationsAreSuspended");
 }
 
 // We will try to change the visibility states as:

Modified: trunk/Source/WebCore/ChangeLog (218746 => 218747)


--- trunk/Source/WebCore/ChangeLog	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/ChangeLog	2017-06-23 15:44:30 UTC (rev 218747)
@@ -1,3 +1,35 @@
+2017-06-23  Chris Dumez  <[email protected]>
+
+        [mac-wk1] requestAnimationFrame callbacks may not get serviced
+        https://bugs.webkit.org/show_bug.cgi?id=173628
+
+        Reviewed by Simon Fraser.
+
+        Page::setIsVisibleInternal() was firing the 'visibilitychange' event
+        synchronously while in the middle of updating its visibility/activity
+        state. This allowed the _javascript_ to re-enter the method by calling
+        testRunner.setPageVisibility() / resetPageVisiblity() and we would
+        end up in an inconsistent state.
+
+        No new tests, extended existing test.
+
+        * dom/Document.cpp:
+        (WebCore::Document::visibilityStateChanged):
+        Do no fire the visibilitychange event synchronously as we are in the
+        middle of updating the page's activity state. Instead fire the
+        event asynchronously.
+
+        * page/Page.cpp:
+        (WebCore::Page::setIsVisibleInternal):
+        Move the calling of Document::visibilityStateChanged() until after we're
+        done updating the page's visibility state.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::scriptedAnimationsAreSuspended):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        Add test infrastructure to check if scripted animations are suspended.
+
 2017-06-23  Eric Carlson  <[email protected]>
 
         [iOS] Respond to AudioSession interruption and resume

Modified: trunk/Source/WebCore/dom/Document.cpp (218746 => 218747)


--- trunk/Source/WebCore/dom/Document.cpp	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/dom/Document.cpp	2017-06-23 15:44:30 UTC (rev 218747)
@@ -1617,7 +1617,7 @@
 
 void Document::visibilityStateChanged()
 {
-    dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
+    enqueueDocumentEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
     for (auto* client : m_visibilityStateCallbackClients)
         client->visibilityStateChanged();
 

Modified: trunk/Source/WebCore/page/Page.cpp (218746 => 218747)


--- trunk/Source/WebCore/page/Page.cpp	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/page/Page.cpp	2017-06-23 15:44:30 UTC (rev 218747)
@@ -1714,13 +1714,6 @@
         }
     }
 
-    Vector<Ref<Document>> documents;
-    for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
-        documents.append(*frame->document());
-
-    for (auto& document : documents)
-        document->visibilityStateChanged();
-
     if (!isVisible) {
         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
             mainFrame().animation().suspendAnimations();
@@ -1740,6 +1733,13 @@
         if (FrameView* view = mainFrame().view())
             view->hide();
     }
+
+    Vector<Ref<Document>> documents;
+    for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
+        documents.append(*frame->document());
+
+    for (auto& document : documents)
+        document->visibilityStateChanged();
 }
 
 void Page::setIsPrerender()

Modified: trunk/Source/WebCore/testing/Internals.cpp (218746 => 218747)


--- trunk/Source/WebCore/testing/Internals.cpp	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/testing/Internals.cpp	2017-06-23 15:44:30 UTC (rev 218747)
@@ -1163,6 +1163,15 @@
     return scriptedAnimationController->interval().value();
 }
 
+bool Internals::scriptedAnimationsAreSuspended() const
+{
+    Document* document = contextDocument();
+    if (!document || !document->page())
+        return true;
+
+    return document->page()->scriptedAnimationsSuspended();
+}
+
 bool Internals::areTimersThrottled() const
 {
     return contextDocument()->isTimerThrottlingEnabled();

Modified: trunk/Source/WebCore/testing/Internals.h (218746 => 218747)


--- trunk/Source/WebCore/testing/Internals.h	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/testing/Internals.h	2017-06-23 15:44:30 UTC (rev 218747)
@@ -152,6 +152,7 @@
     ExceptionOr<bool> isTimerThrottled(int timeoutId);
     bool isRequestAnimationFrameThrottled() const;
     double requestAnimationFrameInterval() const;
+    bool scriptedAnimationsAreSuspended() const;
     bool areTimersThrottled() const;
 
     enum EventThrottlingBehavior { Responsive, Unresponsive };

Modified: trunk/Source/WebCore/testing/Internals.idl (218746 => 218747)


--- trunk/Source/WebCore/testing/Internals.idl	2017-06-23 15:40:05 UTC (rev 218746)
+++ trunk/Source/WebCore/testing/Internals.idl	2017-06-23 15:44:30 UTC (rev 218747)
@@ -370,6 +370,7 @@
 
     [MayThrowException] void setLowPowerModeEnabled(boolean enabled);
     readonly attribute double requestAnimationFrameInterval;
+    readonly attribute boolean scriptedAnimationsAreSuspended;
 
     // Override the behavior of WebPage::eventThrottlingDelay(), which only affects iOS.
     attribute EventThrottlingBehavior? eventThrottlingBehaviorOverride;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to