Diff
Modified: trunk/LayoutTests/ChangeLog (232299 => 232300)
--- trunk/LayoutTests/ChangeLog 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/LayoutTests/ChangeLog 2018-05-30 18:00:23 UTC (rev 232300)
@@ -1,3 +1,14 @@
+2018-05-30 Jer Noble <[email protected]>
+
+ Media elements outside fullscreen should not be considered main content.
+ https://bugs.webkit.org/show_bug.cgi?id=186063
+ <rdar://problem/40630437>
+
+ Reviewed by Eric Carlson.
+
+ * platform/mac/media/video-best-element-for-playback-controls-purpose-expected.txt: Added.
+ * platform/mac/media/video-best-element-for-playback-controls-purpose.html: Added.
+
2018-05-30 Ms2ger <[email protected]>
[GTK] Unreviewed test gardening
Added: trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose-expected.txt (0 => 232300)
--- trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose-expected.txt 2018-05-30 18:00:23 UTC (rev 232300)
@@ -0,0 +1,49 @@
+
+Unloaded video elements should not be considered main content.
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+
+Large, autoplay videos with video and audio should be considered main content.
+RUN(video = createVideo({autoplay: true, type: "audio+video", size: "large"}))
+EVENT(playing)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == '[object HTMLVideoElement]') OK
+
+Small, autoplay videos with video and audio should be considered main content.
+RUN(video = createVideo({autoplay: true, type: "audio+video", size: "small"}))
+EVENT(playing)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+
+Muted autoplay videos should not be considered main content.
+RUN(video = createVideo({autoplay: true, muted: true, type: "audio+video", size: "large"}))
+EVENT(playing)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+
+Video-only autoplay videos should not be considered main content.
+RUN(video = createVideo({autoplay: true, type: "video", size: "large"}))
+EVENT(playing)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+
+Non-playing videos should not be considered main content.
+RUN(video = createVideo({type: "audio+video", size: "large"}))
+EVENT(canplaythrough)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+
+Large, autoplay videos outside fullscreen element should not be considered main content
+RUN(video = createVideo({autoplay: true, muted: true, type: "audio+video", size: "large"}))
+EVENT(playing)
+RUN(document.querySelector("#fullscreen").webkitRequestFullscreen())
+EVENT(webkitfullscreenchange)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == 'null') OK
+RUN(document.webkitExitFullscreen())
+EVENT(webkitfullscreenchange)
+
+Large, autoplay videos inside fullscreen element should be considered main content
+RUN(video = createVideo({autoplay: true, type: "audio+video", size: "large"}))
+EVENT(playing)
+RUN(document.querySelector("#target").webkitRequestFullscreen())
+EVENT(webkitfullscreenchange)
+EXPECTED (internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager") == '[object HTMLVideoElement]') OK
+RUN(document.webkitExitFullscreen())
+EVENT(webkitfullscreenchange)
+
+END OF TEST
+
Added: trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose.html (0 => 232300)
--- trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose.html (rev 0)
+++ trunk/LayoutTests/platform/mac/media/video-best-element-for-playback-controls-purpose.html 2018-05-30 18:00:23 UTC (rev 232300)
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>audio-session-category-track-change</title>
+ <script src=""
+ <script src=""
+ <script>
+ async function go() {
+ for (test of tests) {
+ await test();
+ consoleWrite('');
+ }
+ endTest();
+ }
+
+ function createVideo(parameters) {
+ let target = document.querySelector('#target');
+ target.innerHTML = '';
+
+ let video = document.createElement('video');
+ target.appendChild(video);
+
+ if (!parameters)
+ return video;
+
+ if (parameters.autoplay)
+ video.autoplay = parameters.autoplay;
+
+ if (parameters.muted)
+ video.muted = parameters.muted;
+
+ if (parameters.size) {
+ if (parameters.size === 'large') {
+ video.width = 640;
+ video.height = 480;
+ } else if (parameters.size === 'small') {
+ video.width = 320;
+ video.height = 240;
+ }
+ }
+
+ if (parameters.type) {
+ if (parameters.type === 'audio+video')
+ video.src = "" "../../../media/content/test");
+ else if (parameters.type === 'video')
+ video.src = "" "../../../media/content/long-test");
+ }
+
+ return video;
+ }
+
+ function enterFullscreen(target) {
+ runWithKeyDown(`document.querySelector("${target}").webkitRequestFullscreen()`);
+ return waitFor(document, 'webkitfullscreenchange');
+ }
+
+ function exitFullscreen() {
+ runWithKeyDown('document.webkitExitFullscreen()');
+ return waitFor(document, 'webkitfullscreenchange');
+ }
+
+ let tests = [
+ function() {
+ consoleWrite('Unloaded video elements should not be considered main content.');
+ video = createVideo();
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null)
+ },
+
+ async function() {
+ consoleWrite('Large, autoplay videos with video and audio should be considered main content.')
+ run('video = createVideo({autoplay: true, type: "audio+video", size: "large"})');
+ await waitFor(video, 'playing');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', video)
+ },
+
+ async function() {
+ consoleWrite('Small, autoplay videos with video and audio should be considered main content.')
+ run('video = createVideo({autoplay: true, type: "audio+video", size: "small"})');
+ await waitFor(video, 'playing');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null)
+ },
+
+ async function() {
+ consoleWrite('Muted autoplay videos should not be considered main content.')
+ run('video = createVideo({autoplay: true, muted: true, type: "audio+video", size: "large"})');
+ await waitFor(video, 'playing');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null)
+ },
+
+ async function() {
+ consoleWrite('Video-only autoplay videos should not be considered main content.')
+ run('video = createVideo({autoplay: true, type: "video", size: "large"})');
+ await waitFor(video, 'playing');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null)
+ },
+
+ async function() {
+ consoleWrite('Non-playing videos should not be considered main content.')
+ run('video = createVideo({type: "audio+video", size: "large"})');
+ await waitFor(video, 'canplaythrough');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null)
+ },
+
+ async function() {
+ consoleWrite('Large, autoplay videos outside fullscreen element should not be considered main content');
+ run('video = createVideo({autoplay: true, muted: true, type: "audio+video", size: "large"})');
+ await waitFor(video, 'playing');
+ await enterFullscreen('#fullscreen');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', null);
+ await exitFullscreen();
+ },
+
+ async function() {
+ consoleWrite('Large, autoplay videos inside fullscreen element should be considered main content');
+ run('video = createVideo({autoplay: true, type: "audio+video", size: "large"})');
+ await waitFor(video, 'playing');
+ await enterFullscreen('#target');
+ testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("ControlsManager")', video);
+ await exitFullscreen();
+ },
+ ];
+
+ </script>
+</head>
+<body _onload_="go()">
+ <div id="target"></div>
+ <div id="fullscreen"></div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (232299 => 232300)
--- trunk/Source/WebCore/ChangeLog 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/ChangeLog 2018-05-30 18:00:23 UTC (rev 232300)
@@ -1,3 +1,29 @@
+2018-05-30 Jer Noble <[email protected]>
+
+ Media elements outside fullscreen should not be considered main content.
+ https://bugs.webkit.org/show_bug.cgi?id=186063
+ <rdar://problem/40630437>
+
+ Reviewed by Eric Carlson.
+
+ Test: platform/mac/media/video-best-element-for-playback-controls-purpose.html
+
+ Media elements outside the current fullscreen element are not visible, and thus should not be considered
+ main content.
+
+ Drive-by fix: set the m_hasEverNotifiedAboutPlaying before dispatching the 'playing' event, so that
+ tests can check bestMediaElementForShowingPlaybackControlsManager() in the 'playing' handler.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::notifyAboutPlaying):
+ * html/HTMLMediaElement.h:
+ * html/MediaElementSession.cpp:
+ (WebCore::MediaElementSession::canShowControlsManager const):
+ * testing/Internals.cpp:
+ (WebCore::Internals::bestMediaElementForShowingPlaybackControlsManager):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2018-05-30 Michael Catanzaro <[email protected]>
Unreviewed, silence a -Wreturn-type warning
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (232299 => 232300)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-05-30 18:00:23 UTC (rev 232300)
@@ -1120,10 +1120,10 @@
{
Ref<HTMLMediaElement> protectedThis(*this); // The 'playing' event can make arbitrary DOM mutations.
m_playbackStartedTime = currentMediaTime().toDouble();
+ m_hasEverNotifiedAboutPlaying = true;
dispatchEvent(Event::create(eventNames().playingEvent, false, true));
resolvePendingPlayPromises(WTFMove(pendingPlayPromises));
- m_hasEverNotifiedAboutPlaying = true;
scheduleUpdatePlaybackControlsManager();
}
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (232299 => 232300)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2018-05-30 18:00:23 UTC (rev 232300)
@@ -155,7 +155,7 @@
static HashSet<HTMLMediaElement*>& allMediaElements();
- static HTMLMediaElement* bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose);
+ WEBCORE_EXPORT static HTMLMediaElement* bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose);
static bool isRunningDestructor();
Modified: trunk/Source/WebCore/html/MediaElementSession.cpp (232299 => 232300)
--- trunk/Source/WebCore/html/MediaElementSession.cpp 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/html/MediaElementSession.cpp 2018-05-30 18:00:23 UTC (rev 232300)
@@ -473,6 +473,15 @@
return false;
}
+#if ENABLE(FULLSCREEN_API)
+ // Elements which are not descendents of the current fullscreen element cannot be main content.
+ auto* fullscreenElement = m_element.document().webkitCurrentFullScreenElement();
+ if (fullscreenElement && !m_element.isDescendantOf(*fullscreenElement)) {
+ INFO_LOG(LOGIDENTIFIER, "returning FALSE: outside of full screen");
+ return false;
+ }
+#endif
+
// Only allow the main content heuristic to forbid videos from showing up if our purpose is the controls manager.
if (purpose == PlaybackControlsPurpose::ControlsManager && m_element.isVideo()) {
if (!m_element.renderer()) {
Modified: trunk/Source/WebCore/testing/Internals.cpp (232299 => 232300)
--- trunk/Source/WebCore/testing/Internals.cpp 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/testing/Internals.cpp 2018-05-30 18:00:23 UTC (rev 232300)
@@ -3707,6 +3707,13 @@
#endif
}
+#if ENABLE(VIDEO)
+HTMLMediaElement* Internals::bestMediaElementForShowingPlaybackControlsManager(Internals::PlaybackControlsPurpose purpose)
+{
+ return HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(purpose);
+}
+#endif
+
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void Internals::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
Modified: trunk/Source/WebCore/testing/Internals.h (232299 => 232300)
--- trunk/Source/WebCore/testing/Internals.h 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/testing/Internals.h 2018-05-30 18:00:23 UTC (rev 232300)
@@ -40,6 +40,10 @@
#include "MediaSessionInterruptionProvider.h"
#endif
+#if ENABLE(VIDEO)
+#include "MediaElementSession.h"
+#endif
+
namespace WebCore {
class AnimationTimeline;
@@ -680,6 +684,9 @@
};
ExceptionOr<NowPlayingState> nowPlayingState() const;
+ using PlaybackControlsPurpose = MediaElementSession::PlaybackControlsPurpose;
+ HTMLMediaElement* bestMediaElementForShowingPlaybackControlsManager(PlaybackControlsPurpose);
+
private:
explicit Internals(Document&);
Document* contextDocument() const;
Modified: trunk/Source/WebCore/testing/Internals.idl (232299 => 232300)
--- trunk/Source/WebCore/testing/Internals.idl 2018-05-30 17:46:49 UTC (rev 232299)
+++ trunk/Source/WebCore/testing/Internals.idl 2018-05-30 18:00:23 UTC (rev 232300)
@@ -82,6 +82,11 @@
"unresponsive"
};
+[Conditional=VIDEO] enum PlaybackControlsPurpose {
+ "ControlsManager",
+ "NowPlaying"
+};
+
[
ExportMacro=WEBCORE_TESTSUPPORT_EXPORT,
Conditional=VIDEO,
@@ -616,4 +621,6 @@
boolean usingAppleInternalSDK();
[Conditional=VIDEO, MayThrowException] readonly attribute NowPlayingState nowPlayingState;
+
+ [Conditional=VIDEO] HTMLMediaElement bestMediaElementForShowingPlaybackControlsManager(PlaybackControlsPurpose purpose);
};