Title: [221016] trunk
Revision
221016
Author
[email protected]
Date
2017-08-22 09:13:22 -0700 (Tue, 22 Aug 2017)

Log Message

Autoplay Muted Videos Don't Play When Outside Viewport
https://bugs.webkit.org/show_bug.cgi?id=175748
<rdar://problem/33974383>

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/video-restricted-invisible-autoplay-not-allowed-source.html

The media session is notified that its client (the media element) will begin autoplaying inside
prepareForLoad(), where the m_autoplaying flag is also set. But loading via <source> elements does not go
through prepareForLoad(); the HTML standard states that the <source> element loading path does not trigger the
"media element load algorithm" which is implemented in prepareForLoad(). Since the m_autoplaying flag is
initially set to true, notify the media session that the element will begin autoplaying inside the element's
constructor.

Drive-by fix: Doing the above causes other tests to crash, as purturbing play state during style change can cause
re-entrancy in the native controls code, or fail, since we will transition from autoplay -> play even if there's
not yet a src or source to the media element. Add a task queue for updating the autoplay state and check the ready
state before allowing autoplay to transition to play.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::~HTMLMediaElement):
(WebCore::HTMLMediaElement::canTransitionFromAutoplayToPlay const):
(WebCore::HTMLMediaElement::isVisibleInViewportChanged):

LayoutTests:

* media/video-restricted-invisible-autoplay-not-allowed-source-expected.txt: Added.
* media/video-restricted-invisible-autoplay-not-allowed-source.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (221015 => 221016)


--- trunk/LayoutTests/ChangeLog	2017-08-22 16:03:26 UTC (rev 221015)
+++ trunk/LayoutTests/ChangeLog	2017-08-22 16:13:22 UTC (rev 221016)
@@ -1,3 +1,14 @@
+2017-08-22  Jer Noble  <[email protected]>
+
+        Autoplay Muted Videos Don't Play When Outside Viewport
+        https://bugs.webkit.org/show_bug.cgi?id=175748
+        <rdar://problem/33974383>
+
+        Reviewed by Eric Carlson.
+
+        * media/video-restricted-invisible-autoplay-not-allowed-source-expected.txt: Added.
+        * media/video-restricted-invisible-autoplay-not-allowed-source.html: Added.
+
 2017-08-21  Matt Rajca  <[email protected]>
 
         Call updateIsPlayingMedia whenever m_userHasInteractedWithMediaElement changes

Added: trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source-expected.txt (0 => 221016)


--- trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source-expected.txt	2017-08-22 16:13:22 UTC (rev 221016)
@@ -0,0 +1,21 @@
+
+Test that "invisible autoplay not allowed restriction" pauses media when scrolled out of view.
+
+** setting video source.src
+
+EVENT(play)
+RUN(video.style.display = "none")
+EVENT(pause)
+RUN(video.style.removeProperty("display"))
+EVENT(play)
+RUN(video.style.visibility = "hidden")
+EVENT(pause)
+RUN(video.style.removeProperty("visibility"))
+EVENT(play)
+RUN(document.documentElement.style.height = window.innerHeight + 20 + video.offsetHeight)
+RUN(window.scrollBy(0, 20 + video.offsetHeight))
+EVENT(pause)
+RUN(window.scrollTo(0, 0))
+EVENT(play)
+END OF TEST
+

Added: trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source.html (0 => 221016)


--- trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-source.html	2017-08-22 16:13:22 UTC (rev 221016)
@@ -0,0 +1,65 @@
+<html>
+    <head>
+        <script src=""
+        <script src=""
+        <script>
+            if (window.internals)
+                internals.settings.setInvisibleAutoplayNotPermitted(true);
+
+            function start()
+            {
+                findMediaElement();
+                consoleWrite('** setting video source.src');
+                var source = document.createElement('source');
+                source.src = "" 'content/test');
+                video.appendChild(source);
+                video.muted = true;
+
+                waitForEventOnce('play', play1);
+                consoleWrite('');
+            }
+
+            function play1()
+            {
+                run('video.style.display = "none"');
+                waitForEventOnce('pause', pause1);
+            }
+
+            function pause1()
+            {
+                run('video.style.removeProperty("display")')
+                waitForEventOnce('play', play2);
+            }
+
+            function play2()
+            {
+                run('video.style.visibility = "hidden"');
+                waitForEventOnce('pause', pause2);
+            }
+
+            function pause2()
+            {
+                run('video.style.removeProperty("visibility")');
+                waitForEventOnce('play', play3);
+            }
+
+            function play3()
+            {
+                run('document.documentElement.style.height = window.innerHeight + 20 + video.offsetHeight');
+                run('window.scrollBy(0, 20 + video.offsetHeight)');
+                waitForEventOnce('pause', pause3);
+            }
+
+            function pause3()
+            {
+                run('window.scrollTo(0, 0)');
+                waitForEventOnce('play', endTest);
+            }
+        </script>
+    </head>
+
+    <body _onload_="start()">
+        <video autoplay></video>
+        <p>Test that "invisible autoplay not allowed restriction" pauses media when scrolled out of view.</p>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (221015 => 221016)


--- trunk/Source/WebCore/ChangeLog	2017-08-22 16:03:26 UTC (rev 221015)
+++ trunk/Source/WebCore/ChangeLog	2017-08-22 16:13:22 UTC (rev 221016)
@@ -1,3 +1,31 @@
+2017-08-22  Jer Noble  <[email protected]>
+
+        Autoplay Muted Videos Don't Play When Outside Viewport
+        https://bugs.webkit.org/show_bug.cgi?id=175748
+        <rdar://problem/33974383>
+
+        Reviewed by Eric Carlson.
+
+        Test: media/video-restricted-invisible-autoplay-not-allowed-source.html
+
+        The media session is notified that its client (the media element) will begin autoplaying inside
+        prepareForLoad(), where the m_autoplaying flag is also set. But loading via <source> elements does not go
+        through prepareForLoad(); the HTML standard states that the <source> element loading path does not trigger the
+        "media element load algorithm" which is implemented in prepareForLoad(). Since the m_autoplaying flag is
+        initially set to true, notify the media session that the element will begin autoplaying inside the element's
+        constructor.
+
+        Drive-by fix: Doing the above causes other tests to crash, as purturbing play state during style change can cause
+        re-entrancy in the native controls code, or fail, since we will transition from autoplay -> play even if there's
+        not yet a src or source to the media element. Add a task queue for updating the autoplay state and check the ready
+        state before allowing autoplay to transition to play.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (WebCore::HTMLMediaElement::~HTMLMediaElement):
+        (WebCore::HTMLMediaElement::canTransitionFromAutoplayToPlay const):
+        (WebCore::HTMLMediaElement::isVisibleInViewportChanged):
+
 2017-08-21  Matt Rajca  <[email protected]>
 
         Call updateIsPlayingMedia whenever m_userHasInteractedWithMediaElement changes

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (221015 => 221016)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2017-08-22 16:03:26 UTC (rev 221015)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2017-08-22 16:13:22 UTC (rev 221016)
@@ -519,6 +519,8 @@
 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
     AudioSession::sharedSession().addMutedStateObserver(this);
 #endif
+
+    mediaSession().clientWillBeginAutoplaying();
 }
 
 HTMLMediaElement::~HTMLMediaElement()
@@ -595,6 +597,7 @@
     m_updatePlaybackControlsManagerQueue.close();
     m_playbackControlsManagerBehaviorRestrictionsQueue.close();
     m_resourceSelectionTaskQueue.close();
+    m_visibilityChangeTaskQueue.close();
 #if ENABLE(ENCRYPTED_MEDIA)
     m_encryptedMediaQueue.close();
 #endif
@@ -2332,11 +2335,12 @@
 SuccessOr<MediaPlaybackDenialReason> HTMLMediaElement::canTransitionFromAutoplayToPlay() const
 {
     if (isAutoplaying()
-     && mediaSession().autoplayPermitted()
-     && paused()
-     && autoplay()
-     && !pausedForUserInteraction()
-     && !document().isSandboxed(SandboxAutomaticFeatures))
+        && mediaSession().autoplayPermitted()
+        && paused()
+        && autoplay()
+        && !pausedForUserInteraction()
+        && !document().isSandboxed(SandboxAutomaticFeatures)
+        && m_readyState == HAVE_ENOUGH_DATA)
         return mediaSession().playbackPermitted(*this);
 
     RELEASE_LOG(Media, "HTMLMediaElement::canTransitionFromAutoplayToPlay - page consent required");
@@ -7621,8 +7625,10 @@
 
 void HTMLMediaElement::isVisibleInViewportChanged()
 {
-    updateShouldAutoplay();
-    scheduleUpdatePlaybackControlsManager();
+    m_visibilityChangeTaskQueue.enqueueTask([this] {
+        updateShouldAutoplay();
+        scheduleUpdatePlaybackControlsManager();
+    });
 }
 
 void HTMLMediaElement::updateShouldAutoplay()

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (221015 => 221016)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2017-08-22 16:03:26 UTC (rev 221015)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2017-08-22 16:13:22 UTC (rev 221016)
@@ -901,6 +901,7 @@
     GenericTaskQueue<Timer> m_updatePlaybackControlsManagerQueue;
     GenericTaskQueue<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue;
     GenericTaskQueue<Timer> m_resourceSelectionTaskQueue;
+    GenericTaskQueue<Timer> m_visibilityChangeTaskQueue;
     RefPtr<TimeRanges> m_playedTimeRanges;
     GenericEventQueue m_asyncEventQueue;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to