<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[192966] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/192966">192966</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2015-12-02 14:09:58 -0800 (Wed, 02 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>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 &quot;autoplaying&quot; 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 &quot;Autoplay&quot; 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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomElementh">trunk/Source/WebCore/dom/Element.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementh">trunk/Source/WebCore/html/HTMLMediaElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlMediaElementSessioncpp">trunk/Source/WebCore/html/MediaElementSession.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlMediaElementSessionh">trunk/Source/WebCore/html/MediaElementSession.h</a></li>
<li><a href="#trunkSourceWebCorepageFrameViewcpp">trunk/Source/WebCore/page/FrameView.cpp</a></li>
<li><a href="#trunkSourceWebCorepageSettingsin">trunk/Source/WebCore/page/Settings.in</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessioncpp">trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessionh">trunk/Source/WebCore/platform/audio/PlatformMediaSession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessionManagercpp">trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderElementcpp">trunk/Source/WebCore/rendering/RenderElement.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderElementh">trunk/Source/WebCore/rendering/RenderElement.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderImageh">trunk/Source/WebCore/rendering/RenderImage.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderMediacpp">trunk/Source/WebCore/rendering/RenderMedia.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderMediah">trunk/Source/WebCore/rendering/RenderMedia.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderObjectcpp">trunk/Source/WebCore/rendering/RenderObject.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderObjecth">trunk/Source/WebCore/rendering/RenderObject.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderViewcpp">trunk/Source/WebCore/rendering/RenderView.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderViewh">trunk/Source/WebCore/rendering/RenderView.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediavideorestrictedinvisibleautoplaynotallowedexpectedtxt">trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediavideorestrictedinvisibleautoplaynotallowedhtml">trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/LayoutTests/ChangeLog        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-12-02  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Add a setting and restriction which will pause invisible autoplaying video
+        https://bugs.webkit.org/show_bug.cgi?id=151412
+
+        Reviewed by Eric Carlson.
+
+        * media/video-restricted-invisible-autoplay-not-allowed-expected.txt: Added.
+        * media/video-restricted-invisible-autoplay-not-allowed.html: Added.
+
</ins><span class="cx"> 2015-12-02  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rebaseline fast/parser/xml-declaration-missing-ending-mark.html, fast/parser/xml-colon-entity.html for Win
</span></span></pre></div>
<a id="trunkLayoutTestsmediavideorestrictedinvisibleautoplaynotallowedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-expected.txt (0 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed-expected.txt        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+
+Test that &quot;invisible autoplay not allowed restriction&quot; pauses media when scrolled out of view.
+
+** setting video.src
+RUN(internals.setMediaElementRestrictions(video, &quot;InvisibleAutoplayNotPermitted&quot;))
+
+EVENT(play)
+RUN(video.style.display = &quot;none&quot;)
+EVENT(pause)
+RUN(video.style.removeProperty(&quot;display&quot;))
+EVENT(play)
+RUN(video.style.visibility = &quot;hidden&quot;)
+EVENT(pause)
+RUN(video.style.removeProperty(&quot;visibility&quot;))
+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediavideorestrictedinvisibleautoplaynotallowedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed.html (0 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed.html                                (rev 0)
+++ trunk/LayoutTests/media/video-restricted-invisible-autoplay-not-allowed.html        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+&lt;html&gt;
+    &lt;head&gt;
+        &lt;script src=&quot;media-file.js&quot;&gt;&lt;/script&gt;
+        &lt;script src=&quot;video-test.js&quot;&gt;&lt;/script&gt;
+        &lt;script&gt;
+            function start()
+            {
+                findMediaElement();
+                consoleWrite('** setting video.src');
+                video.src = findMediaFile('video', 'content/test');
+
+                waitForEventOnce('play', play1);
+                run('internals.setMediaElementRestrictions(video, &quot;InvisibleAutoplayNotPermitted&quot;)');
+                consoleWrite('');
+            }
+
+            function play1()
+            {
+                run('video.style.display = &quot;none&quot;');
+                waitForEventOnce('pause', pause1);
+            }
+
+            function pause1()
+            {
+                run('video.style.removeProperty(&quot;display&quot;)')
+                waitForEventOnce('play', play2);
+            }
+
+            function play2()
+            {
+                run('video.style.visibility = &quot;hidden&quot;');
+                waitForEventOnce('pause', pause2);
+            }
+
+            function pause2()
+            {
+                run('video.style.removeProperty(&quot;visibility&quot;)');
+                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);
+            }
+        &lt;/script&gt;
+    &lt;/head&gt;
+
+    &lt;body onload=&quot;start()&quot;&gt;
+        &lt;video controls autoplay&gt;&lt;/video&gt;
+        &lt;p&gt;Test that &quot;invisible autoplay not allowed restriction&quot; pauses media when scrolled out of view.&lt;/p&gt;
+    &lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/ChangeLog        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -1,3 +1,83 @@
</span><ins>+2015-12-02  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Add a setting and restriction which will pause invisible autoplaying video
+        https://bugs.webkit.org/show_bug.cgi?id=151412
+
+        Reviewed by Eric Carlson.
+
+        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 &quot;autoplaying&quot; 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 &quot;Autoplay&quot; 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.
+
</ins><span class="cx"> 2015-12-02  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Modern IDB: IDBTransaction::error is not exposed.
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/dom/Element.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -494,6 +494,8 @@
</span><span class="cx">     StyleResolver&amp; styleResolver();
</span><span class="cx">     Ref&lt;RenderStyle&gt; resolveStyle(RenderStyle* parentStyle);
</span><span class="cx"> 
</span><ins>+    virtual void isVisibleInViewportChanged() { }
+
</ins><span class="cx"> protected:
</span><span class="cx">     Element(const QualifiedName&amp;, Document&amp;, ConstructionType);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -427,6 +427,8 @@
</span><span class="cx">         // Relax RequireUserGestureForFullscreen when requiresUserGestureForMediaPlayback is not set:
</span><span class="cx">         m_mediaSession-&gt;removeBehaviorRestriction(MediaElementSession::RequireUserGestureForFullscreen);
</span><span class="cx">     }
</span><ins>+    if (settings &amp;&amp; settings-&gt;invisibleAutoplayNotPermitted())
+        m_mediaSession-&gt;addBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted);
</ins><span class="cx"> #endif // !PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx">     if (settings &amp;&amp; settings-&gt;audioPlaybackRequiresUserGesture() &amp;&amp; settings-&gt;requiresUserGestureForMediaPlayback())
</span><span class="lines">@@ -602,6 +604,7 @@
</span><span class="cx">     registerWithDocument(document());
</span><span class="cx"> 
</span><span class="cx">     HTMLElement::didMoveToNewDocument(oldDocument);
</span><ins>+    updateShouldAutoplay();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="lines">@@ -613,6 +616,7 @@
</span><span class="cx"> void HTMLMediaElement::resumeFromDocumentSuspension()
</span><span class="cx"> {
</span><span class="cx">     m_mediaSession-&gt;registerWithDocument(document());
</span><ins>+    updateShouldAutoplay();
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -779,10 +783,25 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::didAttachRenderers()
</span><span class="cx"> {
</span><del>-    if (renderer())
-        renderer()-&gt;updateFromElement();
</del><ins>+    if (RenderElement* renderer = this-&gt;renderer()) {
+        renderer-&gt;updateFromElement();
+        if (m_mediaSession-&gt;hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
+            renderer-&gt;registerForVisibleInViewportCallback();
+    }
+    updateShouldAutoplay();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaElement::willDetachRenderers()
+{
+    if (renderer() &amp;&amp; m_mediaSession-&gt;hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
+        renderer()-&gt;unregisterForVisibleInViewportCallback();
+}
+
+void HTMLMediaElement::didDetachRenderers()
+{
+    updateShouldAutoplay();
+}
+
</ins><span class="cx"> void HTMLMediaElement::didRecalcStyle(Style::Change)
</span><span class="cx"> {
</span><span class="cx">     if (renderer())
</span><span class="lines">@@ -2058,6 +2077,15 @@
</span><span class="cx">     endProcessingMediaPlayerCallback();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool elementCanTransitionFromAutoplayToPlay(HTMLMediaElement&amp; element)
+{
+    return element.isAutoplaying()
+        &amp;&amp; element.paused()
+        &amp;&amp; element.autoplay()
+        &amp;&amp; !element.document().isSandboxed(SandboxAutomaticFeatures)
+        &amp;&amp; element.mediaSession().playbackPermitted(element);
+}
+
</ins><span class="cx"> void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::setReadyState(%p) - new state = %d, current state = %d,&quot;, this, static_cast&lt;int&gt;(state), static_cast&lt;int&gt;(m_readyState));
</span><span class="lines">@@ -2167,7 +2195,7 @@
</span><span class="cx">         if (isPotentiallyPlaying &amp;&amp; oldState &lt;= HAVE_CURRENT_DATA)
</span><span class="cx">             scheduleEvent(eventNames().playingEvent);
</span><span class="cx"> 
</span><del>-        if (m_autoplaying &amp;&amp; m_paused &amp;&amp; autoplay() &amp;&amp; !document().isSandboxed(SandboxAutomaticFeatures) &amp;&amp; m_mediaSession-&gt;playbackPermitted(*this)) {
</del><ins>+        if (elementCanTransitionFromAutoplayToPlay(*this)) {
</ins><span class="cx">             m_paused = false;
</span><span class="cx">             invalidateCachedTime();
</span><span class="cx">             scheduleEvent(eventNames().playEvent);
</span><span class="lines">@@ -3942,6 +3970,11 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaElement::visibilityDidChange()
+{
+    updateShouldAutoplay();
+}
+
</ins><span class="cx"> void HTMLMediaElement::setSelectedTextTrack(TextTrack* trackToSelect)
</span><span class="cx"> {
</span><span class="cx">     TextTrackList* trackList = textTracks();
</span><span class="lines">@@ -6174,7 +6207,8 @@
</span><span class="cx">         | MediaElementSession::RequireUserGestureForLoad
</span><span class="cx">         | MediaElementSession::RequireUserGestureForRateChange
</span><span class="cx">         | MediaElementSession::RequireUserGestureForAudioRateChange
</span><del>-        | MediaElementSession::RequireUserGestureForFullscreen;
</del><ins>+        | MediaElementSession::RequireUserGestureForFullscreen
+        | MediaElementSession::InvisibleAutoplayNotPermitted;
</ins><span class="cx">     m_mediaSession-&gt;removeBehaviorRestriction(restrictionsToRemove);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -6455,6 +6489,15 @@
</span><span class="cx">         pause();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaElement::resumeAutoplaying()
+{
+    LOG(Media, &quot;HTMLMediaElement::resumeAutoplaying(%p) - paused = %s&quot;, this, boolString(paused()));
+    m_autoplaying = true;
+
+    if (elementCanTransitionFromAutoplayToPlay(*this))
+        play();
+}
+
</ins><span class="cx"> void HTMLMediaElement::mayResumePlayback(bool shouldResume)
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::mayResumePlayback(%p) - paused = %s&quot;, this, boolString(paused()));
</span><span class="lines">@@ -6694,6 +6737,49 @@
</span><span class="cx">         enterFullscreen();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool mediaElementIsAllowedToAutoplay(const HTMLMediaElement&amp; element)
+{
+    const Document&amp; document = element.document();
+    if (document.inPageCache())
+        return false;
+    if (document.activeDOMObjectsAreSuspended())
+        return false;
+
+    RenderElement* renderer = element.renderer();
+    if (!renderer)
+        return false;
+    if (renderer-&gt;style().visibility() != VISIBLE)
+        return false;
+    if (renderer-&gt;view().frameView().isOffscreen())
+        return false;
+    if (renderer-&gt;visibleInViewportState() != RenderElement::VisibleInViewport)
+        return false;
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaElement::isVisibleInViewportChanged()
+{
+    updateShouldAutoplay();
+}
+
+void HTMLMediaElement::updateShouldAutoplay()
+{
+    if (!autoplay())
+        return;
+
+    if (!m_mediaSession-&gt;hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
+        return;
+
+    bool canAutoplay = mediaElementIsAllowedToAutoplay(*this);
+    if (canAutoplay
+        &amp;&amp; m_mediaSession-&gt;state() == PlatformMediaSession::Interrupted
+        &amp;&amp; m_mediaSession-&gt;interruptionType() == PlatformMediaSession::InvisibleAutoplay)
+        m_mediaSession-&gt;endInterruption(PlatformMediaSession::MayResumePlaying);
+    else if (!canAutoplay
+        &amp;&amp; m_mediaSession-&gt;state() != PlatformMediaSession::Interrupted)
+        m_mediaSession-&gt;beginInterruption(PlatformMediaSession::InvisibleAutoplay);
+}
+
+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -200,7 +200,8 @@
</span><span class="cx">     virtual PassRefPtr&lt;TimeRanges&gt; seekable() const override;
</span><span class="cx">     WEBCORE_EXPORT bool ended() const;
</span><span class="cx">     bool autoplay() const;
</span><del>-    bool loop() const;    
</del><ins>+    bool isAutoplaying() const { return m_autoplaying; }
+    bool loop() const;
</ins><span class="cx">     void setLoop(bool b);
</span><span class="cx">     WEBCORE_EXPORT virtual void play() override;
</span><span class="cx">     WEBCORE_EXPORT virtual void pause() override;
</span><span class="lines">@@ -446,6 +447,7 @@
</span><span class="cx">     virtual MediaProducer::MediaStateFlags mediaState() const override;
</span><span class="cx"> 
</span><span class="cx">     void layoutSizeChanged();
</span><ins>+    void visibilityDidChange();
</ins><span class="cx"> 
</span><span class="cx">     void allowsMediaDocumentInlinePlaybackChanged();
</span><span class="cx"> 
</span><span class="lines">@@ -453,13 +455,15 @@
</span><span class="cx">     HTMLMediaElement(const QualifiedName&amp;, Document&amp;, bool);
</span><span class="cx">     virtual ~HTMLMediaElement();
</span><span class="cx"> 
</span><del>-    virtual void parseAttribute(const QualifiedName&amp;, const AtomicString&amp;) override;
-    virtual void finishParsingChildren() override;
-    virtual bool isURLAttribute(const Attribute&amp;) const override;
-    virtual void willAttachRenderers() override;
-    virtual void didAttachRenderers() override;
</del><ins>+    void parseAttribute(const QualifiedName&amp;, const AtomicString&amp;) override;
+    void finishParsingChildren() override;
+    bool isURLAttribute(const Attribute&amp;) const override;
+    void willAttachRenderers() override;
+    void didAttachRenderers() override;
+    void willDetachRenderers() override;
+    void didDetachRenderers() override;
</ins><span class="cx"> 
</span><del>-    virtual void didMoveToNewDocument(Document* oldDocument) override;
</del><ins>+    void didMoveToNewDocument(Document* oldDocument) override;
</ins><span class="cx"> 
</span><span class="cx">     enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
</span><span class="cx">     DisplayMode displayMode() const { return m_displayMode; }
</span><span class="lines">@@ -713,7 +717,6 @@
</span><span class="cx">     bool isBlockedOnMediaController() const;
</span><span class="cx">     virtual bool hasCurrentSrc() const override { return !m_currentSrc.isEmpty(); }
</span><span class="cx">     virtual bool isLiveStream() const override { return movieLoadType() == MediaPlayerEnums::LiveStream; }
</span><del>-    bool isAutoplaying() const { return m_autoplaying; }
</del><span class="cx"> 
</span><span class="cx">     void updateSleepDisabling();
</span><span class="cx">     bool shouldDisableSleep() const;
</span><span class="lines">@@ -729,6 +732,7 @@
</span><span class="cx">     PlatformMediaSession::MediaType presentationType() const override;
</span><span class="cx">     PlatformMediaSession::DisplayType displayType() const override;
</span><span class="cx">     void suspendPlayback() override;
</span><ins>+    void resumeAutoplaying() override;
</ins><span class="cx">     void mayResumePlayback(bool shouldResume) override;
</span><span class="cx">     String mediaSessionTitle() const override;
</span><span class="cx">     double mediaSessionDuration() const override { return duration(); }
</span><span class="lines">@@ -757,6 +761,9 @@
</span><span class="cx">     void updateMediaState(UpdateMediaState updateState = UpdateMediaState::Synchronously);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void isVisibleInViewportChanged() override final;
+    void updateShouldAutoplay();
+
</ins><span class="cx">     Timer m_pendingActionTimer;
</span><span class="cx">     Timer m_progressEventTimer;
</span><span class="cx">     Timer m_playbackProgressTimer;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlMediaElementSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/MediaElementSession.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/MediaElementSession.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/html/MediaElementSession.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -73,6 +73,7 @@
</span><span class="cx">     CASE(WirelessVideoPlaybackDisabled);
</span><span class="cx"> #endif
</span><span class="cx">     CASE(RequireUserGestureForAudioRateChange);
</span><ins>+    CASE(InvisibleAutoplayNotPermitted);
</ins><span class="cx"> 
</span><span class="cx">     return restrictionBuilder.toString();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlMediaElementSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/MediaElementSession.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/MediaElementSession.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/html/MediaElementSession.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx"> #endif
</span><span class="cx">         MetadataPreloadingNotPermitted = 1 &lt;&lt; 9,
</span><span class="cx">         AutoPreloadingNotPermitted = 1 &lt;&lt; 10,
</span><ins>+        InvisibleAutoplayNotPermitted = 1 &lt;&lt; 11,
</ins><span class="cx">     };
</span><span class="cx">     typedef unsigned BehaviorRestrictions;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/page/FrameView.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -1887,6 +1887,9 @@
</span><span class="cx">     applyRecursivelyWithVisibleRect([] (FrameView&amp; frameView, const IntRect&amp; visibleRect) {
</span><span class="cx">         frameView.resumeVisibleImageAnimations(visibleRect);
</span><span class="cx">         frameView.updateScriptedAnimationsAndTimersThrottlingState(visibleRect);
</span><ins>+
+        if (auto* renderView = frameView.frame().contentRenderer())
+            renderView-&gt;updateVisibleViewportRect(visibleRect);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingsin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.in (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.in        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/page/Settings.in        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -130,6 +130,7 @@
</span><span class="cx"> inlineMediaPlaybackRequiresPlaysInlineAttribute initial=defaultInlineMediaPlaybackRequiresPlaysInlineAttribute
</span><span class="cx"> allowsPictureInPictureMediaPlayback initial=defaultAllowsPictureInPictureMediaPlayback
</span><span class="cx"> mediaControlsScaleWithPageZoom initial=defaultMediaControlsScaleWithPageZoom
</span><ins>+invisibleAutoplayNotPermitted initial=false
</ins><span class="cx"> passwordEchoEnabled initial=false
</span><span class="cx"> suppressesIncrementalRendering initial=false
</span><span class="cx"> incrementalRenderingSuppressionTimeoutInSeconds type=double, initial=defaultIncrementalRenderingSuppressionTimeoutInSeconds
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #define STATE_CASE(state) case PlatformMediaSession::state: return #state
</span><span class="cx">     switch (state) {
</span><span class="cx">     STATE_CASE(Idle);
</span><ins>+    STATE_CASE(Autoplaying);
</ins><span class="cx">     STATE_CASE(Playing);
</span><span class="cx">     STATE_CASE(Paused);
</span><span class="cx">     STATE_CASE(Interrupted);
</span><span class="lines">@@ -55,10 +56,12 @@
</span><span class="cx"> {
</span><span class="cx"> #define INTERRUPTION_CASE(type) case PlatformMediaSession::type: return #type
</span><span class="cx">     switch (type) {
</span><ins>+    INTERRUPTION_CASE(NoInterruption);
</ins><span class="cx">     INTERRUPTION_CASE(SystemSleep);
</span><span class="cx">     INTERRUPTION_CASE(EnteringBackground);
</span><span class="cx">     INTERRUPTION_CASE(SystemInterruption);
</span><span class="cx">     INTERRUPTION_CASE(SuspendedUnderLock);
</span><ins>+    INTERRUPTION_CASE(InvisibleAutoplay);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="lines">@@ -106,6 +109,7 @@
</span><span class="cx">     m_stateToRestore = state();
</span><span class="cx">     m_notifyingClient = true;
</span><span class="cx">     setState(Interrupted);
</span><ins>+    m_interruptionType = type;
</ins><span class="cx">     client().suspendPlayback();
</span><span class="cx">     m_notifyingClient = false;
</span><span class="cx"> }
</span><span class="lines">@@ -124,12 +128,32 @@
</span><span class="cx"> 
</span><span class="cx">     State stateToRestore = m_stateToRestore;
</span><span class="cx">     m_stateToRestore = Idle;
</span><ins>+    m_interruptionType = NoInterruption;
</ins><span class="cx">     setState(Paused);
</span><span class="cx"> 
</span><ins>+    if (stateToRestore == Autoplaying)
+        client().resumeAutoplaying();
+
</ins><span class="cx">     bool shouldResume = flags &amp; MayResumePlaying &amp;&amp; stateToRestore == Playing;
</span><span class="cx">     client().mayResumePlayback(shouldResume);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformMediaSession::clientWillBeginAutoplaying()
+{
+    if (m_notifyingClient)
+        return;
+
+    LOG(Media, &quot;PlatformMediaSession::clientWillBeginAutoplaying(%p)- state = %s&quot;, this, stateName(m_state));
+    if (state() == Interrupted) {
+        m_stateToRestore = Autoplaying;
+        LOG(Media, &quot;      setting stateToRestore to \&quot;Autoplaying\&quot;&quot;);
+        return;
+    }
+
+    setState(Autoplaying);
+    updateClientDataBuffering();
+}
+
</ins><span class="cx"> bool PlatformMediaSession::clientWillBeginPlayback()
</span><span class="cx"> {
</span><span class="cx">     if (m_notifyingClient)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx"> 
</span><span class="cx">     enum State {
</span><span class="cx">         Idle,
</span><ins>+        Autoplaying,
</ins><span class="cx">         Playing,
</span><span class="cx">         Paused,
</span><span class="cx">         Interrupted,
</span><span class="lines">@@ -71,11 +72,15 @@
</span><span class="cx">     void setState(State);
</span><span class="cx"> 
</span><span class="cx">     enum InterruptionType {
</span><ins>+        NoInterruption,
</ins><span class="cx">         SystemSleep,
</span><span class="cx">         EnteringBackground,
</span><span class="cx">         SystemInterruption,
</span><span class="cx">         SuspendedUnderLock,
</span><ins>+        InvisibleAutoplay,
</ins><span class="cx">     };
</span><ins>+    InterruptionType interruptionType() const { return m_interruptionType; }
+
</ins><span class="cx">     enum EndInterruptionFlags {
</span><span class="cx">         NoFlags = 0,
</span><span class="cx">         MayResumePlaying = 1 &lt;&lt; 0,
</span><span class="lines">@@ -84,6 +89,7 @@
</span><span class="cx">     void beginInterruption(InterruptionType);
</span><span class="cx">     void endInterruption(EndInterruptionFlags);
</span><span class="cx"> 
</span><ins>+    void clientWillBeginAutoplaying();
</ins><span class="cx">     bool clientWillBeginPlayback();
</span><span class="cx">     bool clientWillPausePlayback();
</span><span class="cx"> 
</span><span class="lines">@@ -148,6 +154,7 @@
</span><span class="cx">     Timer m_clientDataBufferingTimer;
</span><span class="cx">     State m_state;
</span><span class="cx">     State m_stateToRestore;
</span><ins>+    InterruptionType m_interruptionType { NoInterruption };
</ins><span class="cx">     int m_interruptionCount { 0 };
</span><span class="cx">     bool m_notifyingClient;
</span><span class="cx">     bool m_isPlayingToWirelessPlaybackTarget { false };
</span><span class="lines">@@ -165,6 +172,7 @@
</span><span class="cx">     virtual PlatformMediaSession::MediaType presentationType() const = 0;
</span><span class="cx">     virtual PlatformMediaSession::DisplayType displayType() const { return PlatformMediaSession::Normal; }
</span><span class="cx"> 
</span><ins>+    virtual void resumeAutoplaying() { }
</ins><span class="cx">     virtual void mayResumePlayback(bool shouldResume) = 0;
</span><span class="cx">     virtual void suspendPlayback() = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -208,7 +208,9 @@
</span><span class="cx">     for (auto* oneSession : sessions) {
</span><span class="cx">         if (oneSession == &amp;session)
</span><span class="cx">             continue;
</span><del>-        if (oneSession-&gt;mediaType() == sessionType &amp;&amp; restrictions &amp; ConcurrentPlaybackNotPermitted)
</del><ins>+        if (oneSession-&gt;mediaType() == sessionType
+            &amp;&amp; restrictions &amp; ConcurrentPlaybackNotPermitted
+            &amp;&amp; oneSession-&gt;state() == PlatformMediaSession::Playing)
</ins><span class="cx">             oneSession-&gt;pauseSession();
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderElement.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -141,6 +141,8 @@
</span><span class="cx">     }
</span><span class="cx">     if (m_hasPausedImageAnimations)
</span><span class="cx">         view().removeRendererWithPausedImageAnimations(*this);
</span><ins>+    if (isRegisteredForVisibleInViewportCallback())
+        view().unregisterForVisibleInViewportCallback(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RenderPtr&lt;RenderElement&gt; RenderElement::createFor(Element&amp; element, Ref&lt;RenderStyle&gt;&amp;&amp; style)
</span><span class="lines">@@ -1464,6 +1466,35 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RenderElement::registerForVisibleInViewportCallback()
+{
+    if (isRegisteredForVisibleInViewportCallback())
+        return;
+    setIsRegisteredForVisibleInViewportCallback(true);
+
+    view().registerForVisibleInViewportCallback(*this);
+}
+
+void RenderElement::unregisterForVisibleInViewportCallback()
+{
+    if (!isRegisteredForVisibleInViewportCallback())
+        return;
+    setIsRegisteredForVisibleInViewportCallback(false);
+
+    view().unregisterForVisibleInViewportCallback(*this);
+    m_visibleInViewportState = VisibilityUnknown;
+}
+
+void RenderElement::visibleInViewportStateChanged(VisibleInViewportState state)
+{
+    if (state == visibleInViewportState())
+        return;
+    setVisibleInViewportState(state);
+
+    if (element())
+        element()-&gt;isVisibleInViewportChanged();
+}
+
</ins><span class="cx"> void RenderElement::newImageAnimationFrameAvailable(CachedImage&amp; image)
</span><span class="cx"> {
</span><span class="cx">     if (document().inPageCache())
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderElement.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderElement.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderElement.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -193,6 +193,10 @@
</span><span class="cx">     bool hasShapeOutside() const { return false; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void registerForVisibleInViewportCallback();
+    void unregisterForVisibleInViewportCallback();
+    void visibleInViewportStateChanged(VisibleInViewportState);
+
</ins><span class="cx">     bool repaintForPausedImageAnimationsIfNeeded(const IntRect&amp; visibleRect);
</span><span class="cx">     bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; }
</span><span class="cx">     void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
</span><span class="lines">@@ -328,6 +332,8 @@
</span><span class="cx">     unsigned m_renderBlockFlowHasMarkupTruncation : 1;
</span><span class="cx">     unsigned m_renderBlockFlowLineLayoutPath : 2;
</span><span class="cx"> 
</span><ins>+    VisibleInViewportState m_visibleInViewportState { VisibilityUnknown };
+
</ins><span class="cx">     RenderObject* m_firstChild;
</span><span class="cx">     RenderObject* m_lastChild;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderImage.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderImage.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderImage.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx">     virtual void computeIntrinsicRatioInformation(FloatSize&amp; intrinsicSize, double&amp; intrinsicRatio) const override final;
</span><span class="cx">     virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect&amp; localRect, unsigned maxDepthToTest) const override;
</span><span class="cx"> 
</span><del>-    virtual void styleDidChange(StyleDifference, const RenderStyle*) override final;
</del><ins>+    virtual void styleDidChange(StyleDifference, const RenderStyle*) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderMediacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderMedia.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderMedia.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderMedia.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -63,6 +63,12 @@
</span><span class="cx">         mediaElement().layoutSizeChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RenderMedia::styleDidChange(StyleDifference difference, const RenderStyle* oldStyle)
+{
+    RenderImage::styleDidChange(difference, oldStyle);
+    if (!oldStyle || style().visibility() != oldStyle-&gt;visibility())
+        mediaElement().visibilityDidChange();
+}
</ins><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderMediah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderMedia.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderMedia.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderMedia.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">     virtual bool requiresForcedStyleRecalcPropagation() const override final { return true; }
</span><span class="cx"> 
</span><span class="cx">     virtual bool shadowControlsNeedCustomLayoutMetrics() const override { return true; }
</span><ins>+    void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override final;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderObject.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -2196,6 +2196,18 @@
</span><span class="cx">         ensureRareData().setIsRenderFlowThread(isFlowThread);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RenderObject::setIsRegisteredForVisibleInViewportCallback(bool registered)
+{
+    if (registered || hasRareData())
+        ensureRareData().setIsRegisteredForVisibleInViewportCallback(registered);
+}
+
+void RenderObject::setVisibleInViewportState(VisibleInViewportState visible)
+{
+    if (visible != VisibilityUnknown || hasRareData())
+        ensureRareData().setVisibleInViewportState(visible);
+}
+
</ins><span class="cx"> RenderObject::RareDataHash&amp; RenderObject::rareDataMap()
</span><span class="cx"> {
</span><span class="cx">     static NeverDestroyed&lt;RareDataHash&gt; map;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderObject.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderObject.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderObject.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -504,7 +504,15 @@
</span><span class="cx">     bool isDragging() const { return m_bitfields.hasRareData() &amp;&amp; rareData().isDragging(); }
</span><span class="cx">     bool hasReflection() const { return m_bitfields.hasRareData() &amp;&amp; rareData().hasReflection(); }
</span><span class="cx">     bool isRenderFlowThread() const { return m_bitfields.hasRareData() &amp;&amp; rareData().isRenderFlowThread(); }
</span><ins>+    bool isRegisteredForVisibleInViewportCallback() { return m_bitfields.hasRareData() &amp;&amp; rareData().isRegisteredForVisibleInViewportCallback(); }
</ins><span class="cx"> 
</span><ins>+    enum VisibleInViewportState {
+        VisibilityUnknown,
+        VisibleInViewport,
+        NotVisibleInViewport,
+    };
+    VisibleInViewportState visibleInViewportState() { return m_bitfields.hasRareData() ? rareData().visibleInViewportState() : VisibilityUnknown; }
+
</ins><span class="cx">     bool hasLayer() const { return m_bitfields.hasLayer(); }
</span><span class="cx"> 
</span><span class="cx">     enum BoxDecorationState {
</span><span class="lines">@@ -613,6 +621,8 @@
</span><span class="cx">     void setIsDragging(bool);
</span><span class="cx">     void setHasReflection(bool = true);
</span><span class="cx">     void setIsRenderFlowThread(bool = true);
</span><ins>+    void setIsRegisteredForVisibleInViewportCallback(bool);
+    void setVisibleInViewportState(VisibleInViewportState);
</ins><span class="cx"> 
</span><span class="cx">     // Hook so that RenderTextControl can return the line height of its inner renderer.
</span><span class="cx">     // For other renderers, the value is the same as lineHeight(false).
</span><span class="lines">@@ -908,6 +918,13 @@
</span><span class="cx">         bool name() const { return m_##name; }\
</span><span class="cx">         void set##Name(bool name) { m_##name = name; }\
</span><span class="cx"> 
</span><ins>+#define ADD_ENUM_BITFIELD(name, Name, Type, width) \
+    private:\
+        unsigned m_##name : width;\
+    public:\
+        Type name() const { return static_cast&lt;Type&gt;(m_##name); }\
+        void set##Name(Type name) { m_##name = static_cast&lt;unsigned&gt;(name); }\
+
</ins><span class="cx">     class RenderObjectBitfields {
</span><span class="cx">         enum PositionedState {
</span><span class="cx">             IsStaticallyPositioned = 0,
</span><span class="lines">@@ -1012,12 +1029,18 @@
</span><span class="cx">             : m_isDragging(false)
</span><span class="cx">             , m_hasReflection(false)
</span><span class="cx">             , m_isRenderFlowThread(false)
</span><ins>+            , m_isRegisteredForVisibleInViewportCallback(false)
+            , m_visibleInViewportState(VisibilityUnknown)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         ADD_BOOLEAN_BITFIELD(isDragging, IsDragging);
</span><span class="cx">         ADD_BOOLEAN_BITFIELD(hasReflection, HasReflection);
</span><span class="cx">         ADD_BOOLEAN_BITFIELD(isRenderFlowThread, IsRenderFlowThread);
</span><ins>+
+        // From RenderElement
+        ADD_BOOLEAN_BITFIELD(isRegisteredForVisibleInViewportCallback, IsRegisteredForVisibleInViewportCallback);
+        ADD_ENUM_BITFIELD(visibleInViewportState, VisibleInViewportState, VisibleInViewportState, 2);
+
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     RenderObjectRareData rareData() const;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderView.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderView.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderView.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -1339,6 +1339,26 @@
</span><span class="cx">     return *m_imageQualityController;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RenderView::registerForVisibleInViewportCallback(RenderElement&amp; renderer)
+{
+    ASSERT(!m_visibleInViewportRenderers.contains(&amp;renderer));
+    m_visibleInViewportRenderers.add(&amp;renderer);
+}
+
+void RenderView::unregisterForVisibleInViewportCallback(RenderElement&amp; renderer)
+{
+    ASSERT(m_visibleInViewportRenderers.contains(&amp;renderer));
+    m_visibleInViewportRenderers.remove(&amp;renderer);
+}
+
+void RenderView::updateVisibleViewportRect(const IntRect&amp; visibleRect)
+{
+    resumePausedImageAnimationsIfNeeded(visibleRect);
+
+    for (auto* renderer : m_visibleInViewportRenderers)
+        renderer-&gt;visibleInViewportStateChanged(visibleRect.intersects(enclosingIntRect(renderer-&gt;absoluteClippedOverflowRect())) ? RenderElement::VisibleInViewport : RenderElement::NotVisibleInViewport);
+}
+
</ins><span class="cx"> void RenderView::addRendererWithPausedImageAnimations(RenderElement&amp; renderer)
</span><span class="cx"> {
</span><span class="cx">     if (renderer.hasPausedImageAnimations()) {
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderView.h (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderView.h        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/rendering/RenderView.h        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -225,6 +225,9 @@
</span><span class="cx">     void didCreateRenderer() { ++m_rendererCount; }
</span><span class="cx">     void didDestroyRenderer() { --m_rendererCount; }
</span><span class="cx"> 
</span><ins>+    void updateVisibleViewportRect(const IntRect&amp;);
+    void registerForVisibleInViewportCallback(RenderElement&amp;);
+    void unregisterForVisibleInViewportCallback(RenderElement&amp;);
</ins><span class="cx">     void resumePausedImageAnimationsIfNeeded(IntRect visibleRect);
</span><span class="cx">     void addRendererWithPausedImageAnimations(RenderElement&amp;);
</span><span class="cx">     void removeRendererWithPausedImageAnimations(RenderElement&amp;);
</span><span class="lines">@@ -374,6 +377,7 @@
</span><span class="cx">     bool m_usesFirstLetterRules { false };
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;RenderElement*&gt; m_renderersWithPausedImageAnimation;
</span><ins>+    HashSet&lt;RenderElement*&gt; m_visibleInViewportRenderers;
</ins><span class="cx">     Vector&lt;RefPtr&lt;RenderWidget&gt;&gt; m_protectedRenderWidgets;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SERVICE_CONTROLS)
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (192965 => 192966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2015-12-02 22:09:16 UTC (rev 192965)
+++ trunk/Source/WebCore/testing/Internals.cpp        2015-12-02 22:09:58 UTC (rev 192966)
</span><span class="lines">@@ -2823,6 +2823,8 @@
</span><span class="cx">             restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
</span><span class="cx">         if (equalIgnoringCase(restrictionString, &quot;AutoPreloadingNotPermitted&quot;))
</span><span class="cx">             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
</span><ins>+        if (equalIgnoringCase(restrictionString, &quot;InvisibleAutoplayNotPermitted&quot;))
+            restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
</ins><span class="cx">     }
</span><span class="cx">     element-&gt;mediaSession().addBehaviorRestriction(restrictions);
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>