- 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;