Changeset 218747 in webkit


Ignore:
Timestamp:
Jun 23, 2017 8:44:30 AM (7 years ago)
Author:
Chris Dumez
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:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r218744 r218747  
     12017-06-23  Chris Dumez  <cdumez@apple.com>
     2
     3        [mac-wk1] requestAnimationFrame callbacks may not get serviced
     4        https://bugs.webkit.org/show_bug.cgi?id=173628
     5
     6        Reviewed by Simon Fraser.
     7
     8        Extend layout test coverage.
     9
     10        * fast/events/page-visibility-transition-test-expected.txt:
     11        * fast/events/page-visibility-transition-test.html:
     12
    1132017-06-23  Zan Dobersek  <zdobersek@igalia.com>
    214
  • trunk/LayoutTests/fast/events/page-visibility-transition-test-expected.txt

    r161105 r218747  
    66PASS document.visibilityState is "visible"
    77PASS document.hidden is false
     8PASS internals.scriptedAnimationsAreSuspended is false
    89PASS document.visibilityState is "hidden"
    910PASS document.hidden is true
     11PASS internals.scriptedAnimationsAreSuspended is true
    1012PASS document.visibilityState is "hidden"
    1113PASS document.hidden is true
     14PASS internals.scriptedAnimationsAreSuspended is true
    1215PASS document.visibilityState is "visible"
    1316PASS document.hidden is false
     17PASS internals.scriptedAnimationsAreSuspended is false
    1418PASS successfullyParsed is true
    1519
  • trunk/LayoutTests/fast/events/page-visibility-transition-test.html

    r161105 r218747  
    3333    shouldBeEqualToString("document.visibilityState", "visible");
    3434    shouldBeFalse("document.hidden");
     35    shouldBeFalse("internals.scriptedAnimationsAreSuspended");
    3536}
    3637
     
    3839    shouldBeEqualToString("document.visibilityState", "hidden");
    3940    shouldBeTrue("document.hidden");
     41    shouldBeTrue("internals.scriptedAnimationsAreSuspended");
    4042}
    4143
  • trunk/Source/WebCore/ChangeLog

    r218746 r218747  
     12017-06-23  Chris Dumez  <cdumez@apple.com>
     2
     3        [mac-wk1] requestAnimationFrame callbacks may not get serviced
     4        https://bugs.webkit.org/show_bug.cgi?id=173628
     5
     6        Reviewed by Simon Fraser.
     7
     8        Page::setIsVisibleInternal() was firing the 'visibilitychange' event
     9        synchronously while in the middle of updating its visibility/activity
     10        state. This allowed the JavaScript to re-enter the method by calling
     11        testRunner.setPageVisibility() / resetPageVisiblity() and we would
     12        end up in an inconsistent state.
     13
     14        No new tests, extended existing test.
     15
     16        * dom/Document.cpp:
     17        (WebCore::Document::visibilityStateChanged):
     18        Do no fire the visibilitychange event synchronously as we are in the
     19        middle of updating the page's activity state. Instead fire the
     20        event asynchronously.
     21
     22        * page/Page.cpp:
     23        (WebCore::Page::setIsVisibleInternal):
     24        Move the calling of Document::visibilityStateChanged() until after we're
     25        done updating the page's visibility state.
     26
     27        * testing/Internals.cpp:
     28        (WebCore::Internals::scriptedAnimationsAreSuspended):
     29        * testing/Internals.h:
     30        * testing/Internals.idl:
     31        Add test infrastructure to check if scripted animations are suspended.
     32
    1332017-06-23  Eric Carlson  <eric.carlson@apple.com>
    234
  • trunk/Source/WebCore/dom/Document.cpp

    r218730 r218747  
    16181618void Document::visibilityStateChanged()
    16191619{
    1620     dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
     1620    enqueueDocumentEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
    16211621    for (auto* client : m_visibilityStateCallbackClients)
    16221622        client->visibilityStateChanged();
  • trunk/Source/WebCore/page/Page.cpp

    r218732 r218747  
    17151715    }
    17161716
     1717    if (!isVisible) {
     1718        if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
     1719            mainFrame().animation().suspendAnimations();
     1720
     1721        setSVGAnimationsState(*this, SVGAnimationsState::Paused);
     1722
     1723#if PLATFORM(IOS)
     1724        suspendDeviceMotionAndOrientationUpdates();
     1725#endif
     1726
     1727#if PLATFORM(MAC)
     1728        if (MacApplication::isDumpRenderTree())
     1729            WTFLogAlways("\nPage::setIsVisibleInternal(%s), %p", isVisible ? "true" : "false", this);
     1730#endif
     1731        suspendScriptedAnimations();
     1732
     1733        if (FrameView* view = mainFrame().view())
     1734            view->hide();
     1735    }
     1736
    17171737    Vector<Ref<Document>> documents;
    17181738    for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
     
    17211741    for (auto& document : documents)
    17221742        document->visibilityStateChanged();
    1723 
    1724     if (!isVisible) {
    1725         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
    1726             mainFrame().animation().suspendAnimations();
    1727 
    1728         setSVGAnimationsState(*this, SVGAnimationsState::Paused);
    1729 
    1730 #if PLATFORM(IOS)
    1731         suspendDeviceMotionAndOrientationUpdates();
    1732 #endif
    1733 
    1734 #if PLATFORM(MAC)
    1735         if (MacApplication::isDumpRenderTree())
    1736             WTFLogAlways("\nPage::setIsVisibleInternal(%s), %p", isVisible ? "true" : "false", this);
    1737 #endif
    1738         suspendScriptedAnimations();
    1739 
    1740         if (FrameView* view = mainFrame().view())
    1741             view->hide();
    1742     }
    17431743}
    17441744
  • trunk/Source/WebCore/testing/Internals.cpp

    r218699 r218747  
    11641164}
    11651165
     1166bool Internals::scriptedAnimationsAreSuspended() const
     1167{
     1168    Document* document = contextDocument();
     1169    if (!document || !document->page())
     1170        return true;
     1171
     1172    return document->page()->scriptedAnimationsSuspended();
     1173}
     1174
    11661175bool Internals::areTimersThrottled() const
    11671176{
  • trunk/Source/WebCore/testing/Internals.h

    r218699 r218747  
    153153    bool isRequestAnimationFrameThrottled() const;
    154154    double requestAnimationFrameInterval() const;
     155    bool scriptedAnimationsAreSuspended() const;
    155156    bool areTimersThrottled() const;
    156157
  • trunk/Source/WebCore/testing/Internals.idl

    r218699 r218747  
    371371    [MayThrowException] void setLowPowerModeEnabled(boolean enabled);
    372372    readonly attribute double requestAnimationFrameInterval;
     373    readonly attribute boolean scriptedAnimationsAreSuspended;
    373374
    374375    // Override the behavior of WebPage::eventThrottlingDelay(), which only affects iOS.
Note: See TracChangeset for help on using the changeset viewer.