Title: [199351] trunk/Source/WebCore
Revision
199351
Author
[email protected]
Date
2016-04-12 08:19:31 -0700 (Tue, 12 Apr 2016)

Log Message

[iOS] media title sometimes remain in Control Center after tab is closed
https://bugs.webkit.org/show_bug.cgi?id=156243
<rdar://problem/20167445>

Reviewed by Darin Adler.

* Modules/webaudio/AudioContext.h: Implement characteristics.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::mediaLoadingFailed): Call mediaSession->clientCharacteristicsChanged.
(WebCore::HTMLMediaElement::setReadyState): Ditto.
(WebCore::HTMLMediaElement::clearMediaPlayer): Ditto.
(WebCore::HTMLMediaElement::stop): Call mediaSession->stopSession.
(WebCore::HTMLMediaElement::characteristics): New, return current characteristics.
* html/HTMLMediaElement.h:

* platform/audio/PlatformMediaSession.cpp:
(WebCore::PlatformMediaSession::stopSession): Suspend playback, and remove the session
  from the manager, it will never play again.
(WebCore::PlatformMediaSession::characteristics): Return client characteristics.
(WebCore::PlatformMediaSession::clientCharacteristicsChanged):
* platform/audio/PlatformMediaSession.h:

* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess): Call stopSession
  instead of pauseSession to signal that playback will never start again.
* platform/audio/PlatformMediaSessionManager.h:

* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(WebCore::MediaSessionManageriOS::sessionWillBeginPlayback): Add logging.
(WebCore::MediaSessionManageriOS::removeSession): Update NowPlaying.
(WebCore::MediaSessionManageriOS::sessionWillEndPlayback): Add logging.
(WebCore::MediaSessionManageriOS::clientCharacteristicsChanged): Update NowPlaying.
(WebCore::MediaSessionManageriOS::nowPlayingEligibleSession): New, return the first session
  that is an audio or video element with playable audio. WebAudio is not currently controllable
  so it isn't appropriate to show it in the NowPlaying info center.
(WebCore::MediaSessionManageriOS::updateNowPlayingInfo): Remember the last state passed to
  NowPlaying so we can call it only when something has changed.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (199350 => 199351)


--- trunk/Source/WebCore/ChangeLog	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/ChangeLog	2016-04-12 15:19:31 UTC (rev 199351)
@@ -1,3 +1,45 @@
+2016-04-12  Eric Carlson  <[email protected]>
+
+        [iOS] media title sometimes remain in Control Center after tab is closed
+        https://bugs.webkit.org/show_bug.cgi?id=156243
+        <rdar://problem/20167445>
+
+        Reviewed by Darin Adler.
+
+        * Modules/webaudio/AudioContext.h: Implement characteristics.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::mediaLoadingFailed): Call mediaSession->clientCharacteristicsChanged.
+        (WebCore::HTMLMediaElement::setReadyState): Ditto.
+        (WebCore::HTMLMediaElement::clearMediaPlayer): Ditto.
+        (WebCore::HTMLMediaElement::stop): Call mediaSession->stopSession.
+        (WebCore::HTMLMediaElement::characteristics): New, return current characteristics.
+        * html/HTMLMediaElement.h:
+
+        * platform/audio/PlatformMediaSession.cpp:
+        (WebCore::PlatformMediaSession::stopSession): Suspend playback, and remove the session 
+          from the manager, it will never play again.
+        (WebCore::PlatformMediaSession::characteristics): Return client characteristics.
+        (WebCore::PlatformMediaSession::clientCharacteristicsChanged):
+        * platform/audio/PlatformMediaSession.h:
+
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess): Call stopSession 
+          instead of pauseSession to signal that playback will never start again.
+        * platform/audio/PlatformMediaSessionManager.h:
+
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (WebCore::MediaSessionManageriOS::sessionWillBeginPlayback): Add logging.
+        (WebCore::MediaSessionManageriOS::removeSession): Update NowPlaying.
+        (WebCore::MediaSessionManageriOS::sessionWillEndPlayback): Add logging.
+        (WebCore::MediaSessionManageriOS::clientCharacteristicsChanged): Update NowPlaying.
+        (WebCore::MediaSessionManageriOS::nowPlayingEligibleSession): New, return the first session
+          that is an audio or video element with playable audio. WebAudio is not currently controllable
+          so it isn't appropriate to show it in the NowPlaying info center.
+        (WebCore::MediaSessionManageriOS::updateNowPlayingInfo): Remember the last state passed to
+          NowPlaying so we can call it only when something has changed.
+
 2016-04-12  Carlos Garcia Campos  <[email protected]>
 
         [GTK] Rework scrollbars theming code for GTK+ 3.20

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (199350 => 199351)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2016-04-12 15:19:31 UTC (rev 199351)
@@ -318,6 +318,7 @@
     // PlatformMediaSessionClient
     PlatformMediaSession::MediaType mediaType() const override { return PlatformMediaSession::WebAudio; }
     PlatformMediaSession::MediaType presentationType() const override { return PlatformMediaSession::WebAudio; }
+    PlatformMediaSession::CharacteristicsFlags characteristics() const override { return m_state == State::Running ? PlatformMediaSession::HasAudio : PlatformMediaSession::HasNothing; }
     void mayResumePlayback(bool shouldResume) override;
     void suspendPlayback() override;
     bool canReceiveRemoteControlCommands() const override { return false; }

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (199350 => 199351)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-04-12 15:19:31 UTC (rev 199351)
@@ -2058,6 +2058,8 @@
     }
 
     logMediaLoadRequest(document().page(), String(), stringForNetworkState(error), false);
+
+    m_mediaSession->clientCharacteristicsChanged();
 }
 
 void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
@@ -2213,6 +2215,8 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
         updateMediaState(UpdateMediaState::Asynchronously);
 #endif
+
+        m_mediaSession->clientCharacteristicsChanged();
     }
 
     bool shouldUpdateDisplayState = false;
@@ -5004,6 +5008,7 @@
 #endif
 
     m_mediaSession->setCanProduceAudio(false);
+    m_mediaSession->clientCharacteristicsChanged();
 
     updateSleepDisabling();
 }
@@ -5064,6 +5069,8 @@
     // if the media was not fully loaded, but we need the same cleanup if the file was completely
     // loaded and calling it again won't cause any problems.
     clearMediaPlayer(EveryDelayedAction);
+
+    m_mediaSession->stopSession();
 }
 
 void HTMLMediaElement::suspend(ReasonForSuspension why)
@@ -6577,6 +6584,20 @@
     return PlatformMediaSession::Normal;
 }
 
+PlatformMediaSession::CharacteristicsFlags HTMLMediaElement::characteristics() const
+{
+    if (m_readyState < HAVE_METADATA)
+        return PlatformMediaSession::HasNothing;
+
+    PlatformMediaSession::CharacteristicsFlags state = PlatformMediaSession::HasNothing;
+    if (isVideo() && hasVideo())
+        state |= PlatformMediaSession::HasVideo;
+    if (this->hasAudio())
+        state |= PlatformMediaSession::HasAudio;
+
+    return state;
+}
+
 #if ENABLE(MEDIA_SOURCE)
 size_t HTMLMediaElement::maximumSourceBufferSize(const SourceBuffer& buffer) const
 {

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (199350 => 199351)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2016-04-12 15:19:31 UTC (rev 199351)
@@ -738,6 +738,8 @@
     PlatformMediaSession::MediaType mediaType() const override;
     PlatformMediaSession::MediaType presentationType() const override;
     PlatformMediaSession::DisplayType displayType() const override;
+    PlatformMediaSession::CharacteristicsFlags characteristics() const final;
+
     void suspendPlayback() override;
     void resumeAutoplaying() override;
     void mayResumePlayback(bool shouldResume) override;

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.cpp	2016-04-12 15:19:31 UTC (rev 199351)
@@ -103,8 +103,10 @@
     if (++m_interruptionCount > 1)
         return;
 
-    if (client().shouldOverrideBackgroundPlaybackRestriction(type))
+    if (client().shouldOverrideBackgroundPlaybackRestriction(type)) {
+        LOG(Media, "PlatformMediaSession::beginInterruption(%p), returning early because client says to override interruption", this);
         return;
+    }
 
     m_stateToRestore = state();
     m_notifyingClient = true;
@@ -195,6 +197,13 @@
     m_client.suspendPlayback();
 }
 
+void PlatformMediaSession::stopSession()
+{
+    LOG(Media, "PlatformMediaSession::stopSession(%p)", this);
+    m_client.suspendPlayback();
+    PlatformMediaSessionManager::sharedManager().removeSession(*this);
+}
+
 PlatformMediaSession::MediaType PlatformMediaSession::mediaType() const
 {
     return m_client.mediaType();
@@ -205,6 +214,11 @@
     return m_client.presentationType();
 }
 
+PlatformMediaSession::CharacteristicsFlags PlatformMediaSession::characteristics() const
+{
+    return m_client.characteristics();
+}
+
 #if ENABLE(VIDEO)
 String PlatformMediaSession::title() const
 {
@@ -318,5 +332,10 @@
 }
 #endif
 
+void PlatformMediaSession::clientCharacteristicsChanged()
+{
+    PlatformMediaSessionManager::sharedManager().clientCharacteristicsChanged(*this);
 }
+
+}
 #endif

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSession.h (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSession.h	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSession.h	2016-04-12 15:19:31 UTC (rev 199351)
@@ -86,6 +86,16 @@
         MayResumePlaying = 1 << 0,
     };
 
+    enum Characteristics {
+        HasNothing = 0,
+        HasAudio = 1 << 0,
+        HasVideo = 1 << 1,
+    };
+    typedef unsigned CharacteristicsFlags;
+
+    CharacteristicsFlags characteristics() const;
+    void clientCharacteristicsChanged();
+
     void beginInterruption(InterruptionType);
     void endInterruption(EndInterruptionFlags);
 
@@ -94,6 +104,7 @@
     bool clientWillPausePlayback();
 
     void pauseSession();
+    void stopSession();
     
     void visibilityChanged();
 
@@ -173,6 +184,7 @@
     virtual PlatformMediaSession::MediaType mediaType() const = 0;
     virtual PlatformMediaSession::MediaType presentationType() const = 0;
     virtual PlatformMediaSession::DisplayType displayType() const { return PlatformMediaSession::Normal; }
+    virtual PlatformMediaSession::CharacteristicsFlags characteristics() const = 0;
 
     virtual void resumeAutoplaying() { }
     virtual void mayResumePlayback(bool shouldResume) = 0;

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp	2016-04-12 15:19:31 UTC (rev 199351)
@@ -153,7 +153,6 @@
     LOG(Media, "PlatformMediaSessionManager::removeSession - %p", &session);
     
     size_t index = m_sessions.find(&session);
-    ASSERT(index != notFound);
     if (index == notFound)
         return;
     
@@ -380,7 +379,7 @@
 {
     Vector<PlatformMediaSession*> sessions = m_sessions;
     for (auto* session : sessions)
-        session->pauseSession();
+        session->stopSession();
 }
 
 }

Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h	2016-04-12 15:19:31 UTC (rev 199351)
@@ -82,6 +82,7 @@
     virtual bool sessionWillBeginPlayback(PlatformMediaSession&);
     virtual void sessionWillEndPlayback(PlatformMediaSession&);
     virtual bool sessionCanLoadMedia(const PlatformMediaSession&) const;
+    virtual void clientCharacteristicsChanged(PlatformMediaSession&) { }
 
 #if PLATFORM(IOS)
     virtual void configureWireLessTargetMonitoring() { }
@@ -99,7 +100,7 @@
     explicit PlatformMediaSessionManager();
 
     void addSession(PlatformMediaSession&);
-    void removeSession(PlatformMediaSession&);
+    virtual void removeSession(PlatformMediaSession&);
 
     Vector<PlatformMediaSession*> sessions() { return m_sessions; }
 

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h	2016-04-12 15:19:31 UTC (rev 199351)
@@ -56,9 +56,12 @@
 
     MediaSessionManageriOS();
 
+    void removeSession(PlatformMediaSession&) override;
+
     bool sessionWillBeginPlayback(PlatformMediaSession&) override;
     void sessionWillEndPlayback(PlatformMediaSession&) override;
-    
+    void clientCharacteristicsChanged(PlatformMediaSession&) override;
+
     void updateNowPlayingInfo();
     
     void resetRestrictions() override;
@@ -66,8 +69,11 @@
     void configureWireLessTargetMonitoring() override;
 
     bool sessionCanLoadMedia(const PlatformMediaSession&) const override;
+
+    PlatformMediaSession* nowPlayingEligibleSession();
     
     RetainPtr<WebMediaSessionHelper> m_objcObserver;
+    RetainPtr<NSMutableDictionary> m_nowPlayingInfo;
     bool m_isInBackground { false };
 };
 

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm (199350 => 199351)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2016-04-12 14:56:10 UTC (rev 199350)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2016-04-12 15:19:31 UTC (rev 199351)
@@ -193,43 +193,87 @@
     if (!PlatformMediaSessionManager::sessionWillBeginPlayback(session))
         return false;
 
+    LOG(Media, "MediaSessionManageriOS::sessionWillBeginPlayback");
     updateNowPlayingInfo();
     return true;
 }
-    
+
+void MediaSessionManageriOS::removeSession(PlatformMediaSession& session)
+{
+    PlatformMediaSessionManager::removeSession(session);
+    LOG(Media, "MediaSessionManageriOS::removeSession");
+    updateNowPlayingInfo();
+}
+
 void MediaSessionManageriOS::sessionWillEndPlayback(PlatformMediaSession& session)
 {
     PlatformMediaSessionManager::sessionWillEndPlayback(session);
+    LOG(Media, "MediaSessionManageriOS::sessionWillEndPlayback");
     updateNowPlayingInfo();
 }
-    
+
+void MediaSessionManageriOS::clientCharacteristicsChanged(PlatformMediaSession&)
+{
+    LOG(Media, "MediaSessionManageriOS::clientCharacteristicsChanged");
+    updateNowPlayingInfo();
+}
+
+PlatformMediaSession* MediaSessionManageriOS::nowPlayingEligibleSession()
+{
+    for (auto session : sessions()) {
+        PlatformMediaSession::MediaType type = session->mediaType();
+        if (type != PlatformMediaSession::Video && type != PlatformMediaSession::Audio)
+            continue;
+
+        if (session->characteristics() & PlatformMediaSession::HasAudio)
+            return session;
+    }
+
+    return nullptr;
+}
+
 void MediaSessionManageriOS::updateNowPlayingInfo()
 {
-    LOG(Media, "MediaSessionManageriOS::updateNowPlayingInfo");
+    MPNowPlayingInfoCenter *nowPlaying = (MPNowPlayingInfoCenter *)[getMPNowPlayingInfoCenterClass() defaultCenter];
+    const PlatformMediaSession* currentSession = this->nowPlayingEligibleSession();
 
-    MPNowPlayingInfoCenter *nowPlaying = (MPNowPlayingInfoCenter *)[getMPNowPlayingInfoCenterClass() defaultCenter];
-    const PlatformMediaSession* currentSession = this->currentSession();
-    
+    LOG(Media, "MediaSessionManageriOS::updateNowPlayingInfo - currentSession = %p", currentSession);
+
     if (!currentSession) {
-        [nowPlaying setNowPlayingInfo:nil];
+        if (m_nowPlayingInfo) {
+            LOG(Media, "MediaSessionManageriOS::updateNowPlayingInfo - clearing now playing info");
+            [nowPlaying setNowPlayingInfo:nil];
+            m_nowPlayingInfo = nil;
+        }
+
         return;
     }
-    
+
     RetainPtr<NSMutableDictionary> info = adoptNS([[NSMutableDictionary alloc] init]);
-    
+
     String title = currentSession->title();
     if (!title.isEmpty())
         [info setValue:static_cast<NSString *>(title) forKey:MPMediaItemPropertyTitle];
-    
+
     double duration = currentSession->duration();
     if (std::isfinite(duration) && duration != MediaPlayer::invalidTime())
         [info setValue:@(duration) forKey:MPMediaItemPropertyPlaybackDuration];
-    
+
+    [info setValue:(currentSession->state() == PlatformMediaSession::Playing ? @YES : @NO) forKey:MPNowPlayingInfoPropertyPlaybackRate];
+
+    if ([m_nowPlayingInfo.get() isEqualToDictionary:info.get()]) {
+        LOG(Media, "MediaSessionManageriOS::updateNowPlayingInfo - nothing new to show");
+        return;
+    }
+
+    m_nowPlayingInfo = info;
+
     double currentTime = currentSession->currentTime();
     if (std::isfinite(currentTime) && currentTime != MediaPlayer::invalidTime())
         [info setValue:@(currentTime) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
-    
-    [info setValue:(currentSession->state() == PlatformMediaSession::Playing ? @YES : @NO) forKey:MPNowPlayingInfoPropertyPlaybackRate];
+
+    LOG(Media, "MediaSessionManageriOS::updateNowPlayingInfo - title = \"%s\"", [[info.get() valueForKey:MPMediaItemPropertyTitle] UTF8String]);
+
     [nowPlaying setNowPlayingInfo:info.get()];
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to