Enable video autoplay when getUserMedia is on
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 00:43:49 +0000 (00:43 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 00:43:49 +0000 (00:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170919

Patch by Youenn Fablet <youenn@apple.com> on 2017-04-17
Reviewed by Geoffrey Garen.

Source/WebCore:

Test: webrtc/video-autoplay.html

* dom/Document.h:
(WebCore::Document::isCapturing):
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::hasMediaStreamSrcObject):
* html/MediaElementSession.cpp:
(WebCore::MediaElementSession::playbackPermitted): Allowing playback if getUserMedia is capturing audio or video
on the document and if element is rendering MediaStream based content.
* page/MediaProducer.h:
(WebCore::MediaProducer::isCapturing):

LayoutTests:

* webrtc/video-autoplay-expected.txt: Added.
* webrtc/video-autoplay.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215444 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/webrtc/video-autoplay-expected.txt [new file with mode: 0644]
LayoutTests/webrtc/video-autoplay.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/MediaElementSession.cpp
Source/WebCore/page/MediaProducer.h

index 901bdd8..661c834 100644 (file)
@@ -1,3 +1,13 @@
+2017-04-17  Youenn Fablet  <youenn@apple.com>
+
+        Enable video autoplay when getUserMedia is on
+        https://bugs.webkit.org/show_bug.cgi?id=170919
+
+        Reviewed by Geoffrey Garen.
+
+        * webrtc/video-autoplay-expected.txt: Added.
+        * webrtc/video-autoplay.html: Added.
+
 2017-04-17  Ryan Haddad  <ryanhaddad@apple.com>
 
         Skip webrtc/multi-video.html.
diff --git a/LayoutTests/webrtc/video-autoplay-expected.txt b/LayoutTests/webrtc/video-autoplay-expected.txt
new file mode 100644 (file)
index 0000000..122edc2
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+PASS Ensuring autoplay does not work on regular video elements 
+PASS Ensuring autoplay does not work on regular video elements when getUserMedia is on 
+PASS Local media stream autoplay 
+PASS Remote media stream autoplay 
+
diff --git a/LayoutTests/webrtc/video-autoplay.html b/LayoutTests/webrtc/video-autoplay.html
new file mode 100644 (file)
index 0000000..5765d44
--- /dev/null
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing basic video exchange from offerer to receiver</title>
+        <script src="../resources/testharness.js"></script>
+        <script src="../resources/testharnessreport.js"></script>
+        <script src=../media/media-file.js></script>
+        <script src=../media/video-test.js></script>
+    </head>
+    <body>
+        <video id="video" autoplay></video>
+        <script src ="routines.js"></script>
+        <script>
+video = document.getElementById("video");
+
+if (window.internals)
+    internals.setMediaElementRestrictions(video, "RequireUserGestureForVideoRateChange");
+if (window.testRunner)
+    testRunner.setUserMediaPermission(true);
+
+promise_test((test) => {
+    findMediaElement();
+    video.src = findMediaFile("video", "content/test");
+    return video.play().then(() => assert_unreached(), (e) => { assert_equals(e.name, 'NotAllowedError')});
+}, "Ensuring autoplay does not work on regular video elements")
+
+promise_test((test) => {
+    return navigator.mediaDevices.getUserMedia({audio: true, video: true}).then((stream) => {
+        findMediaElement();
+        video.src = findMediaFile("video", "content/test");
+        return video.play().then(() => assert_unreached(), (e) => { assert_equals(e.name, 'NotAllowedError')});
+    });
+}, "Ensuring autoplay does not work on regular video elements when getUserMedia is on");
+
+promise_test((test) => {
+    return navigator.mediaDevices.getUserMedia({audio: true, video: true}).then((stream) => {
+        video.srcObject = stream;
+        return waitFor(10);
+    }).then(() => {
+        return video.play();
+    });
+}, "Local media stream autoplay");
+
+promise_test((test) => {
+    return navigator.mediaDevices.getUserMedia({audio: true, video: true}).then((stream) => {
+        return new Promise((resolve, reject) => {
+            createConnections((firstConnection) => {
+                firstConnection.addTrack(stream.getVideoTracks()[0], stream);
+                firstConnection.addTrack(stream.getAudioTracks()[0], stream);
+            }, (secondConnection) => {
+                var count = 0;
+                secondConnection.ontrack = (trackEvent) => {
+                    if (++count == 2)
+                        resolve(trackEvent.streams[0]);
+                };
+            });
+            setTimeout(() => reject("Test timed out"), 5000);
+        });
+    }).then((stream) => {
+        video.srcObject = stream;
+        return video.play();
+    });
+}, "Remote media stream autoplay");
+
+        </script>
+    </body>
+</html>
index c845825..33021d1 100644 (file)
@@ -1,3 +1,22 @@
+2017-04-17  Youenn Fablet  <youenn@apple.com>
+
+        Enable video autoplay when getUserMedia is on
+        https://bugs.webkit.org/show_bug.cgi?id=170919
+
+        Reviewed by Geoffrey Garen.
+
+        Test: webrtc/video-autoplay.html
+
+        * dom/Document.h:
+        (WebCore::Document::isCapturing):
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::hasMediaStreamSrcObject):
+        * html/MediaElementSession.cpp:
+        (WebCore::MediaElementSession::playbackPermitted): Allowing playback if getUserMedia is capturing audio or video
+        on the document and if element is rendering MediaStream based content.
+        * page/MediaProducer.h:
+        (WebCore::MediaProducer::isCapturing):
+
 2017-04-17  Alex Christensen  <achristensen@webkit.org>
 
         Fix CMake build.
index 1d2ef8f..ffb4f17 100644 (file)
@@ -1248,6 +1248,7 @@ public:
     WEBCORE_EXPORT void addAudioProducer(MediaProducer*);
     WEBCORE_EXPORT void removeAudioProducer(MediaProducer*);
     MediaProducer::MediaStateFlags mediaState() const { return m_mediaState; }
+    bool isCapturing() const { return MediaProducer::isCapturing(m_mediaState); }
     WEBCORE_EXPORT void updateIsPlayingMedia(uint64_t = HTMLMediaElementInvalidID);
     void pageMutedStateDidChange();
     WeakPtr<Document> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
index fe1be6c..4357a05 100644 (file)
@@ -505,6 +505,10 @@ public:
 
     WEBCORE_EXPORT const MediaResourceLoader* lastMediaResourceLoaderForTesting() const;
 
+#if ENABLE(MEDIA_STREAM)
+    bool hasMediaStreamSrcObject() const { return !!m_mediaStreamSrcObject; }
+#endif
+
 protected:
     HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser);
     virtual ~HTMLMediaElement();
index 1ac40dc..2e2cb7e 100644 (file)
@@ -151,10 +151,10 @@ void MediaElementSession::removeBehaviorRestriction(BehaviorRestrictions restric
 SuccessOr<MediaPlaybackDenialReason> MediaElementSession::playbackPermitted(const HTMLMediaElement& element) const
 {
     if (element.document().isMediaDocument() && !element.document().ownerElement())
-        return SuccessOr<MediaPlaybackDenialReason>();
+        return { };
 
     if (pageExplicitlyAllowsElementToAutoplayInline(element))
-        return SuccessOr<MediaPlaybackDenialReason>();
+        return { };
 
     if (requiresFullscreenForVideoPlayback(element) && !fullscreenPermitted(element)) {
         LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE because of fullscreen restriction");
@@ -162,7 +162,10 @@ SuccessOr<MediaPlaybackDenialReason> MediaElementSession::playbackPermitted(cons
     }
 
     if (m_restrictions & OverrideUserGestureRequirementForMainContent && updateIsMainContent())
-        return SuccessOr<MediaPlaybackDenialReason>();
+        return { };
+
+    if (element.document().isCapturing() && element.hasMediaStreamSrcObject())
+        return { };
 
     if (m_restrictions & RequireUserGestureForVideoRateChange && element.isVideo() && !ScriptController::processingUserGestureForMedia()) {
         LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE because of video rate change restriction");
@@ -179,7 +182,7 @@ SuccessOr<MediaPlaybackDenialReason> MediaElementSession::playbackPermitted(cons
         return MediaPlaybackDenialReason::UserGestureRequired;
     }
 
-    return SuccessOr<MediaPlaybackDenialReason>();
+    return { };
 }
 
 bool MediaElementSession::autoplayPermitted() const
index 6b5e513..81b9c89 100644 (file)
@@ -49,6 +49,8 @@ public:
     };
     typedef unsigned MediaStateFlags;
 
+    static bool isCapturing(MediaStateFlags state) { return (state & HasActiveAudioCaptureDevice) || (state & HasActiveVideoCaptureDevice) || (state & HasMutedAudioCaptureDevice) || (state & HasMutedVideoCaptureDevice); }
+
     virtual MediaStateFlags mediaState() const = 0;
 
     enum MutedState {