<!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>[189322] 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/189322">189322</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2015-09-03 16:53:33 -0700 (Thu, 03 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Playback does not pause when deselecting route and locking screen.
https://bugs.webkit.org/show_bug.cgi?id=148724

Reviewed by Eric Carlson.

When deselecting a route, the route change notification can be delayed for some amount
of time. If the screen is locked before the notification is fired, the PlatformMediaSessionManager
can refuse to pause the video when entering the background due to a wireless playback route
still being active.

When the media element transitions from having an active route to not having one (or vice versa),
re-run the interruption check. In order to correctly determine, when that occurs, whether
we are in an 'application background' state, cache that value to an ivar when handling
application{Will,Did}Enter{Background,Foreground}.

Because we only want to run this step during an actual transition between playing to a route -&gt;
playing locally, cache the value of isPlayingToWirelessPlayback to another ivar, and only
inform the PlatformMediaSessionManager when that value actually changes.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged):
* platform/audio/PlatformMediaSession.cpp:
(WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged): Set or clear m_isPlayingToWirelessPlaybackTarget.
* platform/audio/PlatformMediaSession.h:
(WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTarget): Simple getter.
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::applicationWillEnterBackground): Set m_isApplicationInBackground.
(WebCore::PlatformMediaSessionManager::applicationDidEnterBackground): Ditto.
(WebCore::PlatformMediaSessionManager::applicationWillEnterForeground): Clear m_isApplicationInBackground.
(WebCore::PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged): Run interruption
    if application is in background.</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="#trunkSourceWebCoreplatformaudioPlatformMediaSessioncpp">trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessionh">trunk/Source/WebCore/platform/audio/PlatformMediaSession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessionManagercpp">trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioPlatformMediaSessionManagerh">trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/ChangeLog        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2015-09-03  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [iOS] Playback does not pause when deselecting route and locking screen.
+        https://bugs.webkit.org/show_bug.cgi?id=148724
+
+        Reviewed by Eric Carlson.
+
+        When deselecting a route, the route change notification can be delayed for some amount
+        of time. If the screen is locked before the notification is fired, the PlatformMediaSessionManager
+        can refuse to pause the video when entering the background due to a wireless playback route
+        still being active.
+
+        When the media element transitions from having an active route to not having one (or vice versa),
+        re-run the interruption check. In order to correctly determine, when that occurs, whether
+        we are in an 'application background' state, cache that value to an ivar when handling
+        application{Will,Did}Enter{Background,Foreground}.
+
+        Because we only want to run this step during an actual transition between playing to a route -&gt;
+        playing locally, cache the value of isPlayingToWirelessPlayback to another ivar, and only
+        inform the PlatformMediaSessionManager when that value actually changes.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged):
+        * platform/audio/PlatformMediaSession.cpp:
+        (WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged): Set or clear m_isPlayingToWirelessPlaybackTarget.
+        * platform/audio/PlatformMediaSession.h:
+        (WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTarget): Simple getter.
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::applicationWillEnterBackground): Set m_isApplicationInBackground.
+        (WebCore::PlatformMediaSessionManager::applicationDidEnterBackground): Ditto.
+        (WebCore::PlatformMediaSessionManager::applicationWillEnterForeground): Clear m_isApplicationInBackground.
+        (WebCore::PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged): Run interruption
+            if application is in background.
+
</ins><span class="cx"> 2015-09-03  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move SecurityOriginData from WK2 to WebCore.
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -5031,9 +5031,10 @@
</span><span class="cx"> void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*)
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(%p) - webkitCurrentPlaybackTargetIsWireless = %s&quot;, this, boolString(webkitCurrentPlaybackTargetIsWireless()));
</span><del>-
</del><ins>+    ASSERT(m_player);
</ins><span class="cx">     configureMediaControls();
</span><span class="cx">     scheduleEvent(eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent);
</span><ins>+    m_mediaSession-&gt;isPlayingToWirelessPlaybackTargetChanged(m_player-&gt;isCurrentPlaybackTargetWireless());
</ins><span class="cx">     updateMediaState(UpdateMediaState::Asynchronously);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -255,6 +255,15 @@
</span><span class="cx">     return m_client.elementIsHidden();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged(bool isWireless)
+{
+    if (isWireless == m_isPlayingToWirelessPlaybackTarget)
+        return;
+
+    m_isPlayingToWirelessPlaybackTarget = isWireless;
+    PlatformMediaSessionManager::sharedManager().sessionIsPlayingToWirelessPlaybackTargetChanged(*this);
+}
+
</ins><span class="cx"> PlatformMediaSession::DisplayType PlatformMediaSession::displayType() const
</span><span class="cx"> {
</span><span class="cx">     return m_client.displayType();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.h (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.h        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -125,7 +125,8 @@
</span><span class="cx">     bool isHidden() const;
</span><span class="cx"> 
</span><span class="cx">     virtual bool canPlayToWirelessPlaybackTarget() const { return false; }
</span><del>-    virtual bool isPlayingToWirelessPlaybackTarget() const { return false; }
</del><ins>+    virtual bool isPlayingToWirelessPlaybackTarget() const { return m_isPlayingToWirelessPlaybackTarget; }
+    void isPlayingToWirelessPlaybackTargetChanged(bool);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="cx">     // MediaPlaybackTargetClient
</span><span class="lines">@@ -151,6 +152,7 @@
</span><span class="cx">     State m_stateToRestore;
</span><span class="cx">     int m_interruptionCount { 0 };
</span><span class="cx">     bool m_notifyingClient;
</span><ins>+    bool m_isPlayingToWirelessPlaybackTarget { false };
</ins><span class="cx"> 
</span><span class="cx">     friend class PlatformMediaSessionManager;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -275,6 +275,12 @@
</span><span class="cx"> void PlatformMediaSessionManager::applicationWillEnterBackground() const
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;PlatformMediaSessionManager::applicationWillEnterBackground&quot;);
</span><ins>+
+    if (m_isApplicationInBackground)
+        return;
+
+    m_isApplicationInBackground = true;
+    
</ins><span class="cx">     Vector&lt;PlatformMediaSession*&gt; sessions = m_sessions;
</span><span class="cx">     for (auto* session : sessions) {
</span><span class="cx">         if (m_restrictions[session-&gt;mediaType()] &amp; BackgroundProcessPlaybackRestricted)
</span><span class="lines">@@ -299,6 +305,12 @@
</span><span class="cx"> void PlatformMediaSessionManager::applicationWillEnterForeground() const
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;PlatformMediaSessionManager::applicationWillEnterForeground&quot;);
</span><ins>+
+    if (!m_isApplicationInBackground)
+        return;
+
+    m_isApplicationInBackground = false;
+
</ins><span class="cx">     Vector&lt;PlatformMediaSession*&gt; sessions = m_sessions;
</span><span class="cx">     for (auto* session : sessions) {
</span><span class="cx">         if (m_restrictions[session-&gt;mediaType()] &amp; BackgroundProcessPlaybackRestricted)
</span><span class="lines">@@ -306,6 +318,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession&amp; session)
+{
+    if (!m_isApplicationInBackground || !(m_restrictions[session.mediaType()] &amp; BackgroundProcessPlaybackRestricted))
+        return;
+
+    if (session.state() != PlatformMediaSession::Interrupted &amp;&amp; session.shouldDoInterruption(PlatformMediaSession::EnteringBackground))
+        session.doInterruption();
+}
+
</ins><span class="cx"> #if !PLATFORM(COCOA)
</span><span class="cx"> void PlatformMediaSessionManager::updateSessionState()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioPlatformMediaSessionManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h (189321 => 189322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h        2015-09-03 23:49:09 UTC (rev 189321)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h        2015-09-03 23:53:33 UTC (rev 189322)
</span><span class="lines">@@ -88,6 +88,8 @@
</span><span class="cx">     void setCurrentSession(PlatformMediaSession&amp;);
</span><span class="cx">     PlatformMediaSession* currentSession();
</span><span class="cx"> 
</span><ins>+    void sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession&amp;);
+
</ins><span class="cx"> protected:
</span><span class="cx">     friend class PlatformMediaSession;
</span><span class="cx">     explicit PlatformMediaSessionManager();
</span><span class="lines">@@ -126,6 +128,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool m_interrupted { false };
</span><ins>+    mutable bool m_isApplicationInBackground { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>