Changeset 271870 in webkit


Ignore:
Timestamp:
Jan 25, 2021 4:58:00 PM (18 months ago)
Author:
Peng Liu
Message:

Twitter PiP video pauses when scrolling
https://bugs.webkit.org/show_bug.cgi?id=220887

This patch adds two quirks (requiresUserGestureToPauseInPictureInPicture and
requiresUserGestureToLoadInPictureInPicture) for twitter.com, so that when we scroll
the page while a video is in picture-in-picture, the video won't pause or close.

This patch also fixes a race condition related to function MediaElementSession::playbackPermitted()
by adding a parameter (MediaPlaybackOperation) to it. Because of the race condition, we
cannot resume a paused video in a picture-in-picture window on some sites (e.g., twitter.com).
That happens because when we click the play button on the picture-in-picture window to resume
a video, MediaElementSession::playbackPermitted() will be called by
HTMLMediaElement::mediaPlayerDidAddAudioTrack() when HTMLMediaElement::pause() returns false
(means the playback has already been resumed), so the request to add audio track will be rejected
due to the requiresUserGestureToPauseInPictureInPicture quirk and the video will be paused.
This patch fixes this race condition by enabling the requiresUserGestureToPauseInPictureInPicture
quirk only when the playback operation is "pause".

Reviewed by Eric Carlson.

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::load):
(WebCore::HTMLMediaElement::pause):
(WebCore::HTMLMediaElement::suspendPlayback): We should use pauseInternal() instead of pause() here,
otherwise, it will be prevented by the requiresUserGestureToPauseInPictureInPicture quirk.

  • html/MediaElementSession.cpp:

(WebCore::MediaElementSession::playbackPermitted const):

  • html/MediaElementSession.h:
  • page/Quirks.cpp:

(WebCore::Quirks::requiresUserGestureToPauseInPictureInPicture const):
(WebCore::Quirks::requiresUserGestureToLoadInPictureInPicture const):

  • page/Quirks.h:
Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r271866 r271870  
     12021-01-25  Peng Liu  <peng.liu6@apple.com>
     2
     3        Twitter PiP video pauses when scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=220887
     5
     6        This patch adds two quirks (requiresUserGestureToPauseInPictureInPicture and
     7        requiresUserGestureToLoadInPictureInPicture) for twitter.com, so that when we scroll
     8        the page while a video is in picture-in-picture, the video won't pause or close.
     9
     10        This patch also fixes a race condition related to function MediaElementSession::playbackPermitted()
     11        by adding a parameter (MediaPlaybackOperation) to it. Because of the race condition, we
     12        cannot resume a paused video in a picture-in-picture window on some sites (e.g., twitter.com).
     13        That happens because when we click the play button on the picture-in-picture window to resume
     14        a video, MediaElementSession::playbackPermitted() will be called by
     15        HTMLMediaElement::mediaPlayerDidAddAudioTrack() when HTMLMediaElement::pause() returns false
     16        (means the playback has already been resumed), so the request to add audio track will be rejected
     17        due to the requiresUserGestureToPauseInPictureInPicture quirk and the video will be paused.
     18        This patch fixes this race condition by enabling the requiresUserGestureToPauseInPictureInPicture
     19        quirk only when the playback operation is "pause".
     20
     21        Reviewed by Eric Carlson.
     22
     23        * html/HTMLMediaElement.cpp:
     24        (WebCore::HTMLMediaElement::load):
     25        (WebCore::HTMLMediaElement::pause):
     26        (WebCore::HTMLMediaElement::suspendPlayback): We should use pauseInternal() instead of pause() here,
     27        otherwise, it will be prevented by the requiresUserGestureToPauseInPictureInPicture quirk.
     28        * html/MediaElementSession.cpp:
     29        (WebCore::MediaElementSession::playbackPermitted const):
     30        * html/MediaElementSession.h:
     31        * page/Quirks.cpp:
     32        (WebCore::Quirks::requiresUserGestureToPauseInPictureInPicture const):
     33        (WebCore::Quirks::requiresUserGestureToLoadInPictureInPicture const):
     34        * page/Quirks.h:
     35
    1362021-01-25  Sam Weinig  <weinig@apple.com>
    237
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r271806 r271870  
    10751075    INFO_LOG(LOGIDENTIFIER);
    10761076
     1077    if (m_videoFullscreenMode == VideoFullscreenModePictureInPicture && document().quirks().requiresUserGestureToLoadInPictureInPicture() && !document().processingUserGestureForMedia())
     1078        return;
     1079
    10771080    prepareForLoad();
    10781081    m_resourceSelectionTaskQueue.enqueueTask([this] {
     
    34983501        m_waitingToEnterFullscreen = false;
    34993502
    3500     if (!m_mediaSession->playbackPermitted())
     3503    if (!m_mediaSession->playbackPermitted(MediaPlaybackOperation::Pause))
    35013504        return;
    35023505
     
    35063509    pauseInternal();
    35073510}
    3508 
    35093511
    35103512void HTMLMediaElement::pauseInternal()
     
    74477449    ALWAYS_LOG(LOGIDENTIFIER, "paused = ", paused());
    74487450    if (!paused())
    7449         pause();
     7451        pauseInternal();
    74507452}
    74517453
  • trunk/Source/WebCore/html/MediaElementSession.cpp

    r271470 r271870  
    277277}
    278278
    279 SuccessOr<MediaPlaybackDenialReason> MediaElementSession::playbackPermitted() const
     279SuccessOr<MediaPlaybackDenialReason> MediaElementSession::playbackPermitted(MediaPlaybackOperation operation) const
    280280{
    281281    if (m_element.isSuspended()) {
     
    318318    if (topDocument.quirks().requiresUserGestureToPauseInPictureInPicture()
    319319        && m_element.fullscreenMode() & HTMLMediaElementEnums::VideoFullscreenModePictureInPicture
    320         && !m_element.paused()
     320        && !m_element.paused() && operation == MediaPlaybackOperation::Pause
    321321        && !document.processingUserGestureForMedia()) {
    322322        ALWAYS_LOG(LOGIDENTIFIER, "Returning FALSE because a quirk requires a user gesture to pause while in Picture-in-Picture");
  • trunk/Source/WebCore/html/MediaElementSession.h

    r260529 r271870  
    4343};
    4444
     45enum class MediaPlaybackOperation {
     46    All,
     47    Pause
     48};
     49
    4550enum class MediaPlaybackDenialReason {
    4651    UserGestureRequired,
     
    7277    void inActiveDocumentChanged();
    7378
    74     SuccessOr<MediaPlaybackDenialReason> playbackPermitted() const;
     79    // FIXME: <http://webkit.org/b/220939>
     80    SuccessOr<MediaPlaybackDenialReason> playbackPermitted(MediaPlaybackOperation = MediaPlaybackOperation::All) const;
    7581    bool autoplayPermitted() const;
    7682    bool dataLoadingPermitted() const;
  • trunk/Source/WebCore/page/Quirks.cpp

    r271744 r271870  
    12711271bool Quirks::requiresUserGestureToPauseInPictureInPicture() const
    12721272{
    1273     // Facebook will naively pause a <video> element that has scrolled out of the viewport, regardless of whether that element is currently in PiP mode.
     1273#if ENABLE(VIDEO_PRESENTATION_MODE)
     1274    // Facebook and Twitter will naively pause a <video> element that has scrolled out of the viewport,
     1275    // regardless of whether that element is currently in PiP mode.
     1276    // We should remove the quirk once <rdar://problem/67273166> and <rdar://problem/73369869> have been fixed.
    12741277    if (!needsQuirks())
    12751278        return false;
    12761279
    12771280    if (!m_requiresUserGestureToPauseInPictureInPicture) {
     1281        auto domain = RegistrableDomain(m_document->topDocument().url()).string();
     1282        m_requiresUserGestureToPauseInPictureInPicture = domain == "facebook.com"_s || domain == "twitter.com"_s;
     1283    }
     1284
     1285    return *m_requiresUserGestureToPauseInPictureInPicture;
     1286#else
     1287    return false;
     1288#endif
     1289}
     1290
     1291bool Quirks::requiresUserGestureToLoadInPictureInPicture() const
     1292{
     1293#if ENABLE(VIDEO_PRESENTATION_MODE)
     1294    // Twitter will remove the "src" attribute of a <video> element that has scrolled out of the viewport and
     1295    // load the <video> element with an empty "src" regardless of whether that element is currently in PiP mode.
     1296    // We should remove the quirk once <rdar://problem/73369869> has been fixed.
     1297    if (!needsQuirks())
     1298        return false;
     1299
     1300    if (!m_requiresUserGestureToLoadInPictureInPicture) {
    12781301        auto domain = RegistrableDomain(m_document->topDocument().url());
    1279         m_requiresUserGestureToPauseInPictureInPicture = domain.string() == "facebook.com"_s;
    1280     }
    1281 
    1282     return *m_requiresUserGestureToPauseInPictureInPicture;
     1302        m_requiresUserGestureToLoadInPictureInPicture = domain.string() == "twitter.com"_s;
     1303    }
     1304
     1305    return *m_requiresUserGestureToLoadInPictureInPicture;
     1306#else
     1307    return false;
     1308#endif
    12831309}
    12841310
  • trunk/Source/WebCore/page/Quirks.h

    r271667 r271870  
    129129
    130130    bool requiresUserGestureToPauseInPictureInPicture() const;
     131    bool requiresUserGestureToLoadInPictureInPicture() const;
    131132
    132133    WEBCORE_EXPORT bool blocksReturnToFullscreenFromPictureInPictureQuirk() const;
     
    174175    mutable Optional<bool> m_needsBlackFullscreenBackgroundQuirk;
    175176    mutable Optional<bool> m_requiresUserGestureToPauseInPictureInPicture;
     177    mutable Optional<bool> m_requiresUserGestureToLoadInPictureInPicture;
    176178#if ENABLE(MEDIA_STREAM)
    177179    mutable Optional<bool> m_shouldEnableLegacyGetUserMediaQuirk;
Note: See TracChangeset for help on using the changeset viewer.