Ensure media playback is stopped during page close
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Jul 2015 03:40:19 +0000 (03:40 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Jul 2015 03:40:19 +0000 (03:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146554
<rdar://problem/18033944>

Reviewed by Brady Eidson.

Source/WebCore:

* Modules/webaudio/AudioContext.cpp:
(WebCore::WebAudio::hostingDocument): Added.
* Modules/webaudio/AudioContext.h:
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::hostingDocument): Added.
* dom/Document.cpp:
(WebCore::Document::~Document): Call new 'stopAllMediaPlaybackForDocument' at destruction time.
* platform/audio/PlatformMediaSession.h:
Made PlatformMediaSessionManager a friend so it can access the protected 'client' accessor.
Updated PlatformMediaSessionClient to require clients to have a "hostingDocument" member.
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForDocument): Added. Only pauses
playback on elements that match the provided document.
(WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess): Added. Pauses playback
on all elements in the current process.
* platform/audio/PlatformMediaSessionManager.h:

Source/WebKit2:

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::didClose): Make sure to clean up any running media sessions when
the process is being shut down.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186396 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/dom/Document.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/platform/audio/PlatformMediaSession.h
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/PlatformMediaSessionManager.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebProcess.cpp

index a9aa297..c7b7e26 100644 (file)
@@ -1,3 +1,28 @@
+2015-07-06  Brent Fulgham  <bfulgham@apple.com>
+
+        Ensure media playback is stopped during page close
+        https://bugs.webkit.org/show_bug.cgi?id=146554
+        <rdar://problem/18033944>
+
+        Reviewed by Brady Eidson.
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::WebAudio::hostingDocument): Added.
+        * Modules/webaudio/AudioContext.h:
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::hostingDocument): Added.
+        * dom/Document.cpp:
+        (WebCore::Document::~Document): Call new 'stopAllMediaPlaybackForDocument' at destruction time.
+        * platform/audio/PlatformMediaSession.h:
+        Made PlatformMediaSessionManager a friend so it can access the protected 'client' accessor.
+        Updated PlatformMediaSessionClient to require clients to have a "hostingDocument" member.
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForDocument): Added. Only pauses
+        playback on elements that match the provided document.
+        (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess): Added. Pauses playback
+        on all elements in the current process.
+        * platform/audio/PlatformMediaSessionManager.h:
+
 2015-07-06  Daniel Bates  <dabates@apple.com>
 
         Isolated worlds should respect Content Security Policy; User Agent Shadow DOM
index faa996b..23234a6 100644 (file)
@@ -370,6 +370,11 @@ Document* AudioContext::document() const
     return downcast<Document>(m_scriptExecutionContext);
 }
 
+const Document* AudioContext::hostingDocument() const
+{
+    return downcast<Document>(m_scriptExecutionContext);
+}
+
 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec)
 {
     RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
index e9f76c9..f7d56e9 100644 (file)
@@ -90,6 +90,8 @@ public:
 
     Document* document() const; // ASSERTs if document no longer exists.
 
+    const Document* hostingDocument() const override;
+
     AudioDestinationNode* destination() { return m_destinationNode.get(); }
     size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
     double currentTime() const { return m_destinationNode->currentTime(); }
index f640b7c..445784b 100644 (file)
@@ -3,7 +3,7 @@
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
  *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 #include "PageGroup.h"
 #include "PageTransitionEvent.h"
 #include "PlatformLocale.h"
+#include "PlatformMediaSessionManager.h"
 #include "PlatformStrategies.h"
 #include "PlugInsResources.h"
 #include "PluginDocument.h"
@@ -632,6 +633,8 @@ Document::~Document()
     if (m_cachedResourceLoader->document() == this)
         m_cachedResourceLoader->setDocument(nullptr);
 
+    PlatformMediaSessionManager::sharedManager().stopAllMediaPlaybackForDocument(this);
+    
     // We must call clearRareData() here since a Document class inherits TreeScope
     // as well as Node. See a comment on TreeScope.h for the reason.
     if (hasRareData())
index 9eae862..5832c09 100644 (file)
@@ -147,7 +147,9 @@ public:
     MediaPlayerEnums::MovieLoadType movieLoadType() const;
     
     bool inActiveDocument() const { return m_inActiveDocument; }
-    
+
+    const Document* hostingDocument() const override { return &document(); }
+
 // DOM API
 // error state
     PassRefPtr<MediaError> error() const;
index 001947f..f6c47c9 100644 (file)
@@ -37,6 +37,7 @@
 
 namespace WebCore {
 
+class Document;
 class MediaPlaybackTarget;
 class PlatformMediaSessionClient;
 
@@ -145,6 +146,8 @@ private:
     State m_stateToRestore;
     int m_interruptionCount { 0 };
     bool m_notifyingClient;
+
+    friend class PlatformMediaSessionManager;
 };
 
 class PlatformMediaSessionClient {
@@ -177,6 +180,8 @@ public:
     virtual bool isPlayingToWirelessPlaybackTarget() const { return false; }
     virtual void setShouldPlayToPlaybackTarget(bool) { }
 
+    virtual const Document* hostingDocument() const = 0;
+
 protected:
     virtual ~PlatformMediaSessionClient() { }
 };
index 3293f56..de1d861 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(VIDEO)
 
 #include "AudioSession.h"
+#include "Document.h"
 #include "Logging.h"
 #include "NotImplemented.h"
 #include "PlatformMediaSession.h"
@@ -329,6 +330,22 @@ void PlatformMediaSessionManager::audioOutputDeviceChanged()
     updateSessionState();
 }
 
+void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document* document)
+{
+    Vector<PlatformMediaSession*> sessions = m_sessions;
+    for (auto* session : sessions) {
+        if (session->client().hostingDocument() == document)
+            session->pauseSession();
+    }
+}
+
+void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess()
+{
+    Vector<PlatformMediaSession*> sessions = m_sessions;
+    for (auto* session : sessions)
+        session->pauseSession();
+}
+
 }
 
 #endif
index 2d748a0..01d3b1e 100644 (file)
@@ -36,6 +36,7 @@
 
 namespace WebCore {
 
+class Document;
 class HTMLMediaElement;
 class PlatformMediaSession;
 class RemoteCommandListener;
@@ -56,6 +57,9 @@ public:
     WEBCORE_EXPORT void applicationWillEnterForeground() const;
     WEBCORE_EXPORT void applicationWillEnterBackground() const;
 
+    void stopAllMediaPlaybackForDocument(const Document*);
+    WEBCORE_EXPORT void stopAllMediaPlaybackForProcess();
+
     enum SessionRestrictionFlags {
         NoRestrictions = 0,
         ConcurrentPlaybackNotPermitted = 1 << 0,
index 8cf1814..6a6f4b6 100644 (file)
@@ -1,3 +1,15 @@
+2015-07-06  Brent Fulgham  <bfulgham@apple.com>
+
+        Ensure media playback is stopped during page close
+        https://bugs.webkit.org/show_bug.cgi?id=146554
+        <rdar://problem/18033944>
+
+        Reviewed by Brady Eidson.
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::didClose): Make sure to clean up any running media sessions when
+        the process is being shut down.
+
 2015-07-06  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r186385.
index b4c9e0e..410b8e2 100644 (file)
@@ -82,6 +82,7 @@
 #include <WebCore/Page.h>
 #include <WebCore/PageCache.h>
 #include <WebCore/PageGroup.h>
+#include <WebCore/PlatformMediaSessionManager.h>
 #include <WebCore/ResourceHandle.h>
 #include <WebCore/RuntimeEnabledFeatures.h>
 #include <WebCore/SchemeRegistry.h>
@@ -658,6 +659,9 @@ void WebProcess::didClose(IPC::Connection&)
     MemoryCache::singleton().setDisabled(true);
 #endif    
 
+    // FIXME(146657): This explicit media stop command should not be necessary
+    PlatformMediaSessionManager::sharedManager().stopAllMediaPlaybackForProcess();
+
     // The UI process closed this connection, shut down.
     stopRunLoop();
 }