Title: [197898] trunk
Revision
197898
Author
[email protected]
Date
2016-03-09 16:22:12 -0800 (Wed, 09 Mar 2016)

Log Message

Add heuristic for "main content" videos which override user gesture requirements
https://bugs.webkit.org/show_bug.cgi?id=155224

Reviewed by Eric Carlson.

Source/WebCore:

Tests: media/video-main-content-allow-then-deny.html
       media/video-main-content-allow.html
       media/video-main-content-deny-display-none.html
       media/video-main-content-deny-not-in-dom.html
       media/video-main-content-deny-not-visible.html
       media/video-main-content-deny-obscured.html
       media/video-main-content-deny-too-small.html

Add a new behavior "restriction" to MediaElementSession that allows media elements
to optionally overriding their own user gesture requirements if the session determines
that the media element is the page's "main content".

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didAttachRenderers):
(WebCore::HTMLMediaElement::updateShouldPlay):
* html/HTMLMediaElement.h:
* html/MediaElementSession.cpp:
(WebCore::restrictionName):
(WebCore::MediaElementSession::MediaElementSession):
(WebCore::MediaElementSession::addBehaviorRestriction):
(WebCore::MediaElementSession::playbackPermitted):
(WebCore::MediaElementSession::dataLoadingPermitted):
(WebCore::isMainContent):
(WebCore::MediaElementSession::mainContentCheckTimerFired):
(WebCore::MediaElementSession::updateIsMainContent):
* html/MediaElementSession.h:
* testing/Internals.cpp:
(WebCore::Internals::setMediaElementRestrictions):

LayoutTests:

* media/video-main-content-allow-expected.txt: Added.
* media/video-main-content-allow-then-deny-expected.txt: Added.
* media/video-main-content-allow-then-deny.html: Added.
* media/video-main-content-allow.html: Added.
* media/video-main-content-deny-display-none-expected.txt: Added.
* media/video-main-content-deny-display-none.html: Added.
* media/video-main-content-deny-not-in-dom-expected.txt: Added.
* media/video-main-content-deny-not-in-dom.html: Added.
* media/video-main-content-deny-not-visible-expected.txt: Added.
* media/video-main-content-deny-not-visible.html: Added.
* media/video-main-content-deny-obscured-expected.txt: Added.
* media/video-main-content-deny-obscured.html: Added.
* media/video-main-content-deny-too-small-expected.txt: Added.
* media/video-main-content-deny-too-small.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (197897 => 197898)


--- trunk/LayoutTests/ChangeLog	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/LayoutTests/ChangeLog	2016-03-10 00:22:12 UTC (rev 197898)
@@ -1,3 +1,25 @@
+2016-03-09  Jer Noble  <[email protected]>
+
+        Add heuristic for "main content" videos which override user gesture requirements
+        https://bugs.webkit.org/show_bug.cgi?id=155224
+
+        Reviewed by Eric Carlson.
+
+        * media/video-main-content-allow-expected.txt: Added.
+        * media/video-main-content-allow-then-deny-expected.txt: Added.
+        * media/video-main-content-allow-then-deny.html: Added.
+        * media/video-main-content-allow.html: Added.
+        * media/video-main-content-deny-display-none-expected.txt: Added.
+        * media/video-main-content-deny-display-none.html: Added.
+        * media/video-main-content-deny-not-in-dom-expected.txt: Added.
+        * media/video-main-content-deny-not-in-dom.html: Added.
+        * media/video-main-content-deny-not-visible-expected.txt: Added.
+        * media/video-main-content-deny-not-visible.html: Added.
+        * media/video-main-content-deny-obscured-expected.txt: Added.
+        * media/video-main-content-deny-obscured.html: Added.
+        * media/video-main-content-deny-too-small-expected.txt: Added.
+        * media/video-main-content-deny-too-small.html: Added.
+
 2016-03-09  Ryan Haddad  <[email protected]>
 
         Skipping js/regress/getter-richards-try-catch.html on ios-simulator debug

Added: trunk/LayoutTests/media/video-main-content-allow-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-allow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-allow-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,5 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+EVENT(playing)
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-allow-then-deny-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-allow-then-deny-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-allow-then-deny-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,7 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+EVENT(playing)
+RUN(video.style.visibility = "hidden")
+EVENT(pause)
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-allow-then-deny.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-allow-then-deny.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-allow-then-deny.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.appendChild(video);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEvent('playing', playing);
+    }
+
+    function playing() {
+        run('video.style.visibility = "hidden"');
+        waitForEventAndEnd('pause');
+        failTestIn(500);
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-allow.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-allow.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-allow.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.appendChild(video);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndEnd('playing');
+        failTestIn(100);
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-deny-display-none-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-display-none-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-display-none-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,5 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+Did not begin playing OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-deny-display-none.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-display-none.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-display-none.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.appendChild(video);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndFail('playing');
+        setTimeout(didNotBeginPlaying, 100);
+    }
+
+    function didNotBeginPlaying() {
+        logResult(true, 'Did not begin playing');
+        endTest();
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+        display: none;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-deny-not-in-dom-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-not-in-dom-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-not-in-dom-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,5 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+Did not begin playing OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-deny-not-in-dom.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-not-in-dom.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-not-in-dom.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        mediaElement = video = document.createElement('video');
+        // video.customProperty = 'custom';
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndFail('playing');
+        setTimeout(didNotBeginPlaying, 100);
+    }
+
+    function didNotBeginPlaying() {
+        logResult(true, 'Did not begin playing');
+        endTest();
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-deny-not-visible-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-not-visible-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-not-visible-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,5 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+Did not begin playing OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-deny-not-visible.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-not-visible.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-not-visible.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.appendChild(video);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndFail('playing');
+        setTimeout(didNotBeginPlaying, 100);
+    }
+
+    function didNotBeginPlaying() {
+        logResult(true, 'Did not begin playing');
+        endTest();
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+        visibility: hidden;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-deny-obscured-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-obscured-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-obscured-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,6 @@
+
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+Did not begin playing OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-deny-obscured.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-obscured.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-obscured.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.insertBefore(video, document.body.firstChild);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndFail('playing');
+        setTimeout(didNotBeginPlaying, 100);
+    }
+
+    function didNotBeginPlaying() {
+        logResult(true, 'Did not begin playing');
+        endTest();
+    }
+    </script>
+    <style>
+    video {
+        width: 600px;
+        height: 400px;
+    }
+    .block {
+        position: absolute;
+        top: 0px;
+        width: 600px;
+        height: 400px;
+        background-color: red;
+        z-index: 1;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+    <div class="block"></div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/video-main-content-deny-too-small-expected.txt (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-too-small-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-too-small-expected.txt	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,5 @@
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent"))
+EVENT(canplaythrough)
+Did not begin playing OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-main-content-deny-too-small.html (0 => 197898)


--- trunk/LayoutTests/media/video-main-content-deny-too-small.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-main-content-deny-too-small.html	2016-03-10 00:22:12 UTC (rev 197898)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>video-main-content-allow</title>
+    <script src=""
+    <script src=""
+    <script>
+    function go() {
+        video = document.createElement('video');
+        run('internals.setMediaElementRestrictions(video, "RequireUserGestureForRateChange,OverrideUserGestureRequirementForMainContent")');
+        document.body.appendChild(video);
+
+        video.src = "" 'content/test');
+        waitForEvent('canplaythrough', canPlayThrough);
+    }
+
+    function canPlayThrough() {
+        video.play();
+        waitForEventAndFail('playing');
+        setTimeout(didNotBeginPlaying, 100);
+    }
+
+    function didNotBeginPlaying() {
+        logResult(true, 'Did not begin playing');
+        endTest();
+    }
+    </script>
+    <style>
+    video {
+        width: 200px;
+        height: 100px;
+    }
+    </style>
+</head>
+<body _onload_="go()">
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (197897 => 197898)


--- trunk/Source/WebCore/ChangeLog	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/ChangeLog	2016-03-10 00:22:12 UTC (rev 197898)
@@ -1,3 +1,39 @@
+2016-03-09  Jer Noble  <[email protected]>
+
+        Add heuristic for "main content" videos which override user gesture requirements
+        https://bugs.webkit.org/show_bug.cgi?id=155224
+
+        Reviewed by Eric Carlson.
+
+        Tests: media/video-main-content-allow-then-deny.html
+               media/video-main-content-allow.html
+               media/video-main-content-deny-display-none.html
+               media/video-main-content-deny-not-in-dom.html
+               media/video-main-content-deny-not-visible.html
+               media/video-main-content-deny-obscured.html
+               media/video-main-content-deny-too-small.html
+
+        Add a new behavior "restriction" to MediaElementSession that allows media elements
+        to optionally overriding their own user gesture requirements if the session determines
+        that the media element is the page's "main content".
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::didAttachRenderers):
+        (WebCore::HTMLMediaElement::updateShouldPlay):
+        * html/HTMLMediaElement.h:
+        * html/MediaElementSession.cpp:
+        (WebCore::restrictionName):
+        (WebCore::MediaElementSession::MediaElementSession):
+        (WebCore::MediaElementSession::addBehaviorRestriction):
+        (WebCore::MediaElementSession::playbackPermitted):
+        (WebCore::MediaElementSession::dataLoadingPermitted):
+        (WebCore::isMainContent):
+        (WebCore::MediaElementSession::mainContentCheckTimerFired):
+        (WebCore::MediaElementSession::updateIsMainContent):
+        * html/MediaElementSession.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::setMediaElementRestrictions):
+
 2016-03-09  Konstantin Tokarev  <[email protected]>
 
         Added missing #if(SOUP) after r197591.

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (197897 => 197898)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-03-10 00:22:12 UTC (rev 197898)
@@ -794,7 +794,8 @@
 {
     if (RenderElement* renderer = this->renderer()) {
         renderer->updateFromElement();
-        if (m_mediaSession->hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
+        if (m_mediaSession->hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted)
+            || m_mediaSession->hasBehaviorRestriction(MediaElementSession::OverrideUserGestureRequirementForMainContent))
             renderer->registerForVisibleInViewportCallback();
     }
     updateShouldAutoplay();
@@ -6816,6 +6817,14 @@
         m_mediaSession->beginInterruption(PlatformMediaSession::InvisibleAutoplay);
 }
 
+void HTMLMediaElement::updateShouldPlay()
+{
+    if (isPlaying() && !m_mediaSession->playbackPermitted(*this))
+        pauseInternal();
+    else if (elementCanTransitionFromAutoplayToPlay(*this))
+        play();
 }
 
+}
+
 #endif

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (197897 => 197898)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2016-03-10 00:22:12 UTC (rev 197898)
@@ -452,6 +452,7 @@
     void visibilityDidChange();
 
     void allowsMediaDocumentInlinePlaybackChanged();
+    void updateShouldPlay();
 
 protected:
     HTMLMediaElement(const QualifiedName&, Document&, bool);

Modified: trunk/Source/WebCore/html/MediaElementSession.cpp (197897 => 197898)


--- trunk/Source/WebCore/html/MediaElementSession.cpp	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/html/MediaElementSession.cpp	2016-03-10 00:22:12 UTC (rev 197898)
@@ -38,9 +38,12 @@
 #include "HTMLMediaElementEnums.h"
 #include "HTMLNames.h"
 #include "HTMLVideoElement.h"
+#include "HitTestResult.h"
 #include "Logging.h"
+#include "MainFrame.h"
 #include "Page.h"
 #include "PlatformMediaSessionManager.h"
+#include "RenderView.h"
 #include "ScriptController.h"
 #include "SourceBuffer.h"
 
@@ -51,6 +54,12 @@
 
 namespace WebCore {
 
+static const int elementMainContentMinimumWidth = 400;
+static const int elementMainContentMinimumHeight = 300;
+static const double elementMainContentCheckInterval = .250;
+
+static bool isMainContent(const HTMLMediaElement&);
+
 #if !LOG_DISABLED
 static String restrictionName(MediaElementSession::BehaviorRestrictions restriction)
 {
@@ -75,6 +84,7 @@
 #endif
     CASE(RequireUserGestureForAudioRateChange);
     CASE(InvisibleAutoplayNotPermitted);
+    CASE(OverrideUserGestureRequirementForMainContent);
 
     return restrictionBuilder.toString();
 }
@@ -87,12 +97,14 @@
     return document.isMediaDocument() && !document.ownerElement() && page && page->allowsMediaDocumentInlinePlayback();
 }
 
-MediaElementSession::MediaElementSession(PlatformMediaSessionClient& client)
-    : PlatformMediaSession(client)
+MediaElementSession::MediaElementSession(HTMLMediaElement& element)
+    : PlatformMediaSession(element)
+    , m_element(element)
     , m_restrictions(NoRestrictions)
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     , m_targetAvailabilityChangedTimer(*this, &MediaElementSession::targetAvailabilityChangedTimerFired)
 #endif
+    , m_mainContentCheckTimer(*this, &MediaElementSession::mainContentCheckTimerFired)
 {
 }
 
@@ -118,6 +130,9 @@
 {
     LOG(Media, "MediaElementSession::addBehaviorRestriction - adding %s", restrictionName(restriction).utf8().data());
     m_restrictions |= restriction;
+
+    if (restriction & OverrideUserGestureRequirementForMainContent)
+        m_mainContentCheckTimer.startRepeating(elementMainContentCheckInterval);
 }
 
 void MediaElementSession::removeBehaviorRestriction(BehaviorRestrictions restriction)
@@ -131,6 +146,9 @@
     if (pageExplicitlyAllowsElementToAutoplayInline(element))
         return true;
 
+    if (m_restrictions & OverrideUserGestureRequirementForMainContent && updateIsMainContent())
+        return true;
+
     if (m_restrictions & RequireUserGestureForRateChange && !ScriptController::processingUserGestureForMedia()) {
         LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE");
         return false;
@@ -146,6 +164,9 @@
 
 bool MediaElementSession::dataLoadingPermitted(const HTMLMediaElement&) const
 {
+    if (m_restrictions & OverrideUserGestureRequirementForMainContent && updateIsMainContent())
+        return true;
+
     if (m_restrictions & RequireUserGestureForLoad && !ScriptController::processingUserGestureForMedia()) {
         LOG(Media, "MediaElementSession::dataLoadingPermitted - returning FALSE");
         return false;
@@ -448,6 +469,69 @@
 }
 #endif
 
+static bool isMainContent(const HTMLMediaElement& element)
+{
+    if (!element.hasAudio() || !element.hasVideo())
+        return false;
+
+    // Elements which have not yet been laid out, or which are not yet in the DOM, cannot be main content.
+    RenderBox* renderer = downcast<RenderBox>(element.renderer());
+    if (!renderer)
+        return false;
+
+    if (renderer->clientWidth() < elementMainContentMinimumWidth
+        || renderer->clientHeight() < elementMainContentMinimumHeight)
+        return false;
+
+    // Elements which are hidden by style, or have been scrolled out of view, cannot be main content.
+    if (renderer->style().visibility() != VISIBLE
+        || renderer->visibleInViewportState() != RenderElement::VisibleInViewport)
+        return false;
+
+    // Main content elements must be in the main frame.
+    Document& document = element.document();
+    if (!document.frame() || !document.frame()->isMainFrame())
+        return false;
+
+    MainFrame& mainFrame = document.frame()->mainFrame();
+    if (!mainFrame.view() || !mainFrame.view()->renderView())
+        return false;
+
+    RenderView& mainRenderView = *mainFrame.view()->renderView();
+
+    // Hit test the area of the main frame where the element appears, to determine if the element is being obscured.
+    IntRect rectRelativeToView = element.clientRect();
+    ScrollPosition scrollPosition = mainFrame.view()->documentScrollPositionRelativeToViewOrigin();
+    IntRect rectRelativeToTopDocument(rectRelativeToView.location() + scrollPosition, rectRelativeToView.size());
+    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
+    HitTestResult result(rectRelativeToTopDocument.center());
+
+    // Elements which are obscured by other elements cannot be main content.
+    mainRenderView.hitTest(request, result);
+    Element* hitElement = result.innerElement();
+    if (hitElement != &element)
+        return false;
+
+    return true;
 }
 
+void MediaElementSession::mainContentCheckTimerFired()
+{
+    if (!hasBehaviorRestriction(OverrideUserGestureRequirementForMainContent))
+        return;
+
+    bool wasMainContent = m_isMainContent;
+    m_isMainContent = isMainContent(m_element);
+
+    if (m_isMainContent != wasMainContent)
+        m_element.updateShouldPlay();
+}
+
+bool MediaElementSession::updateIsMainContent() const
+{
+    return m_isMainContent = isMainContent(m_element);
+}
+
+}
+
 #endif // ENABLE(VIDEO)

Modified: trunk/Source/WebCore/html/MediaElementSession.h (197897 => 197898)


--- trunk/Source/WebCore/html/MediaElementSession.h	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/html/MediaElementSession.h	2016-03-10 00:22:12 UTC (rev 197898)
@@ -41,7 +41,7 @@
 class MediaElementSession final : public PlatformMediaSession {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit MediaElementSession(PlatformMediaSessionClient&);
+    explicit MediaElementSession(HTMLMediaElement&);
     virtual ~MediaElementSession() { }
 
     void registerWithDocument(Document&);
@@ -92,6 +92,7 @@
         MetadataPreloadingNotPermitted = 1 << 9,
         AutoPreloadingNotPermitted = 1 << 10,
         InvisibleAutoplayNotPermitted = 1 << 11,
+        OverrideUserGestureRequirementForMainContent = 1 << 12
     };
     typedef unsigned BehaviorRestrictions;
 
@@ -118,7 +119,10 @@
 #if PLATFORM(IOS)
     bool requiresPlaybackTargetRouteMonitoring() const override;
 #endif
+    bool updateIsMainContent() const;
+    void mainContentCheckTimerFired();
 
+    HTMLMediaElement& m_element;
     BehaviorRestrictions m_restrictions;
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -130,6 +134,9 @@
 #if PLATFORM(IOS)
     bool m_hasPlaybackTargetAvailabilityListeners { false };
 #endif
+
+    mutable bool m_isMainContent { false };
+    Timer m_mainContentCheckTimer;
 };
 
 }

Modified: trunk/Source/WebCore/testing/Internals.cpp (197897 => 197898)


--- trunk/Source/WebCore/testing/Internals.cpp	2016-03-10 00:14:07 UTC (rev 197897)
+++ trunk/Source/WebCore/testing/Internals.cpp	2016-03-10 00:22:12 UTC (rev 197898)
@@ -3090,6 +3090,8 @@
             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
         if (equalLettersIgnoringASCIICase(restrictionString, "invisibleautoplaynotpermitted"))
             restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
+        if (equalLettersIgnoringASCIICase(restrictionString, "overrideusergesturerequirementformaincontent"))
+            restrictions |= MediaElementSession::OverrideUserGestureRequirementForMainContent;
     }
     element->mediaSession().addBehaviorRestriction(restrictions);
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to