<!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>[205412] 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/205412">205412</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2016-09-03 17:24:14 -0700 (Sat, 03 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Refactor the heuristic for showing media controls to take all media sessions into account
https://bugs.webkit.org/show_bug.cgi?id=161503
&lt;rdar://problem/28033783&gt;

Reviewed by Darin Adler.

Source/WebCore:

Currently, when selecting a media session to show playback controls for, we grab the first media session that
passes our heuristic. Using this method, we are unable to take additional factors into account, such as whether
another media session's element is scrolled in view, or if another media session has been interacted with more
recently. To address this, we make the following changes:

    1.  Consider the list of all MediaElementSessions.

    2.  Select only the MediaElementSessions capable of showing media controls and sort the list by a special
        heuristic that takes visibility and time of last user interaction into account. The first element on
        this list is the strongest candidate for main content.

    3.  If this strongest candidate is visible in the viewport, or it is playing with audio, we return this
        as the chosen candidate. Otherwise, we return this session only if no other non-candidate video could be
        confused as the main content (i.e. the non-candidate video is not only visible in the viewport, but also
        large enough to be considered main content).

Using this new method of determining the video to show controls for, we retain previous behavior for pages with
a single video. On pages with multiple videos, the above logic ensures that if the current controlled video is
paused, scrolled out of view, and then a new video is scrolled into view, we will either hide media controls to
avoid confusion if that video could be confused for main content (using the mechanism in step 3), or we
hook up the media controls to the new video if it satisfies main content (using the mechanism in step 2).

This patch also adds 6 new TestWebKitAPI unit tests.

* html/HTMLMediaElement.cpp:
(WebCore::mediaElementSessionInfoForSession):
(WebCore::preferMediaControlsForCandidateSessionOverOtherCandidateSession):
(WebCore::mediaSessionMayBeConfusedWithMainContent):
(WebCore::bestMediaSessionForShowingPlaybackControlsManager):
(WebCore::HTMLMediaElement::didAttachRenderers):
(WebCore::HTMLMediaElement::layoutSizeChanged):
(WebCore::HTMLMediaElement::isVisibleInViewportChanged):
(WebCore::HTMLMediaElement::resetPlaybackSessionState):
(WebCore::HTMLMediaElement::isVisibleInViewport):
(WebCore::HTMLMediaElement::updatePlaybackControlsManager):
* html/HTMLMediaElement.h:
* html/MediaElementSession.cpp:
(WebCore::MediaElementSession::removeBehaviorRestriction):
(WebCore::MediaElementSession::canShowControlsManager):
(WebCore::MediaElementSession::isLargeEnoughForMainContent):
(WebCore::MediaElementSession::mostRecentUserInteractionTime):
(WebCore::MediaElementSession::wantsToObserveViewportVisibilityForMediaControls):
(WebCore::MediaElementSession::wantsToObserveViewportVisibilityForAutoplay):
(WebCore::MediaElementSession::resetPlaybackSessionState):
(WebCore::MediaElementSession::canControlControlsManager): Deleted.
* html/MediaElementSession.h:
* platform/audio/PlatformMediaSession.h:
(WebCore::PlatformMediaSession::resetPlaybackSessionState):
(WebCore::PlatformMediaSession::canControlControlsManager): Deleted.
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::currentSessionsMatching):
(WebCore::PlatformMediaSessionManager::currentSessionMatching): Deleted.
* platform/audio/PlatformMediaSessionManager.h:
* platform/cocoa/WebPlaybackSessionModelMediaElement.mm:
(WebPlaybackSessionModelMediaElement::setMediaElement):

Source/WebKit2:

Adds an SPI testing hook for sending the element ID of the currently controlled video element from the web
process to the UI process. See VideoControlsManager.mm in Tools/TestWebKitAPI/ for usage.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _requestControlledElementID]):
(-[WKWebView _handleControlledElementIDResponse:]):
(-[WKWebView _hasActiveVideoForControlsManager]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h:
* UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in:
* UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm:
(WebKit::WebPlaybackSessionManagerProxy::handleControlledElementIDResponse):
(WebKit::WebPlaybackSessionManagerProxy::requestControlledElementID):
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::requestControlledElementID):
(WebKit::WebPageProxy::handleControlledElementIDResponse):
* UIProcess/WebPageProxy.h:
* UIProcess/mac/PageClientImpl.h:
* UIProcess/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::handleControlledElementIDResponse):
* WebProcess/cocoa/WebPlaybackSessionManager.h:
* WebProcess/cocoa/WebPlaybackSessionManager.messages.in:
* WebProcess/cocoa/WebPlaybackSessionManager.mm:
(WebKit::WebPlaybackSessionManager::handleControlledElementIDRequest):

Tools:

Adds new unit tests verifying the behavior of media playback controls when scrolling another video into view.
Please see the WebCore ChangeLog for more details about this change. Also refactors existing
VideoControlsManager tests by folding duplicated setup and testing logic into helper methods to make the unit
tests more readable.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm:
(-[MessageHandler initWithMessage:handler:]):
(-[MessageHandler userContentController:didReceiveScriptMessage:]):
(-[VideoControlsManagerTestWebView performAfterLoading:]):
(-[VideoControlsManagerTestWebView loadTestPageNamed:]):
(-[VideoControlsManagerTestWebView loadTestPageNamed:andExpectControlsManager:afterReceivingMessage:]):
(-[VideoControlsManagerTestWebView performAfterReceivingMessage:action:]):
(-[VideoControlsManagerTestWebView controlledElementID]):
(-[VideoControlsManagerTestWebView _handleControlledElementIDResponse:]):
(TestWebKitAPI::setUpWebViewForTestingVideoControlsManager):
(TestWebKitAPI::TEST):
(-[MediaPlaybackMessageHandler initWithWKWebView:finalMessageString:]): Deleted.
(-[MediaPlaybackMessageHandler userContentController:didReceiveScriptMessage:]): Deleted.
(-[OnLoadMessageHandler initWithWKWebView:handler:]): Deleted.
(-[OnLoadMessageHandler userContentController:didReceiveScriptMessage:]): Deleted.
(-[WKWebView performAfterLoading:]): Deleted.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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="#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="#trunkSourceWebCoreplatformaudioPlatformMediaSessionManagerh">trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformcocoaWebPlaybackSessionModelMediaElementmm">trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxyh">trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxymessagesin">trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxymm">trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacPageClientImplh">trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacPageClientImplmm">trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagerh">trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagermessagesin">trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagermm">trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2CocoaVideoControlsManagermm">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideoplayingscrollawayhtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosautoplayingclicktopausehtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosautoplayingscrolltovideohtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideospausedvideohidescontrolshtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosplayingmutedvideohidescontrolshtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosplayingvideokeepscontrolshtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/ChangeLog        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2016-09-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Refactor the heuristic for showing media controls to take all media sessions into account
+        https://bugs.webkit.org/show_bug.cgi?id=161503
+        &lt;rdar://problem/28033783&gt;
+
+        Reviewed by Darin Adler.
+
+        Currently, when selecting a media session to show playback controls for, we grab the first media session that
+        passes our heuristic. Using this method, we are unable to take additional factors into account, such as whether
+        another media session's element is scrolled in view, or if another media session has been interacted with more
+        recently. To address this, we make the following changes:
+
+            1.  Consider the list of all MediaElementSessions.
+
+            2.  Select only the MediaElementSessions capable of showing media controls and sort the list by a special
+                heuristic that takes visibility and time of last user interaction into account. The first element on
+                this list is the strongest candidate for main content.
+
+            3.  If this strongest candidate is visible in the viewport, or it is playing with audio, we return this
+                as the chosen candidate. Otherwise, we return this session only if no other non-candidate video could be
+                confused as the main content (i.e. the non-candidate video is not only visible in the viewport, but also
+                large enough to be considered main content).
+
+        Using this new method of determining the video to show controls for, we retain previous behavior for pages with
+        a single video. On pages with multiple videos, the above logic ensures that if the current controlled video is
+        paused, scrolled out of view, and then a new video is scrolled into view, we will either hide media controls to
+        avoid confusion if that video could be confused for main content (using the mechanism in step 3), or we
+        hook up the media controls to the new video if it satisfies main content (using the mechanism in step 2).
+
+        This patch also adds 6 new TestWebKitAPI unit tests.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::mediaElementSessionInfoForSession):
+        (WebCore::preferMediaControlsForCandidateSessionOverOtherCandidateSession):
+        (WebCore::mediaSessionMayBeConfusedWithMainContent):
+        (WebCore::bestMediaSessionForShowingPlaybackControlsManager):
+        (WebCore::HTMLMediaElement::didAttachRenderers):
+        (WebCore::HTMLMediaElement::layoutSizeChanged):
+        (WebCore::HTMLMediaElement::isVisibleInViewportChanged):
+        (WebCore::HTMLMediaElement::resetPlaybackSessionState):
+        (WebCore::HTMLMediaElement::isVisibleInViewport):
+        (WebCore::HTMLMediaElement::updatePlaybackControlsManager):
+        * html/HTMLMediaElement.h:
+        * html/MediaElementSession.cpp:
+        (WebCore::MediaElementSession::removeBehaviorRestriction):
+        (WebCore::MediaElementSession::canShowControlsManager):
+        (WebCore::MediaElementSession::isLargeEnoughForMainContent):
+        (WebCore::MediaElementSession::mostRecentUserInteractionTime):
+        (WebCore::MediaElementSession::wantsToObserveViewportVisibilityForMediaControls):
+        (WebCore::MediaElementSession::wantsToObserveViewportVisibilityForAutoplay):
+        (WebCore::MediaElementSession::resetPlaybackSessionState):
+        (WebCore::MediaElementSession::canControlControlsManager): Deleted.
+        * html/MediaElementSession.h:
+        * platform/audio/PlatformMediaSession.h:
+        (WebCore::PlatformMediaSession::resetPlaybackSessionState):
+        (WebCore::PlatformMediaSession::canControlControlsManager): Deleted.
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::currentSessionsMatching):
+        (WebCore::PlatformMediaSessionManager::currentSessionMatching): Deleted.
+        * platform/audio/PlatformMediaSessionManager.h:
+        * platform/cocoa/WebPlaybackSessionModelMediaElement.mm:
+        (WebPlaybackSessionModelMediaElement::setMediaElement):
+
</ins><span class="cx"> 2016-09-03  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Streamline DOMImplementation, and move it to our new DOM exception system
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -346,6 +346,79 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+struct MediaElementSessionInfo {
+    const MediaElementSession* session;
+
+    double timeOfLastUserInteraction;
+    bool canShowControlsManager : 1;
+    bool isVisibleInViewportOrFullscreen : 1;
+    bool isLargeEnoughForMainContent : 1;
+    bool isPlayingAudio : 1;
+};
+
+static MediaElementSessionInfo mediaElementSessionInfoForSession(const MediaElementSession&amp; session)
+{
+    const HTMLMediaElement&amp; element = session.element();
+    return {
+        &amp;session,
+        session.mostRecentUserInteractionTime(),
+        session.canShowControlsManager(),
+        element.isFullscreen() || element.isVisibleInViewport(),
+        session.isLargeEnoughForMainContent(),
+        element.isPlaying() &amp;&amp; element.hasAudio() &amp;&amp; !element.muted()
+    };
+}
+
+static bool preferMediaControlsForCandidateSessionOverOtherCandidateSession(const MediaElementSessionInfo&amp; session, const MediaElementSessionInfo&amp; otherSession)
+{
+    // Prioritize visible media over offscreen media.
+    if (session.isVisibleInViewportOrFullscreen != otherSession.isVisibleInViewportOrFullscreen)
+        return session.isVisibleInViewportOrFullscreen;
+
+    // As a tiebreaker, prioritize elements that the user recently interacted with.
+    return session.timeOfLastUserInteraction &gt; otherSession.timeOfLastUserInteraction;
+}
+
+static bool mediaSessionMayBeConfusedWithMainContent(const MediaElementSessionInfo&amp; session)
+{
+    if (!session.isVisibleInViewportOrFullscreen)
+        return false;
+
+    if (!session.isLargeEnoughForMainContent)
+        return false;
+
+    // Even if this video is not a candidate, if it is visible to the user and large enough
+    // to be main content, it poses a risk for being confused with main content.
+    return true;
+}
+
+static const MediaElementSession* bestMediaSessionForShowingPlaybackControlsManager()
+{
+    auto allSessions = PlatformMediaSessionManager::sharedManager().currentSessionsMatching([] (const PlatformMediaSession&amp; session) {
+        return is&lt;MediaElementSession&gt;(session);
+    });
+
+    Vector&lt;MediaElementSessionInfo&gt; candidateSessions;
+    bool atLeastOneNonCandidateMayBeConfusedForMainContent = false;
+    for (auto&amp; session : allSessions) {
+        auto mediaElementSessionInfo = mediaElementSessionInfoForSession(downcast&lt;MediaElementSession&gt;(*session));
+        if (mediaElementSessionInfo.canShowControlsManager)
+            candidateSessions.append(mediaElementSessionInfo);
+        else if (mediaSessionMayBeConfusedWithMainContent(mediaElementSessionInfo))
+            atLeastOneNonCandidateMayBeConfusedForMainContent = true;
+    }
+
+    if (!candidateSessions.size())
+        return nullptr;
+
+    std::sort(candidateSessions.begin(), candidateSessions.end(), preferMediaControlsForCandidateSessionOverOtherCandidateSession);
+    auto strongestSessionCandidate = candidateSessions.first();
+    if (!strongestSessionCandidate.isVisibleInViewportOrFullscreen &amp;&amp; !strongestSessionCandidate.isPlayingAudio &amp;&amp; atLeastOneNonCandidateMayBeConfusedForMainContent)
+        return nullptr;
+
+    return strongestSessionCandidate.session;
+}
+
</ins><span class="cx"> HTMLMediaElement::HTMLMediaElement(const QualifiedName&amp; tagName, Document&amp; document, bool createdByParser)
</span><span class="cx">     : HTMLElement(tagName, document)
</span><span class="cx">     , ActiveDOMObject(&amp;document)
</span><span class="lines">@@ -837,8 +910,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (auto* renderer = this-&gt;renderer()) {
</span><span class="cx">         renderer-&gt;updateFromElement();
</span><del>-        if (m_mediaSession-&gt;hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted)
-            || m_mediaSession-&gt;hasBehaviorRestriction(MediaElementSession::OverrideUserGestureRequirementForMainContent))
</del><ins>+        if (m_mediaSession &amp;&amp; m_mediaSession-&gt;wantsToObserveViewportVisibilityForAutoplay())
</ins><span class="cx">             renderer-&gt;registerForVisibleInViewportCallback();
</span><span class="cx">     }
</span><span class="cx">     updateShouldAutoplay();
</span><span class="lines">@@ -4022,6 +4094,11 @@
</span><span class="cx">         m_receivedLayoutSizeChanged = true;
</span><span class="cx">         scheduleUpdatePlaybackControlsManager();
</span><span class="cx">     }
</span><ins>+
+    // If the video is a candidate for main content, we should register it for viewport visibility callbacks
+    // if it hasn't already been registered.
+    if (renderer() &amp;&amp; m_mediaSession &amp;&amp; !m_mediaSession-&gt;wantsToObserveViewportVisibilityForAutoplay() &amp;&amp; m_mediaSession-&gt;wantsToObserveViewportVisibilityForMediaControls())
+        renderer()-&gt;registerForVisibleInViewportCallback();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::visibilityDidChange()
</span><span class="lines">@@ -7141,6 +7218,7 @@
</span><span class="cx"> void HTMLMediaElement::isVisibleInViewportChanged()
</span><span class="cx"> {
</span><span class="cx">     updateShouldAutoplay();
</span><ins>+    scheduleUpdatePlaybackControlsManager();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::updateShouldAutoplay()
</span><span class="lines">@@ -7169,6 +7247,18 @@
</span><span class="cx">         play();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaElement::resetPlaybackSessionState()
+{
+    if (m_mediaSession)
+        m_mediaSession-&gt;resetPlaybackSessionState();
+}
+
+bool HTMLMediaElement::isVisibleInViewport() const
+{
+    auto renderer = this-&gt;renderer();
+    return renderer &amp;&amp; renderer-&gt;visibleInViewportState() == RenderElement::VisibleInViewport;
+}
+
</ins><span class="cx"> void HTMLMediaElement::updatePlaybackControlsManager()
</span><span class="cx"> {
</span><span class="cx">     Page* page = document().page();
</span><span class="lines">@@ -7175,14 +7265,11 @@
</span><span class="cx">     if (!page)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    PlatformMediaSession* session = PlatformMediaSessionManager::sharedManager().currentSessionMatching([] (const PlatformMediaSession&amp; session) {
-        return session.canControlControlsManager();
-    });
-
-    if (!is&lt;MediaElementSession&gt;(session))
</del><ins>+    // FIXME: Ensure that the renderer here should be up to date.
+    if (auto bestMediaSession = bestMediaSessionForShowingPlaybackControlsManager())
+        page-&gt;chrome().client().setUpPlaybackControlsManager(bestMediaSession-&gt;element());
+    else
</ins><span class="cx">         page-&gt;chrome().client().clearPlaybackControlsManager();
</span><del>-    else
-        page-&gt;chrome().client().setUpPlaybackControlsManager(downcast&lt;MediaElementSession&gt;(session)-&gt;element());
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::scheduleUpdatePlaybackControlsManager()
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -468,6 +468,9 @@
</span><span class="cx"> 
</span><span class="cx">     RenderMedia* renderer() const;
</span><span class="cx"> 
</span><ins>+    void resetPlaybackSessionState();
+    bool isVisibleInViewport() const;
+
</ins><span class="cx"> protected:
</span><span class="cx">     HTMLMediaElement(const QualifiedName&amp;, Document&amp;, bool createdByParser);
</span><span class="cx">     virtual ~HTMLMediaElement();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlMediaElementSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/MediaElementSession.cpp (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/MediaElementSession.cpp        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/html/MediaElementSession.cpp        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #include &quot;RenderView.h&quot;
</span><span class="cx"> #include &quot;ScriptController.h&quot;
</span><span class="cx"> #include &quot;SourceBuffer.h&quot;
</span><ins>+#include &lt;wtf/CurrentTime.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> #include &quot;AudioSession.h&quot;
</span><span class="lines">@@ -137,6 +138,9 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaElementSession::removeBehaviorRestriction(BehaviorRestrictions restriction)
</span><span class="cx"> {
</span><ins>+    if (restriction &amp; RequireUserGestureToControlControlsManager)
+        m_mostRecentUserInteractionTime = monotonicallyIncreasingTime();
+
</ins><span class="cx">     LOG(Media, &quot;MediaElementSession::removeBehaviorRestriction - removing %s&quot;, restrictionName(restriction).utf8().data());
</span><span class="cx">     m_restrictions &amp;= ~restriction;
</span><span class="cx"> }
</span><span class="lines">@@ -212,69 +216,89 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MediaElementSession::canControlControlsManager() const
</del><ins>+bool MediaElementSession::canShowControlsManager() const
</ins><span class="cx"> {
</span><span class="cx">     if (m_element.isFullscreen()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning TRUE: Is fullscreen&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning TRUE: Is fullscreen&quot;);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_element.hasAudio()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: No audio&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: No audio&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_element.document().activeDOMObjectsAreSuspended()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: activeDOMObjectsAreSuspended()&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: activeDOMObjectsAreSuspended()&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!playbackPermitted(m_element)) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: Playback not permitted&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: Playback not permitted&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!hasBehaviorRestriction(RequireUserGestureToControlControlsManager) || ScriptController::processingUserGestureForMedia()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning TRUE: No user gesture required&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning TRUE: No user gesture required&quot;);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (hasBehaviorRestriction(RequirePlaybackToControlControlsManager) &amp;&amp; !m_element.isPlaying()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: Needs to be playing&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: Needs to be playing&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_element.muted()) {
</span><del>-        LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: Muted&quot;);
</del><ins>+        LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: Muted&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_element.isVideo()) {
</span><span class="cx">         if (!m_element.renderer()) {
</span><del>-            LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: No renderer&quot;);
</del><ins>+            LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: No renderer&quot;);
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_element.document().isMediaDocument()) {
</span><del>-            LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning TRUE: Is media document&quot;);
</del><ins>+            LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning TRUE: Is media document&quot;);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!m_element.hasVideo()) {
</span><del>-            LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: No video&quot;);
</del><ins>+            LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: No video&quot;);
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (isElementLargeEnoughForMainContent(m_element)) {
-            LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning TRUE: Is main content&quot;);
</del><ins>+        if (isLargeEnoughForMainContent()) {
+            LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning TRUE: Is main content&quot;);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    LOG(Media, &quot;MediaElementSession::canControlControlsManager - returning FALSE: No user gesture&quot;);
</del><ins>+    LOG(Media, &quot;MediaElementSession::canShowControlsManager - returning FALSE: No user gesture&quot;);
</ins><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool MediaElementSession::isLargeEnoughForMainContent() const
+{
+    return isElementLargeEnoughForMainContent(m_element);
+}
+
+double MediaElementSession::mostRecentUserInteractionTime() const
+{
+    return m_mostRecentUserInteractionTime;
+}
+
+bool MediaElementSession::wantsToObserveViewportVisibilityForMediaControls() const
+{
+    return isLargeEnoughForMainContent();
+}
+
+bool MediaElementSession::wantsToObserveViewportVisibilityForAutoplay() const
+{
+    return hasBehaviorRestriction(InvisibleAutoplayNotPermitted) || hasBehaviorRestriction(OverrideUserGestureRequirementForMainContent);
+}
+
</ins><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="cx"> void MediaElementSession::showPlaybackTargetPicker(const HTMLMediaElement&amp; element)
</span><span class="cx"> {
</span><span class="lines">@@ -502,6 +526,12 @@
</span><span class="cx">     
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaElementSession::resetPlaybackSessionState()
+{
+    m_mostRecentUserInteractionTime = 0;
+    addBehaviorRestriction(RequireUserGestureToControlControlsManager | RequirePlaybackToControlControlsManager);
+}
+
</ins><span class="cx"> bool MediaElementSession::allowsPictureInPicture(const HTMLMediaElement&amp; element) const
</span><span class="cx"> {
</span><span class="cx">     Settings* settings = element.document().settings();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlMediaElementSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/MediaElementSession.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/MediaElementSession.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/html/MediaElementSession.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -54,8 +54,6 @@
</span><span class="cx">     bool pageAllowsDataLoading(const HTMLMediaElement&amp;) const;
</span><span class="cx">     bool pageAllowsPlaybackAfterResuming(const HTMLMediaElement&amp;) const;
</span><span class="cx"> 
</span><del>-    bool canControlControlsManager() const override;
-
</del><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="cx">     void showPlaybackTargetPicker(const HTMLMediaElement&amp;);
</span><span class="cx">     bool hasWirelessPlaybackTargets(const HTMLMediaElement&amp;) const;
</span><span class="lines">@@ -78,6 +76,8 @@
</span><span class="cx"> 
</span><span class="cx">     void mediaEngineUpdated(const HTMLMediaElement&amp;);
</span><span class="cx"> 
</span><ins>+    void resetPlaybackSessionState() override;
+
</ins><span class="cx">     // Restrictions to modify default behaviors.
</span><span class="cx">     enum BehaviorRestrictionFlags : unsigned {
</span><span class="cx">         NoRestrictions = 0,
</span><span class="lines">@@ -111,6 +111,12 @@
</span><span class="cx"> 
</span><span class="cx">     HTMLMediaElement&amp; element() const { return m_element; }
</span><span class="cx"> 
</span><ins>+    bool wantsToObserveViewportVisibilityForMediaControls() const;
+    bool wantsToObserveViewportVisibilityForAutoplay() const;
+    bool canShowControlsManager() const;
+    bool isLargeEnoughForMainContent() const;
+    double mostRecentUserInteractionTime() const;
+
</ins><span class="cx"> private:
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="lines">@@ -140,6 +146,8 @@
</span><span class="cx">     bool m_hasPlaybackTargetAvailabilityListeners { false };
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    double m_mostRecentUserInteractionTime { 0 };
+
</ins><span class="cx">     mutable bool m_isMainContent { false };
</span><span class="cx">     Timer m_mainContentCheckTimer;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -145,7 +145,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool shouldOverrideBackgroundLoadingRestriction() const;
</span><span class="cx"> 
</span><del>-    virtual bool canControlControlsManager() const { return false; }
</del><span class="cx">     virtual bool canPlayToWirelessPlaybackTarget() const { return false; }
</span><span class="cx">     virtual bool isPlayingToWirelessPlaybackTarget() const { return m_isPlayingToWirelessPlaybackTarget; }
</span><span class="cx">     void isPlayingToWirelessPlaybackTargetChanged(bool);
</span><span class="lines">@@ -166,6 +165,7 @@
</span><span class="cx">     void setCanProduceAudio(bool);
</span><span class="cx"> 
</span><span class="cx">     void scheduleClientDataBufferingCheck();
</span><ins>+    virtual void resetPlaybackSessionState() { }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     PlatformMediaSessionClient&amp; client() const { return m_client; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -280,13 +280,14 @@
</span><span class="cx">     return m_sessions[0];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformMediaSession* PlatformMediaSessionManager::currentSessionMatching(std::function&lt;bool(const PlatformMediaSession &amp;)&gt; filter)
</del><ins>+Vector&lt;PlatformMediaSession*&gt; PlatformMediaSessionManager::currentSessionsMatching(std::function&lt;bool(const PlatformMediaSession &amp;)&gt; filter)
</ins><span class="cx"> {
</span><ins>+    Vector&lt;PlatformMediaSession*&gt; matchingSessions;
</ins><span class="cx">     for (auto&amp; session : m_sessions) {
</span><span class="cx">         if (filter(*session))
</span><del>-            return session;
</del><ins>+            matchingSessions.append(session);
</ins><span class="cx">     }
</span><del>-    return nullptr;
</del><ins>+    return matchingSessions;
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> bool PlatformMediaSessionManager::sessionCanLoadMedia(const PlatformMediaSession&amp; session) const
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx">     void setCurrentSession(PlatformMediaSession&amp;);
</span><span class="cx">     PlatformMediaSession* currentSession() const;
</span><span class="cx"> 
</span><del>-    PlatformMediaSession* currentSessionMatching(std::function&lt;bool(const PlatformMediaSession&amp;)&gt;);
</del><ins>+    Vector&lt;PlatformMediaSession*&gt; currentSessionsMatching(std::function&lt;bool(const PlatformMediaSession&amp;)&gt;);
</ins><span class="cx"> 
</span><span class="cx">     void sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession&amp;);
</span><span class="cx">     void sessionCanProduceAudioChanged(PlatformMediaSession&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcocoaWebPlaybackSessionModelMediaElementmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebCore/platform/cocoa/WebPlaybackSessionModelMediaElement.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -67,6 +67,9 @@
</span><span class="cx">     }
</span><span class="cx">     m_isListening = false;
</span><span class="cx"> 
</span><ins>+    if (m_mediaElement)
+        m_mediaElement-&gt;resetPlaybackSessionState();
+
</ins><span class="cx">     m_mediaElement = mediaElement;
</span><span class="cx"> 
</span><span class="cx">     if (m_mediaElement) {
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/ChangeLog        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2016-09-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Refactor the heuristic for showing media controls to take all media sessions into account
+        https://bugs.webkit.org/show_bug.cgi?id=161503
+        &lt;rdar://problem/28033783&gt;
+
+        Reviewed by Darin Adler.
+
+        Adds an SPI testing hook for sending the element ID of the currently controlled video element from the web
+        process to the UI process. See VideoControlsManager.mm in Tools/TestWebKitAPI/ for usage.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _requestControlledElementID]):
+        (-[WKWebView _handleControlledElementIDResponse:]):
+        (-[WKWebView _hasActiveVideoForControlsManager]): Deleted.
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h:
+        * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in:
+        * UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm:
+        (WebKit::WebPlaybackSessionManagerProxy::handleControlledElementIDResponse):
+        (WebKit::WebPlaybackSessionManagerProxy::requestControlledElementID):
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::requestControlledElementID):
+        (WebKit::WebPageProxy::handleControlledElementIDResponse):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/mac/PageClientImpl.h:
+        * UIProcess/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::handleControlledElementIDResponse):
+        * WebProcess/cocoa/WebPlaybackSessionManager.h:
+        * WebProcess/cocoa/WebPlaybackSessionManager.messages.in:
+        * WebProcess/cocoa/WebPlaybackSessionManager.mm:
+        (WebKit::WebPlaybackSessionManager::handleControlledElementIDRequest):
+
</ins><span class="cx"> 2016-09-03  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Streamline DOMImplementation, and move it to our new DOM exception system
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -4553,6 +4553,17 @@
</span><span class="cx"> {
</span><span class="cx">     return _page &amp;&amp; _page-&gt;hasActiveVideoForControlsManager();
</span><span class="cx"> }
</span><ins>+
+- (void)_requestControlledElementID
+{
+    if (_page)
+        _page-&gt;requestControlledElementID();
+}
+
+- (void)_handleControlledElementIDResponse:(NSString *)identifier
+{
+    // Overridden by subclasses.
+}
</ins><span class="cx"> #endif // PLATFORM(MAC)
</span><span class="cx"> 
</span><span class="cx"> // Execute the supplied block after the next transaction from the WebProcess.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -271,6 +271,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if !TARGET_OS_IPHONE
</span><span class="cx"> @property (nonatomic, readonly) BOOL _hasActiveVideoForControlsManager WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</span><ins>+- (void)_requestControlledElementID WK_API_AVAILABLE(macosx(WK_MAC_TBA));
+- (void)_handleControlledElementIDResponse:(NSString *)identifier WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> - (void)_doAfterNextPresentationUpdate:(void (^)(void))updateBlock WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -146,6 +146,7 @@
</span><span class="cx">     void invalidate();
</span><span class="cx"> 
</span><span class="cx">     PlatformWebPlaybackSessionInterface* controlsManagerInterface();
</span><ins>+    void requestControlledElementID();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class WebPlaybackSessionModelContext;
</span><span class="lines">@@ -176,6 +177,7 @@
</span><span class="cx">     void setWirelessVideoPlaybackDisabled(uint64_t contextId, bool);
</span><span class="cx">     void setDuration(uint64_t contextId, double duration);
</span><span class="cx">     void setRate(uint64_t contextId, bool isPlaying, double rate);
</span><ins>+    void handleControlledElementIDResponse(uint64_t, String) const;
</ins><span class="cx"> 
</span><span class="cx">     // Messages to WebPlaybackSessionManager
</span><span class="cx">     void play(uint64_t contextId);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.messages.in        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -35,5 +35,7 @@
</span><span class="cx">     SetRate(uint64_t contextId, bool isPlaying, double rate)
</span><span class="cx">     SetUpPlaybackControlsManagerWithID(uint64_t contextId)
</span><span class="cx">     ClearPlaybackControlsManager()
</span><ins>+
+    HandleControlledElementIDResponse(uint64_t contextId, String id)
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebPlaybackSessionManagerProxymm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebPlaybackSessionManagerProxy.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -394,6 +394,19 @@
</span><span class="cx">     ensureModel(contextId).setRate(isPlaying, rate);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+void WebPlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t contextId, String identifier) const
+{
+#if PLATFORM(MAC)
+    if (contextId == m_controlsManagerContextId)
+        m_page-&gt;handleControlledElementIDResponse(identifier);
+#else
+    UNUSED_PARAM(contextId);
+    UNUSED_PARAM(identifier);
+#endif
+}
+
+
</ins><span class="cx"> #pragma mark Messages to WebPlaybackSessionManager
</span><span class="cx"> 
</span><span class="cx"> void WebPlaybackSessionManagerProxy::play(uint64_t contextId)
</span><span class="lines">@@ -456,6 +469,12 @@
</span><span class="cx">     m_page-&gt;send(Messages::WebPlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page-&gt;pageID());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPlaybackSessionManagerProxy::requestControlledElementID()
+{
+    if (m_controlsManagerContextId)
+        m_page-&gt;send(Messages::WebPlaybackSessionManager::HandleControlledElementIDRequest(m_controlsManagerContextId), m_page-&gt;pageID());
+}
+
</ins><span class="cx"> PlatformWebPlaybackSessionInterface* WebPlaybackSessionManagerProxy::controlsManagerInterface()
</span><span class="cx"> {
</span><span class="cx">     if (!m_controlsManagerContextId)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -247,6 +247,7 @@
</span><span class="cx">     virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String&amp; replacedString, const String&amp; replacementString) = 0;
</span><span class="cx">     virtual void recommendedScrollbarStyleDidChange(WebCore::ScrollbarStyle) = 0;
</span><span class="cx">     virtual void removeNavigationGestureSnapshot() = 0;
</span><ins>+    virtual void handleControlledElementIDResponse(const String&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual CGRect boundsOfLayerInLayerBackedWindowCoordinates(CALayer *) const = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -6298,6 +6298,19 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::requestControlledElementID() const
+{
+#if ENABLE(VIDEO_PRESENTATION_MODE)
+    if (m_playbackSessionManager)
+        m_playbackSessionManager-&gt;requestControlledElementID();
+#endif
+}
+
+void WebPageProxy::handleControlledElementIDResponse(const String&amp; identifier) const
+{
+    m_pageClient.handleControlledElementIDResponse(identifier);
+}
+
</ins><span class="cx"> bool WebPageProxy::isPlayingVideoInEnhancedFullscreen() const
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(VIDEO_PRESENTATION_MODE)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -1031,6 +1031,8 @@
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     void videoControlsManagerDidChange();
</span><span class="cx">     bool hasActiveVideoForControlsManager() const;
</span><ins>+    void requestControlledElementID() const;
+    void handleControlledElementIDResponse(const String&amp;) const;
</ins><span class="cx">     bool isPlayingVideoInEnhancedFullscreen() const;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacPageClientImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -206,6 +206,7 @@
</span><span class="cx">     void didFailLoadForMainFrame() override;
</span><span class="cx">     void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType) override;
</span><span class="cx">     void removeNavigationGestureSnapshot() override;
</span><ins>+    void handleControlledElementIDResponse(const String&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     void didPerformImmediateActionHitTest(const WebHitTestResultData&amp;, bool contentPreventsDefault, API::Object*) override;
</span><span class="cx">     void* immediateActionAnimationControllerForHitTestResult(RefPtr&lt;API::HitTestResult&gt;, uint64_t, RefPtr&lt;API::Object&gt;) override;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacPageClientImplmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -752,6 +752,13 @@
</span><span class="cx">         gestureController-&gt;removeSwipeSnapshot();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::handleControlledElementIDResponse(const String&amp; identifier)
+{
+#if WK_API_ENABLED
+    [m_webView _handleControlledElementIDResponse:nsStringFromWebCoreString(identifier)];
+#endif
+}
+
</ins><span class="cx"> void PageClientImpl::didChangeBackgroundColor()
</span><span class="cx"> {
</span><span class="cx">     notImplemented();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.h (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.h        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.h        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -143,6 +143,7 @@
</span><span class="cx">     void endScanning(uint64_t contextId);
</span><span class="cx">     void selectAudioMediaOption(uint64_t contextId, uint64_t index);
</span><span class="cx">     void selectLegibleMediaOption(uint64_t contextId, uint64_t index);
</span><ins>+    void handleControlledElementIDRequest(uint64_t contextId);
</ins><span class="cx"> 
</span><span class="cx">     WebPage* m_page;
</span><span class="cx">     HashMap&lt;WebCore::HTMLMediaElement*, uint64_t&gt; m_mediaElements;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagermessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.messages.in (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.messages.in        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.messages.in        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -35,5 +35,6 @@
</span><span class="cx">     EndScanning(uint64_t contextId)
</span><span class="cx">     SelectAudioMediaOption(uint64_t contextId, uint64_t index)
</span><span class="cx">     SelectLegibleMediaOption(uint64_t contextId, uint64_t index)
</span><ins>+    HandleControlledElementIDRequest(uint64_t contextId)
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcesscocoaWebPlaybackSessionManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebPlaybackSessionManager.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -415,6 +415,13 @@
</span><span class="cx">     ensureModel(contextId).selectLegibleMediaOption(index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPlaybackSessionManager::handleControlledElementIDRequest(uint64_t contextId)
+{
+    auto element = ensureModel(contextId).mediaElement();
+    if (element)
+        m_page-&gt;send(Messages::WebPlaybackSessionManagerProxy::HandleControlledElementIDResponse(contextId, element-&gt;getIdAttribute()));
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // PLATFORM(IOS) || (PLATFORM(MAC) &amp;&amp; ENABLE(VIDEO_PRESENTATION_MODE))
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Tools/ChangeLog        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2016-09-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Refactor the heuristic for showing media controls to take all media sessions into account
+        https://bugs.webkit.org/show_bug.cgi?id=161503
+        &lt;rdar://problem/28033783&gt;
+
+        Reviewed by Darin Adler.
+
+        Adds new unit tests verifying the behavior of media playback controls when scrolling another video into view.
+        Please see the WebCore ChangeLog for more details about this change. Also refactors existing
+        VideoControlsManager tests by folding duplicated setup and testing logic into helper methods to make the unit
+        tests more readable.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm:
+        (-[MessageHandler initWithMessage:handler:]):
+        (-[MessageHandler userContentController:didReceiveScriptMessage:]):
+        (-[VideoControlsManagerTestWebView performAfterLoading:]):
+        (-[VideoControlsManagerTestWebView loadTestPageNamed:]):
+        (-[VideoControlsManagerTestWebView loadTestPageNamed:andExpectControlsManager:afterReceivingMessage:]):
+        (-[VideoControlsManagerTestWebView performAfterReceivingMessage:action:]):
+        (-[VideoControlsManagerTestWebView controlledElementID]):
+        (-[VideoControlsManagerTestWebView _handleControlledElementIDResponse:]):
+        (TestWebKitAPI::setUpWebViewForTestingVideoControlsManager):
+        (TestWebKitAPI::TEST):
+        (-[MediaPlaybackMessageHandler initWithWKWebView:finalMessageString:]): Deleted.
+        (-[MediaPlaybackMessageHandler userContentController:didReceiveScriptMessage:]): Deleted.
+        (-[OnLoadMessageHandler initWithWKWebView:handler:]): Deleted.
+        (-[OnLoadMessageHandler userContentController:didReceiveScriptMessage:]): Deleted.
+        (-[WKWebView performAfterLoading:]): Deleted.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html: Added.
+
</ins><span class="cx"> 2016-09-03  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         run-webkit-tests should detect w3c test resource files
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -64,6 +64,12 @@
</span><span class="cx">                 2E1DFDED1D42A51100714A00 /* large-videos-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */; };
</span><span class="cx">                 2E1DFDEF1D42A6F200714A00 /* large-videos-with-audio-autoplay.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */; };
</span><span class="cx">                 2E1DFDF11D42E1E400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */; };
</span><ins>+                2E691AEA1D78B53600129407 /* large-videos-paused-video-hides-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AE81D78B52B00129407 /* large-videos-paused-video-hides-controls.html */; };
+                2E691AEB1D78B53600129407 /* large-videos-playing-video-keeps-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AE91D78B52B00129407 /* large-videos-playing-video-keeps-controls.html */; };
+                2E691AED1D78B91000129407 /* large-videos-playing-muted-video-hides-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AEC1D78B90200129407 /* large-videos-playing-muted-video-hides-controls.html */; };
+                2E691AEF1D79DE8400129407 /* large-videos-autoplaying-click-to-pause.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AEE1D79DE6F00129407 /* large-videos-autoplaying-click-to-pause.html */; };
+                2E691AF11D79E51A00129407 /* large-videos-autoplaying-scroll-to-video.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AF01D79E51400129407 /* large-videos-autoplaying-scroll-to-video.html */; };
+                2E691AF31D79E75E00129407 /* large-video-playing-scroll-away.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AF21D79E75400129407 /* large-video-playing-scroll-away.html */; };
</ins><span class="cx">                 2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */; };
</span><span class="cx">                 2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CE16C4D81100BA2BB1 /* mainMac.mm */; };
</span><span class="cx">                 33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; };
</span><span class="lines">@@ -520,6 +526,12 @@
</span><span class="cx">                         dstPath = TestWebKitAPI.resources;
</span><span class="cx">                         dstSubfolderSpec = 7;
</span><span class="cx">                         files = (
</span><ins>+                                2E691AF31D79E75E00129407 /* large-video-playing-scroll-away.html in Copy Resources */,
+                                2E691AF11D79E51A00129407 /* large-videos-autoplaying-scroll-to-video.html in Copy Resources */,
+                                2E691AEF1D79DE8400129407 /* large-videos-autoplaying-click-to-pause.html in Copy Resources */,
+                                2E691AED1D78B91000129407 /* large-videos-playing-muted-video-hides-controls.html in Copy Resources */,
+                                2E691AEA1D78B53600129407 /* large-videos-paused-video-hides-controls.html in Copy Resources */,
+                                2E691AEB1D78B53600129407 /* large-videos-playing-video-keeps-controls.html in Copy Resources */,
</ins><span class="cx">                                 1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
</span><span class="cx">                                 379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */,
</span><span class="cx">                                 1C2B81871C8925A000A5529F /* Ahem.ttf in Copy Resources */,
</span><span class="lines">@@ -743,6 +755,12 @@
</span><span class="cx">                 2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-with-audio.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-with-audio-autoplay.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-video-seek-to-beginning-and-play-after-ending.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2E691AE81D78B52B00129407 /* large-videos-paused-video-hides-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-paused-video-hides-controls.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E691AE91D78B52B00129407 /* large-videos-playing-video-keeps-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-playing-video-keeps-controls.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E691AEC1D78B90200129407 /* large-videos-playing-muted-video-hides-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-playing-muted-video-hides-controls.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E691AEE1D79DE6F00129407 /* large-videos-autoplaying-click-to-pause.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-autoplaying-click-to-pause.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E691AF01D79E51400129407 /* large-videos-autoplaying-scroll-to-video.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-videos-autoplaying-scroll-to-video.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E691AF21D79E75400129407 /* large-video-playing-scroll-away.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;large-video-playing-scroll-away.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainIOS.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E7765CE16C4D81100BA2BB1 /* mainMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1400,6 +1418,12 @@
</span><span class="cx">                 A16F66B81C40E9E100BD4D24 /* Resources */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                2E691AF21D79E75400129407 /* large-video-playing-scroll-away.html */,
+                                2E691AF01D79E51400129407 /* large-videos-autoplaying-scroll-to-video.html */,
+                                2E691AEE1D79DE6F00129407 /* large-videos-autoplaying-click-to-pause.html */,
+                                2E691AEC1D78B90200129407 /* large-videos-playing-muted-video-hides-controls.html */,
+                                2E691AE81D78B52B00129407 /* large-videos-paused-video-hides-controls.html */,
+                                2E691AE91D78B52B00129407 /* large-videos-playing-video-keeps-controls.html */,
</ins><span class="cx">                                 5C9E593E1D3EB1DE00E3C62E /* ApplicationCache.db */,
</span><span class="cx">                                 5C9E593F1D3EB1DE00E3C62E /* ApplicationCache.db-shm */,
</span><span class="cx">                                 5C9E59401D3EB1DE00E3C62E /* ApplicationCache.db-wal */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2CocoaVideoControlsManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm (205411 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm        2016-09-03 23:34:00 UTC (rev 205411)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -37,66 +37,30 @@
</span><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED &amp;&amp; PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101200
</span><span class="cx"> 
</span><del>-static bool testedControlsManagerAfterPlaying;
-static bool receivedScriptMessage;
</del><ins>+@interface WKWebView (WKWebViewAdditions)
</ins><span class="cx"> 
</span><del>-@interface MediaPlaybackMessageHandler : NSObject &lt;WKScriptMessageHandler&gt; {
-    RetainPtr&lt;WKWebView&gt; _webView;
-}
</del><ins>+- (void)_interactWithMediaControlsForTesting;
</ins><span class="cx"> 
</span><del>-@property (nonatomic) BOOL expectedToHaveControlsManager;
-@property (nonatomic, retain) NSString *finalMessageString;
-
-- (instancetype)initWithWKWebView:(WKWebView*)webView finalMessageString:(NSString *)finalMessageString;
</del><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@implementation MediaPlaybackMessageHandler
-
-- (instancetype)initWithWKWebView:(WKWebView*)webView finalMessageString:(NSString *)finalMessageString
-{
-    if (!(self = [super init]))
-        return nil;
-
-    _webView = webView;
-    _finalMessageString = finalMessageString;
-
-    return self;
</del><ins>+@interface MessageHandler : NSObject &lt;WKScriptMessageHandler&gt; {
+    dispatch_block_t _handler;
+    NSString *_message;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
-{
-    receivedScriptMessage = true;
</del><ins>+- (instancetype)initWithMessage:(NSString *)message handler:(dispatch_block_t)handler;
</ins><span class="cx"> 
</span><del>-    NSString *bodyString = (NSString *)[message body];
-    if ([bodyString isEqualToString:self.finalMessageString]) {
-        BOOL hasControlsManager = [_webView _hasActiveVideoForControlsManager];
-        if (self.expectedToHaveControlsManager)
-            EXPECT_TRUE(hasControlsManager);
-        else
-            EXPECT_FALSE(hasControlsManager);
-        testedControlsManagerAfterPlaying = true;
-    }
-}
</del><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@interface OnLoadMessageHandler : NSObject &lt;WKScriptMessageHandler&gt; {
-    RetainPtr&lt;WKWebView&gt; _webView;
-}
</del><ins>+@implementation MessageHandler
</ins><span class="cx"> 
</span><del>-@property (nonatomic, strong) dispatch_block_t onloadHandler;
-
-- (instancetype)initWithWKWebView:(WKWebView*)webView handler:(dispatch_block_t)handler;
-@end
-
-@implementation OnLoadMessageHandler
-
-- (instancetype)initWithWKWebView:(WKWebView*)webView handler:(dispatch_block_t)handler
</del><ins>+- (instancetype)initWithMessage:(NSString *)message handler:(dispatch_block_t)handler
</ins><span class="cx"> {
</span><span class="cx">     if (!(self = [super init]))
</span><span class="cx">         return nil;
</span><span class="cx"> 
</span><del>-    _webView = webView;
-    _onloadHandler = handler;
</del><ins>+    _handler = [handler copy];
+    _message = message;
</ins><span class="cx"> 
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="lines">@@ -103,30 +67,28 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
</span><span class="cx"> {
</span><del>-    if (![(NSString *)[message body] isEqualToString:@&quot;loaded&quot;])
-        return;
-
-    if (_onloadHandler)
-        _onloadHandler();
-
-    _onloadHandler = nil;
</del><ins>+    if ([(NSString *)[message body] isEqualToString:_message] &amp;&amp; _handler)
+        _handler();
</ins><span class="cx"> }
</span><del>-@end
</del><span class="cx"> 
</span><del>-@interface WKWebView (WKWebViewAdditions)
-
-- (void)_interactWithMediaControlsForTesting;
-
</del><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@interface WKWebView (TestingAdditions)
</del><ins>+@interface VideoControlsManagerTestWebView : WKWebView
</ins><span class="cx"> 
</span><span class="cx"> - (void)mouseDownAtPoint:(NSPoint)point;
</span><span class="cx"> - (void)performAfterLoading:(dispatch_block_t)actions;
</span><ins>+- (void)loadTestPageNamed:(NSString *)pageName;
+- (void)loadTestPageNamed:(NSString *)pageName andExpectControlsManager:(BOOL)expectControlsManager afterReceivingMessage:(NSString *)message;
+- (void)performAfterReceivingMessage:(NSString *)message action:(dispatch_block_t)action;
</ins><span class="cx"> 
</span><ins>+@property (nonatomic, readonly) NSString *controlledElementID;
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@implementation WKWebView (TestingAdditions)
</del><ins>+@implementation VideoControlsManagerTestWebView {
+    bool _isDoneQueryingControlledElementID;
+    NSString *_controlledElementID;
+}
</ins><span class="cx"> 
</span><span class="cx"> - (void)mouseDownAtPoint:(NSPoint)point {
</span><span class="cx">     [self mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:NSMakePoint(point.x, point.y) modifierFlags:0 timestamp:GetCurrentEventTime() windowNumber:0 context:[NSGraphicsContext currentContext] eventNumber:0 clickCount:0 pressure:0]];
</span><span class="lines">@@ -133,78 +95,103 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)performAfterLoading:(dispatch_block_t)actions {
</span><del>-    OnLoadMessageHandler *handler = [[OnLoadMessageHandler alloc] initWithWKWebView:self handler:actions];
</del><ins>+    MessageHandler *handler = [[MessageHandler alloc] initWithMessage:@&quot;loaded&quot; handler:actions];
</ins><span class="cx">     NSString *onloadScript = @&quot;window.onload = function() { window.webkit.messageHandlers.onloadHandler.postMessage('loaded'); }&quot;;
</span><span class="cx">     WKUserScript *script = [[WKUserScript alloc] initWithSource:onloadScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
</span><del>-    [[[self configuration] userContentController] addUserScript:script];
-    [[[self configuration] userContentController] addScriptMessageHandler:handler name:@&quot;onloadHandler&quot;];
</del><ins>+
+    WKUserContentController* contentController = [[self configuration] userContentController];
+    [contentController addUserScript:script];
+    [contentController addScriptMessageHandler:handler name:@&quot;onloadHandler&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)loadTestPageNamed:(NSString *)pageName
+{
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:pageName withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
+    [self loadRequest:request];
+}
+
+- (void)loadTestPageNamed:(NSString *)pageName andExpectControlsManager:(BOOL)expectControlsManager afterReceivingMessage:(NSString *)message
+{
+    __block bool doneWaiting = false;
+    [self performAfterReceivingMessage:message action:^ {
+        BOOL hasVideoForControlsManager = [self _hasActiveVideoForControlsManager];
+        if (expectControlsManager)
+            EXPECT_TRUE(hasVideoForControlsManager);
+        else
+            EXPECT_FALSE(hasVideoForControlsManager);
+        doneWaiting = true;
+    }];
+
+    [self loadTestPageNamed:pageName];
+    TestWebKitAPI::Util::run(&amp;doneWaiting);
+}
+
+- (void)performAfterReceivingMessage:(NSString *)message action:(dispatch_block_t)action
+{
+    RetainPtr&lt;MessageHandler&gt; handler = adoptNS([[MessageHandler alloc] initWithMessage:message handler:action]);
+    [[[self configuration] userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
+}
+
+- (NSString *)controlledElementID
+{
+    _isDoneQueryingControlledElementID = false;
+    [self _requestControlledElementID];
+    TestWebKitAPI::Util::run(&amp;_isDoneQueryingControlledElementID);
+    return _controlledElementID;
+}
+
+- (void)_handleControlledElementIDResponse:(NSString *)identifier
+{
+    _controlledElementID = [identifier copy];
+    _isDoneQueryingControlledElementID = true;
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> namespace TestWebKitAPI {
</span><span class="cx"> 
</span><del>-TEST(VideoControlsManager, VideoControlsManagerSingleLargeVideo)
</del><ins>+RetainPtr&lt;VideoControlsManagerTestWebView*&gt; setUpWebViewForTestingVideoControlsManager(NSRect frame)
</ins><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
</span><span class="cx">     configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
</span><del>-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
-
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView&gt; webView = adoptNS([[VideoControlsManagerTestWebView alloc] initWithFrame:frame configuration:configuration.get()]);
</ins><span class="cx">     RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
</span><span class="cx">     [[window contentView] addSubview:webView.get()];
</span><span class="cx"> 
</span><ins>+    return webView;
+}
+
+TEST(VideoControlsManager, VideoControlsManagerSingleLargeVideo)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
+
</ins><span class="cx">     // A large video with audio should have a controls manager even if it is played via script like this video.
</span><span class="cx">     // So the expectation is YES.
</span><del>-    [handler setExpectedToHaveControlsManager:YES];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-video-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;large-video-with-audio&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerSingleSmallVideo)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-
</del><span class="cx">     // A small video will not have a controls manager unless it started playing because of a user gesture. Since this
</span><span class="cx">     // video is started with a script, the expectation is NO.
</span><del>-    [handler setExpectedToHaveControlsManager:NO];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;video-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;video-with-audio&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerMultipleVideosWithAudio)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><span class="cx">     __block BOOL didShowMediaControls;
</span><span class="cx">     __block bool isDoneLoading = false;
</span><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-    RetainPtr&lt;OnLoadMessageHandler&gt; onloadHandler = adoptNS([[OnLoadMessageHandler alloc] initWithWKWebView:webView.get() handler:^() {
</del><ins>+    [webView performAfterLoading:^ {
</ins><span class="cx">         didShowMediaControls = [webView _hasActiveVideoForControlsManager];
</span><span class="cx">         isDoneLoading = true;
</span><del>-    }]);
-    [[configuration userContentController] addScriptMessageHandler:onloadHandler.get() name:@&quot;onloadHandler&quot;];
</del><ins>+    }];
</ins><span class="cx"> 
</span><del>-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-videos-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
</del><ins>+    [webView loadTestPageNamed:@&quot;large-videos-with-audio&quot;];
</ins><span class="cx"> 
</span><span class="cx">     TestWebKitAPI::Util::run(&amp;isDoneLoading);
</span><span class="cx">     EXPECT_FALSE(didShowMediaControls);
</span><span class="lines">@@ -212,175 +199,157 @@
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerMultipleVideosWithAudioAndAutoplay)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><span class="cx">     __block BOOL didShowMediaControls;
</span><span class="cx">     __block bool isDoneLoading = false;
</span><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-    RetainPtr&lt;OnLoadMessageHandler&gt; onloadHandler = adoptNS([[OnLoadMessageHandler alloc] initWithWKWebView:webView.get() handler:^() {
</del><ins>+    [webView performAfterLoading:^ {
</ins><span class="cx">         didShowMediaControls = [webView _hasActiveVideoForControlsManager];
</span><span class="cx">         isDoneLoading = true;
</span><del>-    }]);
-    [[configuration userContentController] addScriptMessageHandler:onloadHandler.get() name:@&quot;onloadHandler&quot;];
</del><ins>+    }];
</ins><span class="cx"> 
</span><del>-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-videos-with-audio-autoplay&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
</del><ins>+    [webView loadTestPageNamed:@&quot;large-videos-with-audio-autoplay&quot;];
</ins><span class="cx"> 
</span><span class="cx">     TestWebKitAPI::Util::run(&amp;isDoneLoading);
</span><span class="cx">     EXPECT_TRUE(didShowMediaControls);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TEST(VideoControlsManager, VideoControlsManagerSingleSmallAutoplayingVideo)
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosScrollPausedVideoOutOfView)
</ins><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; playbackHandler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;paused&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:playbackHandler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 500, 500));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
</del><ins>+    [webView loadTestPageNamed:@&quot;large-videos-paused-video-hides-controls&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;paused&quot;];
+}
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;OnLoadMessageHandler&gt; onloadHandler = adoptNS([[OnLoadMessageHandler alloc] initWithWKWebView:webView.get() handler:^() {
-        [webView mouseDownAtPoint:NSMakePoint(50, 50)];
-    }]);
-    [[configuration userContentController] addScriptMessageHandler:onloadHandler.get() name:@&quot;onloadHandler&quot;];
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosScrollPlayingVideoWithSoundOutOfView)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 500, 500));
</ins><span class="cx"> 
</span><del>-    // A small video should have a controls manager after the first user gesture, which includes pausing the video. The expectation is YES.
-    [playbackHandler setExpectedToHaveControlsManager:YES];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;autoplaying-video-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
</del><ins>+    [webView loadTestPageNamed:@&quot;large-videos-playing-video-keeps-controls&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;playing&quot;];
+}
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosScrollPlayingMutedVideoOutOfView)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 500, 500));
+
+    [webView loadTestPageNamed:@&quot;large-videos-playing-muted-video-hides-controls&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-TEST(VideoControlsManager, VideoControlsManagerLargeAutoplayingVideoSeeksAfterEnding)
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosShowControlsForLastInteractedVideo)
</ins><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;ended&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 800, 600));
+    NSPoint clickPoint = NSMakePoint(400, 300);
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
</del><ins>+    [webView performAfterLoading:^ {
+        [webView mouseDownAtPoint:clickPoint];
+    }];
</ins><span class="cx"> 
</span><del>-    // Since the video has ended, the expectation is NO even if the page programmatically seeks to the beginning.
-    [handler setExpectedToHaveControlsManager:NO];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-video-seek-after-ending&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
</del><ins>+    __block bool firstVideoPaused = false;
+    __block bool secondVideoPaused = false;
+    [webView performAfterReceivingMessage:@&quot;paused&quot; action:^ {
+        NSString *controlledElementID = [webView controlledElementID];
+        if (firstVideoPaused) {
+            secondVideoPaused = true;
+            EXPECT_TRUE([controlledElementID isEqualToString:@&quot;second&quot;]);
+        } else {
+            [webView mouseDownAtPoint:clickPoint];
+            EXPECT_TRUE([controlledElementID isEqualToString:@&quot;first&quot;]);
+        }
+        firstVideoPaused = true;
+    }];
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;large-videos-autoplaying-click-to-pause&quot;];
+    TestWebKitAPI::Util::run(&amp;secondVideoPaused);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-TEST(VideoControlsManager, VideoControlsManagerLargeAutoplayingVideoSeeksAndPlaysAfterEnding)
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosSwitchControlledVideoWhenScrolling)
</ins><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;replaying&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 800, 600));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
</del><ins>+    __block bool scrolledSecondVideoIntoView = false;
+    [webView loadTestPageNamed:@&quot;large-videos-autoplaying-scroll-to-video&quot;];
+    [webView performAfterReceivingMessage:@&quot;scrolled&quot; action:^ {
+        scrolledSecondVideoIntoView = true;
+    }];
</ins><span class="cx"> 
</span><del>-    // Since the video is still playing, the expectation is YES even if the video has ended once.
-    [handler setExpectedToHaveControlsManager:YES];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-video-seek-to-beginning-and-play-after-ending&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
</del><ins>+    TestWebKitAPI::Util::run(&amp;scrolledSecondVideoIntoView);
+    EXPECT_TRUE([[webView controlledElementID] isEqualToString:@&quot;second&quot;]);
+}
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+TEST(VideoControlsManager, VideoControlsManagerMultipleVideosScrollOnlyLargeVideoOutOfView)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 500, 500));
+
+    [webView loadTestPageNamed:@&quot;large-video-playing-scroll-away&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;scrolled&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(VideoControlsManager, VideoControlsManagerSingleSmallAutoplayingVideo)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
+
+    [webView performAfterLoading:^ {
+        [webView mouseDownAtPoint:NSMakePoint(50, 50)];
+    }];
+
+    [webView loadTestPageNamed:@&quot;autoplaying-video-with-audio&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;paused&quot;];
+}
+
+TEST(VideoControlsManager, VideoControlsManagerLargeAutoplayingVideoSeeksAfterEnding)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
+
+    // Since the video has ended, the expectation is NO even if the page programmatically seeks to the beginning.
+    [webView loadTestPageNamed:@&quot;large-video-seek-after-ending&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;ended&quot;];
+}
+
+TEST(VideoControlsManager, VideoControlsManagerLargeAutoplayingVideoSeeksAndPlaysAfterEnding)
+{
+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
+
+    // Since the video is still playing, the expectation is YES even if the video has ended once.
+    [webView loadTestPageNamed:@&quot;large-video-seek-to-beginning-and-play-after-ending&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;replaying&quot;];
+}
+
</ins><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerLargeAutoplayingVideoAfterSeekingToEnd)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;ended&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-
-    RetainPtr&lt;OnLoadMessageHandler&gt; onloadHandler = adoptNS([[OnLoadMessageHandler alloc] initWithWKWebView:webView.get() handler:^() {
</del><ins>+    [webView performAfterLoading:^ {
</ins><span class="cx">         [webView mouseDownAtPoint:NSMakePoint(50, 50)];
</span><del>-    }]);
-    [[configuration userContentController] addScriptMessageHandler:onloadHandler.get() name:@&quot;onloadHandler&quot;];
</del><ins>+    }];
</ins><span class="cx"> 
</span><span class="cx">     // We expect there to be media controls, since this is a user gestured seek to the end.
</span><span class="cx">     // This is akin to seeking to the end by scrubbing in the controls.
</span><del>-    [handler setExpectedToHaveControlsManager:YES];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-video-hides-controls-after-seek-to-end&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;large-video-hides-controls-after-seek-to-end&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;ended&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerSingleLargeVideoWithoutAudio)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-
</del><span class="cx">     // A large video with no audio will not have a controls manager unless it started playing because of a user gesture. Since this
</span><span class="cx">     // video is started with a script, the expectation is NO.
</span><del>-    [handler setExpectedToHaveControlsManager:NO];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;large-video-without-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;large-video-without-audio&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerAudioElementStartedWithScript)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-
</del><span class="cx">     // An audio element MUST be started with a user gesture in order to have a controls manager, so the expectation is NO.
</span><del>-    [handler setExpectedToHaveControlsManager:NO];
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;audio-only&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;audio-only&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerTearsDownMediaControlsOnDealloc)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-
</del><span class="cx">     NSURL *urlOfVideo = [[NSBundle mainBundle] URLForResource:@&quot;video-with-audio&quot; withExtension:@&quot;mp4&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;];
</span><span class="cx">     [webView loadFileURL:urlOfVideo allowingReadAccessToURL:[urlOfVideo URLByDeletingLastPathComponent]];
</span><span class="cx"> 
</span><span class="cx">     __block bool finishedTest = false;
</span><del>-    [webView performAfterLoading:^()
-    {
</del><ins>+    [webView performAfterLoading:^ {
</ins><span class="cx">         // Verify that we tear down the media controls properly, such that we don't crash when the web view is released.
</span><span class="cx">         if ([webView respondsToSelector:@selector(_interactWithMediaControlsForTesting)])
</span><span class="cx">             [webView _interactWithMediaControlsForTesting];
</span><span class="lines">@@ -394,16 +363,10 @@
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerSmallVideoInMediaDocument)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
-    
-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
-    
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 100, 100));
+
</ins><span class="cx">     __block bool finishedLoad = false;
</span><del>-    [webView performAfterLoading:^()
-    {
</del><ins>+    [webView performAfterLoading:^ {
</ins><span class="cx">         finishedLoad = true;
</span><span class="cx">     }];
</span><span class="cx">     
</span><span class="lines">@@ -418,40 +381,16 @@
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerLongSkinnyVideoInWideMainFrame)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 1600, 800) configuration:configuration.get()]);
-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 1600, 800));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
-    [handler setExpectedToHaveControlsManager:NO];
-
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;skinny-autoplaying-video-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;skinny-autoplaying-video-with-audio&quot; andExpectControlsManager:NO afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(VideoControlsManager, VideoControlsManagerFullSizeVideoInWideMainFrame)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebViewConfiguration&gt; configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 1600, 800) configuration:configuration.get()]);
-    RetainPtr&lt;NSWindow&gt; window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
-    [[window contentView] addSubview:webView.get()];
</del><ins>+    RetainPtr&lt;VideoControlsManagerTestWebView*&gt; webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 1600, 800));
</ins><span class="cx"> 
</span><del>-    RetainPtr&lt;MediaPlaybackMessageHandler&gt; handler = adoptNS([[MediaPlaybackMessageHandler alloc] initWithWKWebView:webView.get() finalMessageString:@&quot;playing&quot;]);
-    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@&quot;playingHandler&quot;];
-    [handler setExpectedToHaveControlsManager:YES];
-
-    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;full-size-autoplaying-video-with-audio&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
-    [webView loadRequest:request];
-
-    TestWebKitAPI::Util::run(&amp;testedControlsManagerAfterPlaying);
-    TestWebKitAPI::Util::run(&amp;receivedScriptMessage);
</del><ins>+    [webView loadTestPageNamed:@&quot;full-size-autoplaying-video-with-audio&quot; andExpectControlsManager:YES afterReceivingMessage:@&quot;playing&quot;];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace TestWebKitAPI
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideoplayingscrollawayhtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+    &lt;head&gt;
+        &lt;style&gt;
+            video {
+                width: 480px;
+                height: 320px;
+            }
+            div {
+                margin-top: 5000px;
+            }
+        &lt;/style&gt;
+        &lt;script&gt;
+            function handleLoaded() {
+                document.querySelector(&quot;div&quot;).scrollIntoView();
+                setTimeout(function() {
+                    window.webkit.messageHandlers.playingHandler.postMessage(&quot;scrolled&quot;);
+                }, 0);
+            }
+        &lt;/script&gt;
+    &lt;/head&gt;
+    &lt;body onload=handleLoaded()&gt;
+        &lt;video autoplay loop id=&quot;first&quot; src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+        &lt;br&gt;
+        &lt;div&gt;hello world!&lt;/div&gt;
+    &lt;/body&gt;
+&lt;html&gt;
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosautoplayingclicktopausehtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+    &lt;head&gt;
+        &lt;style&gt;
+            video {
+                width: 480px;
+                height: 320px;
+            }
+        &lt;/style&gt;
+        &lt;script&gt;
+            var isFirstClick = true;
+            function handleMouseDown() {
+                document.querySelector(isFirstClick ? &quot;#first&quot; : &quot;#second&quot;).pause();
+                isFirstClick = false;
+            }
+
+            function handleFirstPause() {
+                setTimeout(function() {
+                    try {
+                        window.webkit.messageHandlers.playingHandler.postMessage(&quot;paused&quot;);
+                    } catch(e) { }
+                }, 0);
+            }
+
+            function handleSecondPause() {
+                setTimeout(function() {
+                    try {
+                        window.webkit.messageHandlers.playingHandler.postMessage(&quot;paused&quot;);
+                    } catch(e) { }
+                }, 0);
+            }
+        &lt;/script&gt;
+    &lt;/head&gt;
+    &lt;body onmousedown=handleMouseDown()&gt;
+        &lt;video autoplay loop id=&quot;first&quot; src=&quot;large-video-with-audio.mp4&quot; onpause=handleFirstPause()&gt;&lt;/video&gt;
+        &lt;video autoplay loop id=&quot;second&quot; src=&quot;large-video-with-audio.mp4&quot; onpause=handleSecondPause()&gt;&lt;/video&gt;
+    &lt;/body&gt;
+&lt;html&gt;
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosautoplayingscrolltovideohtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+    &lt;head&gt;
+        &lt;style&gt;
+            video {
+                width: 480px;
+                height: 320px;
+            }
+            #second {
+                margin-top: 5000px;
+            }
+        &lt;/style&gt;
+        &lt;script&gt;
+            function handleLoaded() {
+                document.querySelector(&quot;#second&quot;).scrollIntoView();
+                setTimeout(function() {
+                    window.webkit.messageHandlers.playingHandler.postMessage(&quot;scrolled&quot;);
+                }, 0);
+            }
+        &lt;/script&gt;
+    &lt;/head&gt;
+    &lt;body onload=handleLoaded()&gt;
+        &lt;video autoplay loop id=&quot;first&quot; src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+        &lt;br&gt;
+        &lt;video autoplay loop id=&quot;second&quot; src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+    &lt;/body&gt;
+&lt;html&gt;
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideospausedvideohidescontrolshtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;style&gt;
+    video {
+        width: 480px;
+        height: 320px;
+    }
+    #bar {
+        margin-top: 5000px;
+    }
+&lt;/style&gt;
+&lt;script&gt;
+    function handleLoaded() {
+        document.querySelector(&quot;#bar&quot;).scrollIntoView();
+        document.querySelector(&quot;#foo&quot;).pause();
+    }
+    function handlePaused() {
+        setTimeout(function() {
+            try {
+                window.webkit.messageHandlers.playingHandler.postMessage(&quot;paused&quot;);
+            } catch(e) { }
+        }, 0);
+    }
+&lt;/script&gt;
+&lt;body onload=handleLoaded()&gt;
+    &lt;video autoplay loop id=&quot;foo&quot; onpause=handlePaused()&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+    &lt;br&gt;
+    &lt;video id=&quot;bar&quot;&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosplayingmutedvideohidescontrolshtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;style&gt;
+    video {
+        width: 480px;
+        height: 320px;
+    }
+    #bar {
+        margin-top: 5000px;
+    }
+&lt;/style&gt;
+&lt;script&gt;
+    function handleLoaded() {
+        document.querySelector(&quot;#foo&quot;).muted = true;
+        document.querySelector(&quot;#bar&quot;).scrollIntoView();
+        setTimeout(function() {
+            try {
+                window.webkit.messageHandlers.playingHandler.postMessage(&quot;playing&quot;);
+            } catch(e) { }
+        }, 0);
+    }
+&lt;/script&gt;
+&lt;body onload=handleLoaded()&gt;
+    &lt;video autoplay loop id=&quot;foo&quot;&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+    &lt;br&gt;
+    &lt;video id=&quot;bar&quot;&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoalargevideosplayingvideokeepscontrolshtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html (0 => 205412)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html        2016-09-04 00:24:14 UTC (rev 205412)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;style&gt;
+    video {
+        width: 480px;
+        height: 320px;
+    }
+    #bar {
+        margin-top: 5000px;
+    }
+&lt;/style&gt;
+&lt;script&gt;
+    function handleLoaded() {
+        document.querySelector(&quot;#bar&quot;).scrollIntoView();
+        setTimeout(function() {
+            try {
+                window.webkit.messageHandlers.playingHandler.postMessage(&quot;playing&quot;);
+            } catch(e) { }
+        }, 0);
+    }
+&lt;/script&gt;
+&lt;body onload=handleLoaded()&gt;
+    &lt;video autoplay loop id=&quot;foo&quot;&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+    &lt;br&gt;
+    &lt;video id=&quot;bar&quot;&gt;&lt;source src=&quot;large-video-with-audio.mp4&quot;&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>