<!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>[164661] trunk/Source/WebCore</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/164661">164661</a></dd>
<dt>Author</dt> <dd>eric.carlson@apple.com</dd>
<dt>Date</dt> <dd>2014-02-25 12:29:58 -0800 (Tue, 25 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Show status image when playing video to external device
https://bugs.webkit.org/show_bug.cgi?id=129277

Reviewed by Jer Noble.

* Modules/mediacontrols/mediaControlsApple.js:
(Controller.prototype.handleEvent): Restructure the code so it is possible to handle events
    that target the video element which aren't in the HandledVideoEvents array.

* Modules/mediacontrols/mediaControlsiOS.js:
(ControllerIOS.prototype.currentPlaybackTargetIsWireless): webkitCurrentPlaybackTargetIsWireless
    is an attribute, not a function.
(ControllerIOS.prototype.updateWirelessPlaybackStatus): Fix style.
(ControllerIOS.prototype.updateWirelessTargetAvailable): Ditto.
(ControllerIOS.prototype.updateProgress): Ditto.
(ControllerIOS.prototype.handleWrapperTouchStart): Show the controls if the wireless status
    display is touched.
(ControllerIOS.prototype.handleFullscreenButtonClicked): Fix style
(ControllerIOS.prototype.handleWirelessPlaybackChange): Ditto.
(ControllerIOS.prototype.handleWirelessTargetAvailableChange):
(ControllerIOS.prototype.handleWirelessPickerButtonClicked): Ditto. Stop even propagation.

Move &quot;playback target&quot; logic into HTMLMediaSession.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::~HTMLMediaElement): Call media session.
(WebCore::HTMLMediaElement::loadResource): Tell media session to apply media player
    restrictions now that it has a url.
(WebCore::HTMLMediaElement::invalidateCachedTime): Only log when cached time is not
    already invalie.
(WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker): Call media session.
(WebCore::HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless): Ditto.
(WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged): Ditto.
(WebCore::HTMLMediaElement::addEventListener): Ditto.
(WebCore::HTMLMediaElement::removeEventListen): Ditto.
(WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent): Ditto.
(WebCore::HTMLMediaElement::createMediaPlayer): Ditto.

* html/HTMLMediaSession.cpp:
(WebCore::restrictionName): Log new WirelessVideoPlaybackDisabled restriction.
(WebCore::HTMLMediaSession::showingPlaybackTargetPickerPermitted): Return false if there
    is no page, or if wireless playback is disabled.
(WebCore::HTMLMediaSession::currentPlaybackTargetIsWireless): New, logic from HTMLMediaElement.
(WebCore::HTMLMediaSession::showPlaybackTargetPicker): Ditto.
(WebCore::HTMLMediaSession::hasWirelessPlaybackTargets): Ditto.
(WebCore::HTMLMediaSession::wirelessVideoPlaybackDisabled): Ditto.
(WebCore::HTMLMediaSession::setWirelessVideoPlaybackDisabled): Ditto.
(WebCore::HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners): Ditto.
(WebCore::HTMLMediaSession::applyMediaPlayerRestrictions): New, apply media player specific
    restriction.
* html/HTMLMediaSession.h:

Move &quot;playback target&quot; logic into HTMLMediaSession.
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::parseAttribute): Call media session.
(WebCore::HTMLVideoElement::webkitWirelessVideoPlaybackDisabled): Call media session.

* platform/audio/MediaSessionManager.h:
(WebCore::MediaSessionManager::showPlaybackTargetPicker): New method, does nothing in base class.

* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(WebCore::MediaSessionManageriOS::showPlaybackTargetPicker): Add non-functional stub.

Implement wireless playback control and status API.
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::dispatchNotification): Dispatch TargetIsWirelessChanged.
(WebCore::MediaPlayerPrivateAVFoundation::playbackTargetIsWirelessChanged): Pass through to
    media element.
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:

* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC): Initialize
    m_allowsWirelessVideoPlayback.
(WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad): Remove &quot;externalPlaybackActive&quot; observer.
(WebCore::MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer): Fix broken logging.
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): Add &quot;externalPlaybackActive&quot; observer,
    set initial wireless playback.
(WebCore::MediaPlayerPrivateAVFoundationObjC::createPixelBuffer):  Fix broken logging.
(WebCore::MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless): New.
(WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled): New.
(WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled): New.
(WebCore::MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange): New.
(-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]): Deal with
    externalPlaybackActive.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediacontrolsmediaControlsApplejs">trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmediacontrolsmediaControlsiOSjs">trunk/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaSessioncpp">trunk/Source/WebCore/html/HTMLMediaSession.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaSessionh">trunk/Source/WebCore/html/HTMLMediaSession.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLVideoElementcpp">trunk/Source/WebCore/html/HTMLVideoElement.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioMediaSessionManagerh">trunk/Source/WebCore/platform/audio/MediaSessionManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioiosMediaSessionManagerIOSh">trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioiosMediaSessionManagerIOSmm">trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationMediaPlayerPrivateAVFoundationcpp">trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationMediaPlayerPrivateAVFoundationh">trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/ChangeLog        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -1,3 +1,92 @@
</span><ins>+2014-02-25  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [iOS] Show status image when playing video to external device
+        https://bugs.webkit.org/show_bug.cgi?id=129277
+
+        Reviewed by Jer Noble.
+
+        * Modules/mediacontrols/mediaControlsApple.js:
+        (Controller.prototype.handleEvent): Restructure the code so it is possible to handle events
+            that target the video element which aren't in the HandledVideoEvents array.
+
+        * Modules/mediacontrols/mediaControlsiOS.js:
+        (ControllerIOS.prototype.currentPlaybackTargetIsWireless): webkitCurrentPlaybackTargetIsWireless
+            is an attribute, not a function.
+        (ControllerIOS.prototype.updateWirelessPlaybackStatus): Fix style.
+        (ControllerIOS.prototype.updateWirelessTargetAvailable): Ditto.
+        (ControllerIOS.prototype.updateProgress): Ditto.
+        (ControllerIOS.prototype.handleWrapperTouchStart): Show the controls if the wireless status
+            display is touched.
+        (ControllerIOS.prototype.handleFullscreenButtonClicked): Fix style
+        (ControllerIOS.prototype.handleWirelessPlaybackChange): Ditto.
+        (ControllerIOS.prototype.handleWirelessTargetAvailableChange):
+        (ControllerIOS.prototype.handleWirelessPickerButtonClicked): Ditto. Stop even propagation.
+
+        Move &quot;playback target&quot; logic into HTMLMediaSession.
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::~HTMLMediaElement): Call media session.
+        (WebCore::HTMLMediaElement::loadResource): Tell media session to apply media player
+            restrictions now that it has a url.
+        (WebCore::HTMLMediaElement::invalidateCachedTime): Only log when cached time is not 
+            already invalie.
+        (WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker): Call media session.
+        (WebCore::HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless): Ditto.
+        (WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged): Ditto.
+        (WebCore::HTMLMediaElement::addEventListener): Ditto.
+        (WebCore::HTMLMediaElement::removeEventListen): Ditto.
+        (WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent): Ditto.
+        (WebCore::HTMLMediaElement::createMediaPlayer): Ditto.
+
+        * html/HTMLMediaSession.cpp:
+        (WebCore::restrictionName): Log new WirelessVideoPlaybackDisabled restriction.
+        (WebCore::HTMLMediaSession::showingPlaybackTargetPickerPermitted): Return false if there
+            is no page, or if wireless playback is disabled.
+        (WebCore::HTMLMediaSession::currentPlaybackTargetIsWireless): New, logic from HTMLMediaElement.
+        (WebCore::HTMLMediaSession::showPlaybackTargetPicker): Ditto.
+        (WebCore::HTMLMediaSession::hasWirelessPlaybackTargets): Ditto.
+        (WebCore::HTMLMediaSession::wirelessVideoPlaybackDisabled): Ditto.
+        (WebCore::HTMLMediaSession::setWirelessVideoPlaybackDisabled): Ditto.
+        (WebCore::HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners): Ditto.
+        (WebCore::HTMLMediaSession::applyMediaPlayerRestrictions): New, apply media player specific
+            restriction.
+        * html/HTMLMediaSession.h:
+
+        Move &quot;playback target&quot; logic into HTMLMediaSession.
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::parseAttribute): Call media session.
+        (WebCore::HTMLVideoElement::webkitWirelessVideoPlaybackDisabled): Call media session.
+
+        * platform/audio/MediaSessionManager.h:
+        (WebCore::MediaSessionManager::showPlaybackTargetPicker): New method, does nothing in base class.
+
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (WebCore::MediaSessionManageriOS::showPlaybackTargetPicker): Add non-functional stub.
+
+        Implement wireless playback control and status API.
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::dispatchNotification): Dispatch TargetIsWirelessChanged.
+        (WebCore::MediaPlayerPrivateAVFoundation::playbackTargetIsWirelessChanged): Pass through to
+            media element.
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC): Initialize
+            m_allowsWirelessVideoPlayback.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad): Remove &quot;externalPlaybackActive&quot; observer.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer): Fix broken logging.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): Add &quot;externalPlaybackActive&quot; observer,
+            set initial wireless playback.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createPixelBuffer):  Fix broken logging.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless): New.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled): New.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled): New.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange): New.
+        (-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]): Deal with 
+            externalPlaybackActive.
+
</ins><span class="cx"> 2014-02-24  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Gracefully recover from missing 'naturalSize' parameter for media
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediacontrolsmediaControlsApplejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -225,15 +225,15 @@
</span><span class="cx">                 var handler = this[handlerName];
</span><span class="cx">                 if (handler &amp;&amp; handler instanceof Function)
</span><span class="cx">                     handler.call(this, event);
</span><del>-            } else {
-                if (!(this.listeners[event.type] instanceof Array))
-                    return;
</del><ins>+            }
</ins><span class="cx"> 
</span><del>-                this.listeners[event.type].forEach(function(entry) {
-                    if (entry.element === event.currentTarget &amp;&amp; entry.handler instanceof Function)
-                        entry.handler.call(this, event);
-                }, this);
-            }
</del><ins>+            if (!(this.listeners[event.type] instanceof Array))
+                return;
+
+            this.listeners[event.type].forEach(function(entry) {
+                if (entry.element === event.currentTarget &amp;&amp; entry.handler instanceof Function)
+                    entry.handler.call(this, event);
+            }, this);
</ins><span class="cx">         } catch(e) {
</span><span class="cx">             if (window.console)
</span><span class="cx">                 console.error(e);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediacontrolsmediaControlsiOSjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -104,13 +104,11 @@
</span><span class="cx">         return this.shouldHaveStartPlaybackButton() || Controller.prototype.shouldHaveAnyUI.call(this) || this.currentPlaybackTargetIsWireless();
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    currentPlaybackTargetIsWireless: function()
-    {
-        return ControllerIOS.gSimulateWirelessPlaybackTarget || ((typeof this.video.webkitCurrentPlaybackTargetIsWireless === &quot;function&quot;) &amp;&amp; this.video.webkitCurrentPlaybackTargetIsWireless());
</del><ins>+    currentPlaybackTargetIsWireless: function() {
+        return ControllerIOS.gSimulateWirelessPlaybackTarget || (('webkitCurrentPlaybackTargetIsWireless' in this.video) &amp;&amp; this.video.webkitCurrentPlaybackTargetIsWireless);
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    updateWirelessPlaybackStatus: function()
-    {
</del><ins>+    updateWirelessPlaybackStatus: function() {
</ins><span class="cx">         if (this.currentPlaybackTargetIsWireless()) {
</span><span class="cx">             var backgroundImageSVG = &quot;url('&quot; + ControllerIOS.gWirelessImage + &quot;')&quot;;
</span><span class="cx"> 
</span><span class="lines">@@ -133,8 +131,7 @@
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    updateWirelessTargetAvailable: function()
-    {
</del><ins>+    updateWirelessTargetAvailable: function() {
</ins><span class="cx">         if (ControllerIOS.gSimulateWirelessPlaybackTarget || this.hasWirelessPlaybackTargets)
</span><span class="cx">             this.controls.wirelessTargetPicker.classList.remove(this.ClassNames.hidden);
</span><span class="cx">         else
</span><span class="lines">@@ -227,8 +224,7 @@
</span><span class="cx">         return 'rgba(0, 0, 0, 0.5)';
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    updateProgress: function()
-    {
</del><ins>+    updateProgress: function() {
</ins><span class="cx">         Controller.prototype.updateProgress.call(this);
</span><span class="cx"> 
</span><span class="cx">         var width = this.controls.timeline.offsetWidth;
</span><span class="lines">@@ -280,7 +276,7 @@
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     handleWrapperTouchStart: function(event) {
</span><del>-        if (event.target != this.base)
</del><ins>+        if (event.target != this.base &amp;&amp; event.target != this.controls.wirelessPlaybackStatus)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         if (this.controlsAreHidden()) {
</span><span class="lines">@@ -309,9 +305,7 @@
</span><span class="cx">         return this.video.webkitDisplayingFullscreen;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    handleFullscreenButtonClicked: function(event)
-    {
-        console.trace();
</del><ins>+    handleFullscreenButtonClicked: function(event) {
</ins><span class="cx">         if (this.isFullScreen())
</span><span class="cx">             this.video.webkitExitFullscreen();
</span><span class="cx">         else
</span><span class="lines">@@ -358,20 +352,18 @@
</span><span class="cx">         this.updateControls();
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    handleWirelessPlaybackChange: function(event)
-    {
-        updateWirelessPlaybackStatus();
</del><ins>+    handleWirelessPlaybackChange: function(event) {
+        this.updateWirelessPlaybackStatus();
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    handleWirelessTargetAvailableChange: function(event)
-    {
</del><ins>+    handleWirelessTargetAvailableChange: function(event) {
</ins><span class="cx">         this.hasWirelessPlaybackTargets = event.availability == &quot;available&quot;;
</span><del>-        updateWirelessTargetAvailable();
</del><ins>+        this.updateWirelessTargetAvailable();
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    handleWirelessPickerButtonClicked: function(event)
-    {
-        video.webkitShowPlaybackTargetPicker();
</del><ins>+    handleWirelessPickerButtonClicked: function(event) {
+        this.video.webkitShowPlaybackTargetPicker();
+        event.stopPropagation();
</ins><span class="cx">     },
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -417,8 +417,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><del>-    if (m_player &amp;&amp; !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent))
-        m_player-&gt;setHasPlaybackTargetAvailabilityListeners(false);
</del><ins>+    if (!hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent))
+        m_mediaSession-&gt;setHasPlaybackTargetAvailabilityListeners(*this, false);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     if (m_mediaController) {
</span><span class="lines">@@ -1246,6 +1246,8 @@
</span><span class="cx">     if (!m_player-&gt;load(url, contentType, keySystem))
</span><span class="cx">         mediaLoadingFailed(MediaPlayer::FormatError);
</span><span class="cx"> 
</span><ins>+    m_mediaSession-&gt;applyMediaPlayerRestrictions(*this);
+
</ins><span class="cx">     // If there is no poster to display, allow the media engine to render video frames as soon as
</span><span class="cx">     // they are available.
</span><span class="cx">     updateDisplayState();
</span><span class="lines">@@ -2452,7 +2454,10 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::invalidateCachedTime() const
</span><span class="cx"> {
</span><del>-    LOG(Media, &quot;HTMLMediaElement::invalidateCachedTime&quot;);
</del><ins>+#if !LOG_DISABLED
+    if (m_cachedTime != MediaPlayer::invalidTime())
+        LOG(Media, &quot;HTMLMediaElement::invalidateCachedTime&quot;);
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // Don't try to cache movie time when playback first starts as the time reported by the engine
</span><span class="cx">     // sometimes fluctuates for a short amount of time, so the cached time will be off if we take it
</span><span class="lines">@@ -4775,28 +4780,17 @@
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx"> void HTMLMediaElement::webkitShowPlaybackTargetPicker()
</span><span class="cx"> {
</span><del>-    if (!document().page())
-        return;
-
-    if (!m_player)
-        return;
-
-    if (!m_mediaSession-&gt;showingPlaybackTargetPickerPermitted(*this))
-        return;
-
-    if (document().settings()-&gt;mediaPlaybackAllowsAirPlay())
-        return;
-
-    m_player-&gt;showPlaybackTargetPicker();
</del><ins>+    m_mediaSession-&gt;showPlaybackTargetPicker(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless() const
</span><span class="cx"> {
</span><del>-    return m_player &amp;&amp; m_player-&gt;isCurrentPlaybackTargetWireless();
</del><ins>+    return m_mediaSession-&gt;currentPlaybackTargetIsWireless(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*)
</span><span class="cx"> {
</span><ins>+    LOG(Media, &quot;HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged - webkitCurrentPlaybackTargetIsWireless = %s&quot;, boolString(webkitCurrentPlaybackTargetIsWireless()));
</ins><span class="cx">     scheduleEvent(eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -4813,9 +4807,12 @@
</span><span class="cx">     bool isFirstAvailabilityChangedListener = !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent);
</span><span class="cx">     if (!Node::addEventListener(eventType, listener, useCapture))
</span><span class="cx">         return false;
</span><del>-    if (m_player &amp;&amp; isFirstAvailabilityChangedListener)
-        m_player-&gt;setHasPlaybackTargetAvailabilityListeners(true);
</del><span class="cx"> 
</span><ins>+    if (isFirstAvailabilityChangedListener)
+        m_mediaSession-&gt;setHasPlaybackTargetAvailabilityListeners(*this, true);
+
+    LOG(Media, &quot;HTMLMediaElement::addEventListener('webkitplaybacktargetavailabilitychanged')&quot;);
+    
</ins><span class="cx">     enqueuePlaybackTargetAvailabilityChangedEvent(); // Ensure the event listener gets at least one event.
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -4829,17 +4826,16 @@
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     bool didRemoveLastAvailabilityChangedListener = !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent);
</span><del>-    if (m_player &amp;&amp; didRemoveLastAvailabilityChangedListener)
-        m_player-&gt;setHasPlaybackTargetAvailabilityListeners(false);
</del><ins>+    if (didRemoveLastAvailabilityChangedListener)
+        m_mediaSession-&gt;setHasPlaybackTargetAvailabilityListeners(*this, false);
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent()
</span><span class="cx"> {
</span><del>-    if (!m_player)
-        return;
-    bool isAirPlayAvailable = m_player-&gt;hasWirelessPlaybackTargets();
-    RefPtr&lt;Event&gt; event = WebKitPlaybackTargetAvailabilityEvent::create(eventNames().webkitplaybacktargetavailabilitychangedEvent, isAirPlayAvailable);
</del><ins>+    LOG(Media, &quot;HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent&quot;);
+    RefPtr&lt;Event&gt; event = WebKitPlaybackTargetAvailabilityEvent::create(eventNames().webkitplaybacktargetavailabilitychangedEvent, m_mediaSession-&gt;hasWirelessPlaybackTargets(*this));
</ins><span class="cx">     event-&gt;setTarget(this);
</span><span class="cx">     m_asyncEventQueue.enqueueEvent(event.release());
</span><span class="cx"> }
</span><span class="lines">@@ -5344,7 +5340,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx">     if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent)) {
</span><del>-        m_player-&gt;setHasPlaybackTargetAvailabilityListeners(true);
</del><ins>+        m_mediaSession-&gt;setHasPlaybackTargetAvailabilityListeners(*this, true);
</ins><span class="cx">         enqueuePlaybackTargetAvailabilityChangedEvent(); // Ensure the event listener gets at least one event.
</span><span class="cx">     }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaSession.cpp (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaSession.cpp        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/html/HTMLMediaSession.cpp        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -30,8 +30,10 @@
</span><span class="cx"> #include &quot;HTMLMediaSession.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;HTMLMediaElement.h&quot;
</span><ins>+#include &quot;HTMLNames.h&quot;
</ins><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;MediaSessionManager.h&quot;
</span><ins>+#include &quot;NotImplemented.h&quot;
</ins><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;ScriptController.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -55,6 +57,7 @@
</span><span class="cx">     CASE(RequirePageConsentToResumeMedia);
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx">     CASE(RequireUserGestureToShowPlaybackTargetPicker);
</span><ins>+    CASE(WirelessVideoPlaybackDisabled);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -155,17 +158,146 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><del>-bool HTMLMediaSession::showingPlaybackTargetPickerPermitted(const HTMLMediaElement&amp;) const
</del><ins>+bool HTMLMediaSession::showingPlaybackTargetPickerPermitted(const HTMLMediaElement&amp; element) const
</ins><span class="cx"> {
</span><span class="cx">     if (m_restrictions &amp; RequireUserGestureToShowPlaybackTargetPicker &amp;&amp; !ScriptController::processingUserGesture()) {
</span><del>-        LOG(Media, &quot;HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning FALSE&quot;);
</del><ins>+        LOG(Media, &quot;HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning FALSE because of permissions&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return true;
</del><ins>+    if (!element.document().page()) {
+        LOG(Media, &quot;HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning FALSE because page is NULL&quot;);
+        return false;
+    }
+
+    return !wirelessVideoPlaybackDisabled(element);
</ins><span class="cx"> }
</span><ins>+
+bool HTMLMediaSession::currentPlaybackTargetIsWireless(const HTMLMediaElement&amp; element) const
+{
+    MediaPlayer* player = element.player();
+    if (!player) {
+        LOG(Media, &quot;HTMLMediaSession::currentPlaybackTargetIsWireless - returning FALSE because player is NULL&quot;);
+        return false;
+    }
+
+    bool isWireless = player-&gt;isCurrentPlaybackTargetWireless();
+    LOG(Media, &quot;HTMLMediaSession::currentPlaybackTargetIsWireless - returning %s&quot;, isWireless ? &quot;TRUE&quot; : &quot;FALSE&quot;);
+
+    return isWireless;
+}
+
+void HTMLMediaSession::showPlaybackTargetPicker(const HTMLMediaElement&amp; element)
+{
+    LOG(Media, &quot;HTMLMediaSession::showPlaybackTargetPicker&quot;);
+
+    if (!showingPlaybackTargetPickerPermitted(element))
+        return;
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    if (element.shouldUseVideoPluginProxy()) {
+        MediaPlayer* player = element.player();
+        if (!player)
+            return;
+
+        player-&gt;showPlaybackTargetPicker();
+        return;
+    }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    MediaSessionManager::sharedManager().showPlaybackTargetPicker();
+}
+
+bool HTMLMediaSession::hasWirelessPlaybackTargets(const HTMLMediaElement&amp; element) const
+{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    if (element.shouldUseVideoPluginProxy()) {
+        MediaPlayer* player = element.player();
+        if (!player)
+            return false;
+
+        return player-&gt;hasWirelessPlaybackTargets();
+    }
+#else
+    UNUSED_PARAM(element);
+#endif
+
+    // FIXME: this only lets us know if the current element is playing to an external target, we want to
+    // know if there are *any* external targets.
+    bool hasTargets = currentPlaybackTargetIsWireless(element);
+    LOG(Media, &quot;HTMLMediaSession::hasWirelessPlaybackTargets - returning %s&quot;, hasTargets ? &quot;TRUE&quot; : &quot;FALSE&quot;);
+
+    return hasTargets;
+}
+
+bool HTMLMediaSession::wirelessVideoPlaybackDisabled(const HTMLMediaElement&amp; element) const
+{
+    Settings* settings = element.document().settings();
+    if (!settings || !settings-&gt;mediaPlaybackAllowsAirPlay()) {
+        LOG(Media, &quot;HTMLMediaSession::wirelessVideoPlaybackDisabled - returning TRUE because of settings&quot;);
+        return true;
+    }
+
+    if (element.fastHasAttribute(HTMLNames::webkitwirelessvideoplaybackdisabledAttr)) {
+        LOG(Media, &quot;HTMLMediaSession::wirelessVideoPlaybackDisabled - returning TRUE because of attribute&quot;);
+        return true;
+    }
+
+#if PLATFORM(IOS)
+    String legacyAirplayAttributeValue = element.fastGetAttribute(HTMLNames::webkitairplayAttr);
+    if (equalIgnoringCase(legacyAirplayAttributeValue, &quot;deny&quot;)) {
+        LOG(Media, &quot;HTMLMediaSession::wirelessVideoPlaybackDisabled - returning TRUE because of legacy attribute&quot;);
+        return true;
+    }
+#endif
+
+    MediaPlayer* player = element.player();
+    if (!player)
+        return false;
+
+    bool disabled = player-&gt;wirelessVideoPlaybackDisabled();
+    LOG(Media, &quot;HTMLMediaSession::wirelessVideoPlaybackDisabled - returning %s because media engine says so&quot;, disabled ? &quot;TRUE&quot; : &quot;FALSE&quot;);
+    
+    return disabled;
+}
+
+void HTMLMediaSession::setWirelessVideoPlaybackDisabled(const HTMLMediaElement&amp; element, bool disabled)
+{
+    if (disabled)
+        addBehaviorRestriction(WirelessVideoPlaybackDisabled);
+    else
+        removeBehaviorRestriction(WirelessVideoPlaybackDisabled);
+
+    MediaPlayer* player = element.player();
+    if (!player)
+        return;
+
+    LOG(Media, &quot;HTMLMediaSession::setWirelessVideoPlaybackDisabled - disabled %s&quot;, disabled ? &quot;TRUE&quot; : &quot;FALSE&quot;);
+    player-&gt;setWirelessVideoPlaybackDisabled(disabled);
+}
+
+void HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners(const HTMLMediaElement&amp; element, bool hasListeners)
+{
+    LOG(Media, &quot;HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners - hasListeners %s&quot;, hasListeners ? &quot;TRUE&quot; : &quot;FALSE&quot;);
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    if (element.shouldUseVideoPluginProxy()) {
+        MediaPlayer* player = element.player();
+        if (!player)
+            return;
+        
+        player-&gt;setHasPlaybackTargetAvailabilityListeners(hasListeners);
+        return;
+    }
+#else
+    UNUSED_PARAM(hasListeners);
+    UNUSED_PARAM(element);
+#endif
+
+    notImplemented();
+}
+#endif
+
</ins><span class="cx"> MediaPlayer::Preload HTMLMediaSession::effectivePreloadForElement(const HTMLMediaElement&amp; element) const
</span><span class="cx"> {
</span><span class="cx">     MediaSessionManager::SessionRestrictions restrictions = MediaSessionManager::sharedManager().restrictions(mediaType());
</span><span class="lines">@@ -202,6 +334,18 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void HTMLMediaSession::applyMediaPlayerRestrictions(const HTMLMediaElement&amp; element)
+{
+    LOG(Media, &quot;HTMLMediaSession::applyMediaPlayerRestrictions&quot;);
+
+#if ENABLE(IOS_AIRPLAY)
+    setWirelessVideoPlaybackDisabled(element, m_restrictions &amp; WirelessVideoPlaybackDisabled);
+#else
+    UNUSED_PARAM(element);
+#endif
+    
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif // ENABLE(VIDEO)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaSession.h (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaSession.h        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/html/HTMLMediaSession.h        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -49,10 +49,21 @@
</span><span class="cx">     bool pageAllowsPlaybackAfterResuming(const HTMLMediaElement&amp;) const;
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx">     bool showingPlaybackTargetPickerPermitted(const HTMLMediaElement&amp;) const;
</span><ins>+
+    bool currentPlaybackTargetIsWireless(const HTMLMediaElement&amp;) const;
+    void showPlaybackTargetPicker(const HTMLMediaElement&amp;);
+    bool hasWirelessPlaybackTargets(const HTMLMediaElement&amp;) const;
+
+    bool wirelessVideoPlaybackDisabled(const HTMLMediaElement&amp;) const;
+    void setWirelessVideoPlaybackDisabled(const HTMLMediaElement&amp;, bool);
+
+    void setHasPlaybackTargetAvailabilityListeners(const HTMLMediaElement&amp;, bool);
</ins><span class="cx"> #endif
</span><span class="cx">     bool requiresFullscreenForVideoPlayback(const HTMLMediaElement&amp;) const;
</span><span class="cx">     MediaPlayer::Preload effectivePreloadForElement(const HTMLMediaElement&amp;) const;
</span><span class="cx"> 
</span><ins>+    void applyMediaPlayerRestrictions(const HTMLMediaElement&amp;);
+
</ins><span class="cx">     // Restrictions to modify default behaviors.
</span><span class="cx">     enum BehaviorRestrictionFlags {
</span><span class="cx">         NoRestrictions = 0,
</span><span class="lines">@@ -63,6 +74,7 @@
</span><span class="cx">         RequirePageConsentToResumeMedia = 1 &lt;&lt; 4,
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx">         RequireUserGestureToShowPlaybackTargetPicker = 1 &lt;&lt; 5,
</span><ins>+        WirelessVideoPlaybackDisabled =  1 &lt;&lt; 6,
</ins><span class="cx"> #endif
</span><span class="cx">     };
</span><span class="cx">     typedef unsigned BehaviorRestrictions;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLVideoElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLVideoElement.cpp        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -133,21 +133,18 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><del>-    else if (name == webkitwirelessvideoplaybackdisabledAttr) {
-        if (player())
-            player()-&gt;setWirelessVideoPlaybackDisabled(webkitWirelessVideoPlaybackDisabled());
-    } else {
-        HTMLMediaElement::parseAttribute(name, value);
-
-        if (name == webkitairplayAttr) {
-            if (player())
-                player()-&gt;setWirelessVideoPlaybackDisabled(webkitWirelessVideoPlaybackDisabled());
-        }
-    }
-#else
-    else
</del><ins>+    else if (name == webkitwirelessvideoplaybackdisabledAttr)
+        mediaSession().setWirelessVideoPlaybackDisabled(*this, webkitWirelessVideoPlaybackDisabled());
+#endif
+    else {
</ins><span class="cx">         HTMLMediaElement::parseAttribute(name, value);    
</span><ins>+
+#if PLATFORM(IOS) &amp;&amp; ENABLE(IOS_AIRPLAY)
+        if (name == webkitairplayAttr)
+            mediaSession().setWirelessVideoPlaybackDisabled(*this, webkitWirelessVideoPlaybackDisabled());
</ins><span class="cx"> #endif
</span><ins>+    }
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool HTMLVideoElement::supportsFullscreen() const
</span><span class="lines">@@ -316,14 +313,7 @@
</span><span class="cx"> #if ENABLE(IOS_AIRPLAY)
</span><span class="cx"> bool HTMLVideoElement::webkitWirelessVideoPlaybackDisabled() const
</span><span class="cx"> {
</span><del>-    Settings* settings = document().settings();
-    if (!settings || !settings-&gt;mediaPlaybackAllowsAirPlay())
-        return true;
-
-    String legacyAirplayAttributeValue = fastGetAttribute(webkitairplayAttr);
-    if (equalIgnoringCase(legacyAirplayAttributeValue, &quot;deny&quot;))
-        return true;
-    return fastHasAttribute(webkitwirelessvideoplaybackdisabledAttr);
</del><ins>+    return mediaSession().wirelessVideoPlaybackDisabled(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLVideoElement::setWebkitWirelessVideoPlaybackDisabled(bool disabled)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioMediaSessionManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/MediaSessionManager.h (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/MediaSessionManager.h        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/audio/MediaSessionManager.h        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -69,6 +69,10 @@
</span><span class="cx"> 
</span><span class="cx">     bool sessionRestrictsInlineVideoPlayback(const MediaSession&amp;) const;
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    virtual void showPlaybackTargetPicker() { }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     friend class MediaSession;
</span><span class="cx">     explicit MediaSessionManager();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioiosMediaSessionManagerIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -44,6 +44,10 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void resetRestrictions() override;
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    virtual void showPlaybackTargetPicker() override;
+#endif
+
</ins><span class="cx">     MediaSessionManageriOS();
</span><span class="cx">     RetainPtr&lt;WebMediaSessionHelper&gt; m_objcObserver;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioiosMediaSessionManagerIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="cx"> #import &quot;MediaSession.h&quot;
</span><ins>+#import &quot;NotImplemented.h&quot;
</ins><span class="cx"> #import &quot;SoftLinking.h&quot;
</span><span class="cx"> #import &quot;WebCoreSystemInterface.h&quot;
</span><span class="cx"> #import &quot;WebCoreThreadRun.h&quot;
</span><span class="lines">@@ -106,6 +107,13 @@
</span><span class="cx">     addRestriction(MediaSession::Video, AutoPreloadingNotPermitted);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+void MediaSessionManageriOS::showPlaybackTargetPicker()
+{
+    notImplemented();
+}
+#endif
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> @implementation WebMediaSessionHelper
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationMediaPlayerPrivateAVFoundationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -892,6 +892,11 @@
</span><span class="cx">     case Notification::FunctionType:
</span><span class="cx">         notification.function()();
</span><span class="cx">         break;
</span><ins>+    case Notification::TargetIsWirelessChanged:
+#if ENABLE(IOS_AIRPLAY)
+        playbackTargetIsWirelessChanged();
+#endif
+        break;
</ins><span class="cx"> 
</span><span class="cx">     case Notification::None:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="lines">@@ -971,6 +976,13 @@
</span><span class="cx">     LOG(Media, &quot;MediaPlayerPrivateAVFoundation::processNewAndRemovedTextTracks(%p) - found %lu text tracks&quot;, this, m_textTracks.size());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+void MediaPlayerPrivateAVFoundation::playbackTargetIsWirelessChanged()
+{
+    if (m_player)
+        m_player-&gt;currentPlaybackTargetIsWirelessChanged();
+}
+#endif
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationMediaPlayerPrivateAVFoundationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -59,7 +59,10 @@
</span><span class="cx">     virtual void configureInbandTracks();
</span><span class="cx">     virtual void setCurrentTrack(InbandTextTrackPrivateAVF*) { }
</span><span class="cx">     virtual InbandTextTrackPrivateAVF* currentTrack() const = 0;
</span><del>-
</del><ins>+#if ENABLE(IOS_AIRPLAY)
+    void playbackTargetIsWirelessChanged();
+#endif
+    
</ins><span class="cx">     class Notification {
</span><span class="cx">     public:
</span><span class="cx"> #define FOR_EACH_MEDIAPLAYERPRIVATEAVFOUNDATION_NOTIFICATION_TYPE(macro) \
</span><span class="lines">@@ -81,6 +84,7 @@
</span><span class="cx">     macro(DurationChanged) \
</span><span class="cx">     macro(ContentsNeedsDisplay) \
</span><span class="cx">     macro(InbandTracksNeedConfiguration) \
</span><ins>+    macro(TargetIsWirelessChanged) \
</ins><span class="cx"> 
</span><span class="cx">         enum Type {
</span><span class="cx"> #define DEFINE_TYPE_ENUM(type) type,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -113,6 +113,10 @@
</span><span class="cx">     void outputMediaDataWillChange(AVPlayerItemVideoOutput*);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    void playbackTargetIsWirelessDidChange();
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx">     MediaPlayerPrivateAVFoundationObjC(MediaPlayer*);
</span><span class="cx"> 
</span><span class="lines">@@ -222,6 +226,12 @@
</span><span class="cx">     void updateVideoTracks();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    virtual bool isCurrentPlaybackTargetWireless() const override;
+    virtual bool wirelessVideoPlaybackDisabled() const override;
+    virtual void setWirelessVideoPlaybackDisabled(bool) override;
+#endif
+
</ins><span class="cx">     WeakPtrFactory&lt;MediaPlayerPrivateAVFoundationObjC&gt; m_weakPtrFactory;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVURLAsset&gt; m_avAsset;
</span><span class="lines">@@ -277,6 +287,9 @@
</span><span class="cx">     bool m_cachedBufferEmpty;
</span><span class="cx">     bool m_cachedBufferFull;
</span><span class="cx">     bool m_cachedHasEnabledAudio;
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    mutable bool m_allowsWirelessVideoPlayback;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (164660 => 164661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2014-02-25 19:47:37 UTC (rev 164660)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2014-02-25 20:29:58 UTC (rev 164661)
</span><span class="lines">@@ -331,6 +331,9 @@
</span><span class="cx">     , m_cachedBufferEmpty(false)
</span><span class="cx">     , m_cachedBufferFull(false)
</span><span class="cx">     , m_cachedHasEnabledAudio(false)
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    , m_allowsWirelessVideoPlayback(true)
+#endif
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><span class="cx">     playerToPrivateMap().set(player, this);
</span><span class="lines">@@ -389,6 +392,9 @@
</span><span class="cx">             [m_avPlayer.get() removeTimeObserver:m_timeObserver.get()];
</span><span class="cx">         m_timeObserver = nil;
</span><span class="cx">         [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@&quot;rate&quot;];
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+        [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@&quot;externalPlaybackActive&quot;];
+#endif
</ins><span class="cx">         m_avPlayer = nil;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -494,7 +500,7 @@
</span><span class="cx">     if (!m_videoLayer)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying&quot;, this, m_videoLayer.get());
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying %p&quot;, this, m_videoLayer.get());
</ins><span class="cx"> 
</span><span class="cx">     [m_videoLayer.get() setPlayer:nil];
</span><span class="cx"> 
</span><span class="lines">@@ -602,11 +608,18 @@
</span><span class="cx"> 
</span><span class="cx">     m_avPlayer = adoptNS([[AVPlayer alloc] init]);
</span><span class="cx">     [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@&quot;rate&quot; options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@&quot;externalPlaybackActive&quot; options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) &amp;&amp; HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT)
</span><span class="cx">     [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically:YES];
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+    [m_avPlayer.get() setAllowsExternalPlayback:m_allowsWirelessVideoPlayback];
+#endif
+
</ins><span class="cx">     if (m_avPlayerItem)
</span><span class="cx">         [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()];
</span><span class="cx"> 
</span><span class="lines">@@ -1459,7 +1472,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if !LOG_DISABLED
</span><span class="cx">     double duration = monotonicallyIncreasingTime() - start;
</span><del>-    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::createPixelBuffer() - creating buffer took %.4f&quot;, this, narrowPrecisionToFloat(duration));
</del><ins>+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::createPixelBuffer(%p) - creating buffer took %.4f&quot;, this, narrowPrecisionToFloat(duration));
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     return buffer;
</span><span class="lines">@@ -1876,7 +1889,7 @@
</span><span class="cx">     NSArray *tracks = [m_avAsset.get() tracksWithMediaType:AVMediaTypeAudio];
</span><span class="cx">     if (!tracks || [tracks count] != 1) {
</span><span class="cx">         m_languageOfPrimaryAudioTrack = emptyString();
</span><del>-        LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - %i audio tracks, returning emptyString()&quot;, this, (tracks ? [tracks count] : 0));
</del><ins>+        LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - %lu audio tracks, returning emptyString()&quot;, this, static_cast&lt;unsigned long&gt;(tracks ? [tracks count] : 0));
</ins><span class="cx">         return m_languageOfPrimaryAudioTrack;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1893,6 +1906,39 @@
</span><span class="cx">     return m_languageOfPrimaryAudioTrack;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+bool MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless() const
+{
+    if (!m_avPlayer)
+        return false;
+
+    bool wirelessTarget = [m_avPlayer.get() isExternalPlaybackActive];
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless(%p) - returning %s&quot;, this, boolString(wirelessTarget));
+    return wirelessTarget;
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled() const
+{
+    if (!m_avPlayer)
+        return !m_allowsWirelessVideoPlayback;
+    
+    m_allowsWirelessVideoPlayback = ![m_avPlayer.get() allowsExternalPlayback];
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled(%p) - returning %s&quot;, this, boolString(!m_allowsWirelessVideoPlayback));
+
+    return !m_allowsWirelessVideoPlayback;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled(bool disabled)
+{
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled(%p) - %s&quot;, this, boolString(disabled));
+    m_allowsWirelessVideoPlayback = !disabled;
+    if (!m_avPlayer)
+        return;
+    
+    [m_avPlayer.get() setAllowsExternalPlayback:disabled];
+}
+#endif
+
</ins><span class="cx"> void MediaPlayerPrivateAVFoundationObjC::playerItemStatusDidChange(int status)
</span><span class="cx"> {
</span><span class="cx">     m_cachedItemStatus = status;
</span><span class="lines">@@ -1996,6 +2042,13 @@
</span><span class="cx">     updateStates();
</span><span class="cx">     rateChanged();
</span><span class="cx"> }
</span><ins>+    
+#if ENABLE(IOS_AIRPLAY)
+void MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange()
+{
+    playbackTargetIsWirelessChanged();
+}
+#endif
</ins><span class="cx"> 
</span><span class="cx"> NSArray* assetMetadataKeyNames()
</span><span class="cx"> {
</span><span class="lines">@@ -2082,7 +2135,7 @@
</span><span class="cx">     UNUSED_PARAM(object);
</span><span class="cx">     id newValue = [change valueForKey:NSKeyValueChangeNewKey];
</span><span class="cx"> 
</span><del>-    LOG(Media, &quot;WebCoreAVFMovieObserver:observeValueForKeyPath(%p) - keyPath = %s&quot;, self, [keyPath UTF8String]);
</del><ins>+    LOG(Media, &quot;WebCoreAVFMovieObserver::observeValueForKeyPath(%p) - keyPath = %s&quot;, self, [keyPath UTF8String]);
</ins><span class="cx"> 
</span><span class="cx">     if (!m_callback)
</span><span class="cx">         return;
</span><span class="lines">@@ -2130,6 +2183,10 @@
</span><span class="cx">         // A value changed for an AVPlayer.
</span><span class="cx">         if ([keyPath isEqualToString:@&quot;rate&quot;])
</span><span class="cx">             function = WTF::bind(&amp;MediaPlayerPrivateAVFoundationObjC::rateDidChange, m_callback, [newValue doubleValue]);
</span><ins>+#if ENABLE(IOS_AIRPLAY)
+        else if ([keyPath isEqualToString:@&quot;externalPlaybackActive&quot;])
+            function = WTF::bind(&amp;MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
+#endif
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (function.isNull())
</span></span></pre>
</div>
</div>

</body>
</html>