haikuwebkit/LayoutTests/media/video-restricted-invisible-...

64 lines
1.9 KiB
HTML
Raw Permalink Normal View History

Add a setting and restriction which will pause invisible autoplaying video https://bugs.webkit.org/show_bug.cgi?id=151412 Reviewed by Eric Carlson. Source/WebCore: Test: media/video-restricted-invisible-autoplay-not-allowed.html Drive-by fix: m_autoplaying is reset in many places by calling pause() or play(), where those calls did not originate from an explicit request to pause or play, e.g., during an interruption. This causes m_autoplaying to be set to false, thus breaking resumption of autoplaying when the interruption ends. Update PlatformMediaSession to remember its client's "autoplaying" state and restore it when an interruption ends. Add a means to register for viewport visibility notifications to FrameView, RenderView, and RenderElement. Elements who wish to recieve these notifications must do so through their renderer, and thus will have to re-register whenever a new renderer is attached. Add a restriction to HTMLMediaElement which will pause autoplaying video when that video scrolls out of the viewport, or is hidden with CSS. Add a setting which controls whether that new restriction is set. * dom/Element.h: (WebCore::Element::isVisibleInViewportChanged): Add default empty virtual method. * html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::HTMLMediaElement): (WebCore::HTMLMediaElement::didMoveToNewDocument): (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): (WebCore::HTMLMediaElement::resumeAutoplaying): (WebCore::mediaElementIsAllowedToAutoplay): (WebCore::HTMLMediaElement::isVisibleInViewportChanged): (WebCore::HTMLMediaElement::updateShouldAutoplay): (WebCore::HTMLMediaElement::HTMLMediaElement): Set the new restriction based on the current Settings. (WebCore::HTMLMediaElement::resumeAutoplaying): Continue autoplay, or begin playback. (WebCore::HTMLMediaElement::didMoveToNewDocument): Update our autoplay state. (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): Ditto. (WebCore::HTMLMediaElement::removedFrom): Ditto. (WebCore::HTMLMediaElement::didAttachRenderers): Ditto. (WebCore::HTMLMediaElement::didDetachRenderers): Ditto. (WebCore::HTMLMediaElement::visibilityDidChange): Ditto. (WebCore::HTMLMediaElement::willDetachRenderers): Unregister for visibility callbacks. (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): Clear new restriction. (WebCore::mediaElementIsAllowedToAutoplay): Check for autoplay requirements. (WebCore::HTMLMediaElement::isVisibleInViewportChanged): Added, update our autoplay state. (WebCore::HTMLMediaElement::updateShouldAutoplay): Set interruption if necessary, clear otherwise. * html/HTMLMediaElement.h: * html/MediaElementSession.cpp: (WebCore::restrictionName): Added support for new restriction. * html/MediaElementSession.h: * page/FrameView.cpp: (WebCore::FrameView::viewportContentsChanged): Update clients of viewport visibility. * page/Settings.in: * platform/audio/PlatformMediaSession.cpp: (WebCore::stateName): Add new "Autoplay" state. (WebCore::interruptionName): Added new interruption type. (WebCore::PlatformMediaSession::beginInterruption): Set the m_interruptionType. (WebCore::PlatformMediaSession::clientWillBeginAutoplaying): Set the m_state to Autoplaying. * platform/audio/PlatformMediaSession.h: (WebCore::PlatformMediaSession::interruptionType): Added getter. (WebCore::PlatformMediaSessionClient::resumeAutoplaying): Added default. * platform/audio/PlatformMediaSessionManager.cpp: (WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback): Only pause session if its state is playing. * rendering/RenderElement.cpp: (WebCore::RenderElement::RenderElement): Set new ivars. (WebCore::RenderElement::~RenderElement): Unregister for callbacks if necessary. (WebCore::RenderElement::registerForVisibleInViewportCallback): Register for callbacks from RenderView. (WebCore::RenderElement::unregisterForVisibleInViewportCallback): Unregister from same. (WebCore::RenderElement::visibleInViewportStateChanged): Notify Element if value has changed. * rendering/RenderElement.h: * rendering/RenderView.cpp: (WebCore::RenderView::registerForVisibleInViewportCallback): Add renderer to list of callbacks. (WebCore::RenderView::unregisterForVisibleInViewportCallback): Remove renderer from same. (WebCore::RenderView::updateVisibleViewportRect): Walk renderers setting their visiblility based on the viewport visible rect. * rendering/RenderView.h: * testing/Internals.cpp: (WebCore::Internals::setMediaElementRestrictions): Support new restriction. LayoutTests: * media/video-restricted-invisible-autoplay-not-allowed-expected.txt: Added. * media/video-restricted-invisible-autoplay-not-allowed.html: Added. Canonical link: https://commits.webkit.org/169911@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@192966 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-12-02 22:09:58 +00:00
<html>
<head>
<script src="media-file.js"></script>
<script src="video-test.js"></script>
<script>
Allow multiple playing videos on a page with 'autoplay' and 'playsinline' attributes https://bugs.webkit.org/show_bug.cgi?id=162366 <rdar://problem/28639600> Reviewed by Eric Carlson. Source/WebCore: Tests: media/video-concurrent-visible-playback.html media/video-multiple-concurrent-playback.html Separate out the concept of "video-only" from "video-with-audio" in PlatformMediaSession::MediaType, and only set the ConcurrentPlaybackNotPermitted restriction for "video-with-audio". This allows multiple silent video elements to play back simultaneously. However, the bug in question also shows bad behavior when both concurrent playback and invisible playback are not allowed. Namely, an invisible element will attempt to autoplay, interrupt visible elements, and then fail to play due to it's non-visibility. Add an extra check to canTransitionFromAutoplayToPlay() which asks the session if autoplay is allowed (which will return false if the element is not visible). * html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::canTransitionFromAutoplayToPlay): (WebCore::HTMLMediaElement::mediaType): (WebCore::HTMLMediaElement::presentationType): (WebCore::HTMLMediaElement::updateShouldAutoplay): (WebCore::mediaElementIsAllowedToAutoplay): Deleted. * html/MediaElementSession.cpp: (WebCore::MediaElementSession::autoplayPermitted): * html/MediaElementSession.h: * platform/audio/PlatformMediaSession.h: * platform/audio/ios/MediaSessionManagerIOS.mm: (WebCore::MediaSessionManageriOS::resetRestrictions): * testing/Internals.cpp: (WebCore::Internals::setMediaSessionRestrictions): LayoutTests: * media/content/test-video-only.mp4: Added. * media/non-existent-video-playback-interrupted-expected.txt: * media/non-existent-video-playback-interrupted.html: * media/video-background-playback-expected.txt: * media/video-background-playback.html: * media/video-background-tab-playback-expected.txt: * media/video-background-tab-playback.html: * media/video-concurrent-playback-expected.txt: * media/video-concurrent-playback.html: * media/video-concurrent-visible-playback-expected.txt: Added. * media/video-concurrent-visible-playback.html: Added. * media/video-multiple-concurrent-playback-expected.txt: Added. * media/video-multiple-concurrent-playback.html: Added. * media/video-playback-interrupted-expected.txt: * media/video-playback-interrupted.html: * media/video-restricted-invisible-autoplay-not-allowed.html: Canonical link: https://commits.webkit.org/181931@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208149 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-31 16:36:00 +00:00
if (window.internals)
internals.settings.setInvisibleAutoplayNotPermitted(true);
Add a setting and restriction which will pause invisible autoplaying video https://bugs.webkit.org/show_bug.cgi?id=151412 Reviewed by Eric Carlson. Source/WebCore: Test: media/video-restricted-invisible-autoplay-not-allowed.html Drive-by fix: m_autoplaying is reset in many places by calling pause() or play(), where those calls did not originate from an explicit request to pause or play, e.g., during an interruption. This causes m_autoplaying to be set to false, thus breaking resumption of autoplaying when the interruption ends. Update PlatformMediaSession to remember its client's "autoplaying" state and restore it when an interruption ends. Add a means to register for viewport visibility notifications to FrameView, RenderView, and RenderElement. Elements who wish to recieve these notifications must do so through their renderer, and thus will have to re-register whenever a new renderer is attached. Add a restriction to HTMLMediaElement which will pause autoplaying video when that video scrolls out of the viewport, or is hidden with CSS. Add a setting which controls whether that new restriction is set. * dom/Element.h: (WebCore::Element::isVisibleInViewportChanged): Add default empty virtual method. * html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::HTMLMediaElement): (WebCore::HTMLMediaElement::didMoveToNewDocument): (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): (WebCore::HTMLMediaElement::resumeAutoplaying): (WebCore::mediaElementIsAllowedToAutoplay): (WebCore::HTMLMediaElement::isVisibleInViewportChanged): (WebCore::HTMLMediaElement::updateShouldAutoplay): (WebCore::HTMLMediaElement::HTMLMediaElement): Set the new restriction based on the current Settings. (WebCore::HTMLMediaElement::resumeAutoplaying): Continue autoplay, or begin playback. (WebCore::HTMLMediaElement::didMoveToNewDocument): Update our autoplay state. (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): Ditto. (WebCore::HTMLMediaElement::removedFrom): Ditto. (WebCore::HTMLMediaElement::didAttachRenderers): Ditto. (WebCore::HTMLMediaElement::didDetachRenderers): Ditto. (WebCore::HTMLMediaElement::visibilityDidChange): Ditto. (WebCore::HTMLMediaElement::willDetachRenderers): Unregister for visibility callbacks. (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): Clear new restriction. (WebCore::mediaElementIsAllowedToAutoplay): Check for autoplay requirements. (WebCore::HTMLMediaElement::isVisibleInViewportChanged): Added, update our autoplay state. (WebCore::HTMLMediaElement::updateShouldAutoplay): Set interruption if necessary, clear otherwise. * html/HTMLMediaElement.h: * html/MediaElementSession.cpp: (WebCore::restrictionName): Added support for new restriction. * html/MediaElementSession.h: * page/FrameView.cpp: (WebCore::FrameView::viewportContentsChanged): Update clients of viewport visibility. * page/Settings.in: * platform/audio/PlatformMediaSession.cpp: (WebCore::stateName): Add new "Autoplay" state. (WebCore::interruptionName): Added new interruption type. (WebCore::PlatformMediaSession::beginInterruption): Set the m_interruptionType. (WebCore::PlatformMediaSession::clientWillBeginAutoplaying): Set the m_state to Autoplaying. * platform/audio/PlatformMediaSession.h: (WebCore::PlatformMediaSession::interruptionType): Added getter. (WebCore::PlatformMediaSessionClient::resumeAutoplaying): Added default. * platform/audio/PlatformMediaSessionManager.cpp: (WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback): Only pause session if its state is playing. * rendering/RenderElement.cpp: (WebCore::RenderElement::RenderElement): Set new ivars. (WebCore::RenderElement::~RenderElement): Unregister for callbacks if necessary. (WebCore::RenderElement::registerForVisibleInViewportCallback): Register for callbacks from RenderView. (WebCore::RenderElement::unregisterForVisibleInViewportCallback): Unregister from same. (WebCore::RenderElement::visibleInViewportStateChanged): Notify Element if value has changed. * rendering/RenderElement.h: * rendering/RenderView.cpp: (WebCore::RenderView::registerForVisibleInViewportCallback): Add renderer to list of callbacks. (WebCore::RenderView::unregisterForVisibleInViewportCallback): Remove renderer from same. (WebCore::RenderView::updateVisibleViewportRect): Walk renderers setting their visiblility based on the viewport visible rect. * rendering/RenderView.h: * testing/Internals.cpp: (WebCore::Internals::setMediaElementRestrictions): Support new restriction. LayoutTests: * media/video-restricted-invisible-autoplay-not-allowed-expected.txt: Added. * media/video-restricted-invisible-autoplay-not-allowed.html: Added. Canonical link: https://commits.webkit.org/169911@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@192966 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-12-02 22:09:58 +00:00
function start()
{
findMediaElement();
consoleWrite('** setting video.src');
video.src = findMediaFile('video', 'content/test');
video.muted = true;
Add a setting and restriction which will pause invisible autoplaying video https://bugs.webkit.org/show_bug.cgi?id=151412 Reviewed by Eric Carlson. Source/WebCore: Test: media/video-restricted-invisible-autoplay-not-allowed.html Drive-by fix: m_autoplaying is reset in many places by calling pause() or play(), where those calls did not originate from an explicit request to pause or play, e.g., during an interruption. This causes m_autoplaying to be set to false, thus breaking resumption of autoplaying when the interruption ends. Update PlatformMediaSession to remember its client's "autoplaying" state and restore it when an interruption ends. Add a means to register for viewport visibility notifications to FrameView, RenderView, and RenderElement. Elements who wish to recieve these notifications must do so through their renderer, and thus will have to re-register whenever a new renderer is attached. Add a restriction to HTMLMediaElement which will pause autoplaying video when that video scrolls out of the viewport, or is hidden with CSS. Add a setting which controls whether that new restriction is set. * dom/Element.h: (WebCore::Element::isVisibleInViewportChanged): Add default empty virtual method. * html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::HTMLMediaElement): (WebCore::HTMLMediaElement::didMoveToNewDocument): (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): (WebCore::HTMLMediaElement::resumeAutoplaying): (WebCore::mediaElementIsAllowedToAutoplay): (WebCore::HTMLMediaElement::isVisibleInViewportChanged): (WebCore::HTMLMediaElement::updateShouldAutoplay): (WebCore::HTMLMediaElement::HTMLMediaElement): Set the new restriction based on the current Settings. (WebCore::HTMLMediaElement::resumeAutoplaying): Continue autoplay, or begin playback. (WebCore::HTMLMediaElement::didMoveToNewDocument): Update our autoplay state. (WebCore::HTMLMediaElement::documentDidResumeFromPageCache): Ditto. (WebCore::HTMLMediaElement::removedFrom): Ditto. (WebCore::HTMLMediaElement::didAttachRenderers): Ditto. (WebCore::HTMLMediaElement::didDetachRenderers): Ditto. (WebCore::HTMLMediaElement::visibilityDidChange): Ditto. (WebCore::HTMLMediaElement::willDetachRenderers): Unregister for visibility callbacks. (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): Clear new restriction. (WebCore::mediaElementIsAllowedToAutoplay): Check for autoplay requirements. (WebCore::HTMLMediaElement::isVisibleInViewportChanged): Added, update our autoplay state. (WebCore::HTMLMediaElement::updateShouldAutoplay): Set interruption if necessary, clear otherwise. * html/HTMLMediaElement.h: * html/MediaElementSession.cpp: (WebCore::restrictionName): Added support for new restriction. * html/MediaElementSession.h: * page/FrameView.cpp: (WebCore::FrameView::viewportContentsChanged): Update clients of viewport visibility. * page/Settings.in: * platform/audio/PlatformMediaSession.cpp: (WebCore::stateName): Add new "Autoplay" state. (WebCore::interruptionName): Added new interruption type. (WebCore::PlatformMediaSession::beginInterruption): Set the m_interruptionType. (WebCore::PlatformMediaSession::clientWillBeginAutoplaying): Set the m_state to Autoplaying. * platform/audio/PlatformMediaSession.h: (WebCore::PlatformMediaSession::interruptionType): Added getter. (WebCore::PlatformMediaSessionClient::resumeAutoplaying): Added default. * platform/audio/PlatformMediaSessionManager.cpp: (WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback): Only pause session if its state is playing. * rendering/RenderElement.cpp: (WebCore::RenderElement::RenderElement): Set new ivars. (WebCore::RenderElement::~RenderElement): Unregister for callbacks if necessary. (WebCore::RenderElement::registerForVisibleInViewportCallback): Register for callbacks from RenderView. (WebCore::RenderElement::unregisterForVisibleInViewportCallback): Unregister from same. (WebCore::RenderElement::visibleInViewportStateChanged): Notify Element if value has changed. * rendering/RenderElement.h: * rendering/RenderView.cpp: (WebCore::RenderView::registerForVisibleInViewportCallback): Add renderer to list of callbacks. (WebCore::RenderView::unregisterForVisibleInViewportCallback): Remove renderer from same. (WebCore::RenderView::updateVisibleViewportRect): Walk renderers setting their visiblility based on the viewport visible rect. * rendering/RenderView.h: * testing/Internals.cpp: (WebCore::Internals::setMediaElementRestrictions): Support new restriction. LayoutTests: * media/video-restricted-invisible-autoplay-not-allowed-expected.txt: Added. * media/video-restricted-invisible-autoplay-not-allowed.html: Added. Canonical link: https://commits.webkit.org/169911@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@192966 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-12-02 22:09:58 +00:00
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 controls autoplay></video>
<p>Test that "invisible autoplay not allowed restriction" pauses media when scrolled out of view.</p>
</body>
</html>