Changeset 229466 in webkit


Ignore:
Timestamp:
Mar 9, 2018 10:21:11 AM (6 years ago)
Author:
jer.noble@apple.com
Message:

webkitfullscreenchange event not fired at the same time as :-webkit-full-screen pseudo selector changes; causes glitchiness
https://bugs.webkit.org/show_bug.cgi?id=183383

Source/WebCore:

Reviewed by Eric Carlson.

Fire the webkitfullscreenchange event at the same time as the pseudo class selector changes, during the handling
of webkitDidEnterFullScreenForElement. For WebKit2 clients, this is guaranteed to be asynchronous, since the
calling method originates in the UIProcess. For WebKit1 clients (and WKTR and DRT), there's the possibility that
webkitWillEnterFullScreenForElement will be called synchronously from within
Document::requestFullScreenForElement(), so break that synchronousness by starting the
ChromeClient::enterFullScreenForElement(...) process in a async task.

Previously, the firing of the fullscreenchange event was done through a zero-length timer. Use a
GenericTaskQueue instead.

A number of layout tests depend on the behavior that the element will be in fullscreen when the 'playing' event
fires. This was true for DRT (but not WKTR), since its fullscreen implementations were deliberately synchronous, but
won't necessarily be true for all ports. Fix this in a subsequent patch.

  • dom/Document.cpp:

(WebCore::Document::requestFullScreenForElement):
(WebCore::Document::webkitExitFullscreen):
(WebCore::Document::webkitWillEnterFullScreenForElement):
(WebCore::Document::webkitDidEnterFullScreenForElement):
(WebCore::Document::webkitDidExitFullScreenForElement):
(WebCore::Document::dispatchFullScreenChangeEvents):

  • dom/Document.h:
  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::setReadyState):
(WebCore::HTMLMediaElement::playInternal):
(WebCore::HTMLMediaElement::mediaPlayerTimeChanged):
(WebCore::HTMLMediaElement::updatePlayState):
(WebCore::HTMLMediaElement::setPlaying):

LayoutTests:

Fix a couple tests that depended on non-standard behavior, and skip other tests to be fixed later.

Reviewed by Eric Carlson.

  • media/fullscreen-video-going-into-pip.html:
  • media/video-fullscreeen-only-playback.html:
  • platform/mac/TestExpectations:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r229463 r229466  
     12018-03-09  Jer Noble  <jer.noble@apple.com>
     2
     3        webkitfullscreenchange event not fired at the same time as :-webkit-full-screen pseudo selector changes; causes glitchiness
     4        https://bugs.webkit.org/show_bug.cgi?id=183383
     5
     6        Fix a couple tests that depended on non-standard behavior, and skip other tests to be fixed later.
     7
     8        Reviewed by Eric Carlson.
     9
     10        * media/fullscreen-video-going-into-pip.html:
     11        * media/video-fullscreeen-only-playback.html:
     12        * platform/mac/TestExpectations:
     13
    1142018-03-09  Frederic Wang  <fwang@igalia.com>
    215
  • trunk/LayoutTests/media/fullscreen-video-going-into-pip.html

    r202219 r229466  
    2323
    2424            consoleWrite("Going into Full Screen");
    25             video.addEventListener('webkitfullscreenchange', onfullscreenchange);
     25            video.addEventListener('webkitpresentationmodechanged', onfullscreenchange);
    2626            runWithKeyDown(function(){ video.webkitRequestFullscreen(); });
    2727        }
     
    3030        {
    3131            testExpected("document.webkitCurrentFullScreenElement", video);
    32             video.removeEventListener('webkitfullscreenchange', onfullscreenchange);
     32            video.removeEventListener('webkitpresentationmodechanged', onfullscreenchange);
    3333
    3434            consoleWrite("Going into Picture-in-Picture from Full Screen");
  • trunk/LayoutTests/media/video-fullscreeen-only-playback.html

    r210959 r229466  
    99            function fullscreenchange()
    1010            {
    11                 if (document.webkitIsFullScreen)
    12                     beginfullscreen();
    13                 else
     11                if (!document.webkitIsFullScreen)
    1412                    endfullscreen();
    1513            }
    1614
    17             function beginfullscreen()
     15            function playing()
    1816            {
    1917                consoleWrite("<br>** Entered fullscreen");
     
    5351                video = document.getElementsByTagName('video')[0];
    5452                waitForEvent("canplaythrough", canplaythrough);
    55                 waitForEvent('playing');
     53                waitForEvent('playing', playing);
    5654
    57                 video.addEventListener('webkitbeginfullscreen', beginfullscreen, true);
    5855                video.addEventListener('webkitendfullscreen', endfullscreen, true);
    5956                video.addEventListener('webkitfullscreenchange', fullscreenchange, true);
  • trunk/LayoutTests/platform/mac/TestExpectations

    r229411 r229466  
    17281728
    17291729webkit.org/b/173946 [ Debug ] media/modern-media-controls/fullscreen-support/fullscreen-support-press.html [ Pass Failure ]
     1730
     1731webkit.org/b/183490 media/modern-media-controls/controls-visibility-support/controls-visibility-support-fullscreen-on-video.html [ Failure ]
     1732webkit.org/b/183490 media/modern-media-controls/media-controller/media-controller-fade-controls-when-entering-fullscreen.html [ Failure ]
     1733webkit.org/b/183490 media/modern-media-controls/media-controller/media-controller-fullscreen-change.html [ Failure ]
     1734webkit.org/b/183490 media/modern-media-controls/media-controller/media-controller-inline-to-fullscreen-to-inline.html [ Failure ]
     1735webkit.org/b/183490 media/modern-media-controls/start-support/start-support-fullscreen.html [ Failure ]
     1736webkit.org/b/183490 media/video-playsinline.html [ Failure ]
     1737webkit.org/b/183490 media/video-webkit-playsinline.html [ Failure ]
     1738webkit.org/b/183490 media/modern-media-controls/media-controller/media-controller-inline-to-fullscreen-to-pip-to-inline.html [ Failure ]
  • trunk/Source/WebCore/ChangeLog

    r229460 r229466  
     12018-03-09  Jer Noble  <jer.noble@apple.com>
     2
     3        webkitfullscreenchange event not fired at the same time as :-webkit-full-screen pseudo selector changes; causes glitchiness
     4        https://bugs.webkit.org/show_bug.cgi?id=183383
     5
     6        Reviewed by Eric Carlson.
     7
     8        Fire the webkitfullscreenchange event at the same time as the pseudo class selector changes, during the handling
     9        of webkitDidEnterFullScreenForElement. For WebKit2 clients, this is guaranteed to be asynchronous, since the
     10        calling method originates in the UIProcess. For WebKit1 clients (and WKTR and DRT), there's the possibility that
     11        webkitWillEnterFullScreenForElement will be called synchronously from within
     12        Document::requestFullScreenForElement(), so break that synchronousness by starting the
     13        ChromeClient::enterFullScreenForElement(...) process in a async task.
     14
     15        Previously, the firing of the fullscreenchange event was done through a zero-length timer. Use a
     16        GenericTaskQueue instead.
     17
     18        A number of layout tests depend on the behavior that the element will be in fullscreen when the 'playing' event
     19        fires. This was true for DRT (but not WKTR), since its fullscreen implementations were deliberately synchronous, but
     20        won't necessarily be true for all ports. Fix this in a subsequent patch.
     21
     22        * dom/Document.cpp:
     23        (WebCore::Document::requestFullScreenForElement):
     24        (WebCore::Document::webkitExitFullscreen):
     25        (WebCore::Document::webkitWillEnterFullScreenForElement):
     26        (WebCore::Document::webkitDidEnterFullScreenForElement):
     27        (WebCore::Document::webkitDidExitFullScreenForElement):
     28        (WebCore::Document::dispatchFullScreenChangeEvents):
     29        * dom/Document.h:
     30        * html/HTMLMediaElement.cpp:
     31        (WebCore::HTMLMediaElement::setReadyState):
     32        (WebCore::HTMLMediaElement::playInternal):
     33        (WebCore::HTMLMediaElement::mediaPlayerTimeChanged):
     34        (WebCore::HTMLMediaElement::updatePlayState):
     35        (WebCore::HTMLMediaElement::setPlaying):
     36
    1372018-03-09  Zan Dobersek  <zdobersek@igalia.com>
    238
  • trunk/Source/WebCore/dom/Document.cpp

    r229448 r229466  
    496496    , m_documentClasses(documentClasses)
    497497    , m_eventQueue(*this)
    498 #if ENABLE(FULLSCREEN_API)
    499     , m_fullScreenChangeDelayTimer(*this, &Document::fullScreenChangeDelayTimerFired)
    500 #endif
    501498    , m_loadEventDelayTimer(*this, &Document::loadEventDelayTimerFired)
    502499#if PLATFORM(IOS)
     
    60906087        // 6. Optionally, perform some animation.
    60916088        m_areKeysEnabledInFullScreen = hasKeyboardAccess;
    6092         page()->chrome().client().enterFullScreenForElement(*element);
     6089        m_fullScreenTaskQueue.enqueueTask([this, element = makeRefPtr(element)] {
     6090            if (auto page = this->page())
     6091                page->chrome().client().enterFullScreenForElement(*element);
     6092        });
    60936093
    60946094        // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
     
    60976097
    60986098    m_fullScreenErrorEventTargetQueue.append(element ? element : documentElement());
    6099     m_fullScreenChangeDelayTimer.startOneShot(0_s);
     6099    m_fullScreenTaskQueue.enqueueTask([this] {
     6100        dispatchFullScreenChangeEvents();
     6101    });
    61006102}
    61016103
     
    61756177    // 6. Return, and run the remaining steps asynchronously.
    61766178    // 7. Optionally, perform some animation.
    6177 
    6178     if (!page())
    6179         return;
    6180 
    6181     // Only exit out of full screen window mode if there are no remaining elements in the
    6182     // full screen stack.
    6183     if (!newTop) {
    6184         page()->chrome().client().exitFullScreenForElement(m_fullScreenElement.get());
    6185         return;
    6186     }
    6187 
    6188     // Otherwise, notify the chrome of the new full screen element.
    6189     page()->chrome().client().enterFullScreenForElement(*newTop);
     6179    m_fullScreenTaskQueue.enqueueTask([this, newTop = makeRefPtr(newTop), fullScreenElement = m_fullScreenElement] {
     6180        auto* page = this->page();
     6181        if (!page)
     6182            return;
     6183
     6184        // Only exit out of full screen window mode if there are no remaining elements in the
     6185        // full screen stack.
     6186        if (!newTop) {
     6187            page->chrome().client().exitFullScreenForElement(fullScreenElement.get());
     6188            return;
     6189        }
     6190
     6191        // Otherwise, notify the chrome of the new full screen element.
     6192        page->chrome().client().enterFullScreenForElement(*newTop);
     6193    });
    61906194}
    61916195
     
    62526256
    62536257    resolveStyle(ResolveStyleType::Rebuild);
    6254 #if PLATFORM(IOS) && ENABLE(FULLSCREEN_API)
    6255     m_fullScreenChangeDelayTimer.startOneShot(0_s);
    6256 #endif
     6258    dispatchFullScreenChangeEvents();
    62576259}
    62586260
     
    62666268
    62676269    m_fullScreenElement->didBecomeFullscreenElement();
    6268 
    6269 #if !PLATFORM(IOS) || !ENABLE(FULLSCREEN_API)
    6270     m_fullScreenChangeDelayTimer.startOneShot(0_s);
    6271 #endif
    62726270}
    62736271
     
    63066304    Document& exitingDocument = eventTargetQueuesEmpty ? topDocument() : *this;
    63076305
    6308     exitingDocument.m_fullScreenChangeDelayTimer.startOneShot(0_s);
     6306    exitingDocument.dispatchFullScreenChangeEvents();
    63096307}
    63106308
     
    63286326}
    63296327
    6330 void Document::fullScreenChangeDelayTimerFired()
     6328void Document::dispatchFullScreenChangeEvents()
    63316329{
    63326330    // Since we dispatch events in this function, it's possible that the
  • trunk/Source/WebCore/dom/Document.h

    r229448 r229466  
    3636#include "FontSelectorClient.h"
    3737#include "FrameDestructionObserver.h"
     38#include "GenericTaskQueue.h"
    3839#include "MediaProducer.h"
    3940#include "MutationObserver.h"
     
    11371138    RenderFullScreen* fullScreenRenderer() const { return m_fullScreenRenderer.get(); }
    11381139
    1139     void fullScreenChangeDelayTimerFired();
     1140    void dispatchFullScreenChangeEvents();
    11401141    bool fullScreenIsAllowedForElement(Element*) const;
    11411142    void fullScreenElementRemoved();
     
    16841685    Vector<RefPtr<Element>> m_fullScreenElementStack;
    16851686    WeakPtr<RenderFullScreen> m_fullScreenRenderer { nullptr };
    1686     Timer m_fullScreenChangeDelayTimer;
     1687    GenericTaskQueue<Timer> m_fullScreenTaskQueue;
    16871688    Deque<RefPtr<Node>> m_fullScreenChangeEventTargetQueue;
    16881689    Deque<RefPtr<Node>> m_fullScreenErrorEventTargetQueue;
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r229416 r229466  
    25162516    }
    25172517
    2518     bool isPotentiallyPlaying = potentiallyPlaying();
    25192518    if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady) {
    25202519        scheduleEvent(eventNames().canplayEvent);
    2521         if (isPotentiallyPlaying)
    2522             scheduleNotifyAboutPlaying();
    25232520        shouldUpdateDisplayState = true;
    25242521    }
     
    25292526
    25302527        scheduleEvent(eventNames().canplaythroughEvent);
    2531 
    2532         if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA)
    2533             scheduleNotifyAboutPlaying();
    25342528
    25352529        auto success = canTransitionFromAutoplayToPlay();
     
    25402534            m_playbackStartedTime = currentMediaTime().toDouble();
    25412535            scheduleEvent(eventNames().playEvent);
    2542             scheduleNotifyAboutPlaying();
    25432536        } else if (success.value() == MediaPlaybackDenialReason::UserGestureRequired) {
    25442537            ALWAYS_LOG(LOGIDENTIFIER, "Autoplay blocked, user gesture required");
     
    34983491        if (m_readyState <= HAVE_CURRENT_DATA)
    34993492            scheduleEvent(eventNames().waitingEvent);
    3500         else if (m_readyState >= HAVE_FUTURE_DATA)
    3501             scheduleNotifyAboutPlaying();
    35023493    } else if (m_readyState >= HAVE_FUTURE_DATA)
    35033494        scheduleResolvePendingPlayPromises();
     
    47144705                if (!wasSeeking)
    47154706                    addBehaviorRestrictionsOnEndIfNecessary();
    4716 
    47174707                setPlaybackWithoutUserGesture(PlaybackWithoutUserGesture::None);
    47184708            }
     4709            setPlaying(false);
    47194710            // If the media element has a current media controller, then report the controller state
    47204711            // for the media element's current media controller.
     
    53295320
    53305321    m_playing = playing;
     5322
     5323    if (m_playing)
     5324        scheduleNotifyAboutPlaying();
    53315325
    53325326#if ENABLE(MEDIA_SESSION)
Note: See TracChangeset for help on using the changeset viewer.