Multiple videos (with audios) with autoplay & playinline not working. Only one video...
[WebKit-https.git] / Source / WebCore / platform / audio / PlatformMediaSessionManager.cpp
index b9b079d..426a674 100644 (file)
@@ -59,6 +59,9 @@ void PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary()
 
 PlatformMediaSessionManager::PlatformMediaSessionManager()
     : m_systemSleepListener(PAL::SystemSleepListener::create(*this))
+#if !RELEASE_LOG_DISABLED
+    , m_logger(AggregateLogger::create(this))
+#endif
 {
     resetRestrictions();
 }
@@ -76,21 +79,21 @@ bool PlatformMediaSessionManager::has(PlatformMediaSession::MediaType type) cons
 {
     ASSERT(type >= PlatformMediaSession::None && type <= PlatformMediaSession::MediaStreamCapturingAudio);
 
-    return anyOfSessions([type] (PlatformMediaSession& session, size_t) {
+    return anyOfSessions([type] (auto& session) {
         return session.mediaType() == type;
     });
 }
 
 bool PlatformMediaSessionManager::activeAudioSessionRequired() const
 {
-    return anyOfSessions([] (PlatformMediaSession& session, size_t) {
+    return anyOfSessions([] (auto& session) {
         return session.activeAudioSessionRequired();
     });
 }
 
 bool PlatformMediaSessionManager::canProduceAudio() const
 {
-    return anyOfSessions([] (PlatformMediaSession& session, size_t) {
+    return anyOfSessions([] (auto& session) {
         return session.canProduceAudio();
     });
 }
@@ -100,7 +103,7 @@ int PlatformMediaSessionManager::count(PlatformMediaSession::MediaType type) con
     ASSERT(type >= PlatformMediaSession::None && type <= PlatformMediaSession::MediaStreamCapturingAudio);
 
     int count = 0;
-    for (auto* session : m_sessions) {
+    for (const auto& session : m_sessions) {
         if (session->mediaType() == type)
             ++count;
     }
@@ -110,10 +113,10 @@ int PlatformMediaSessionManager::count(PlatformMediaSession::MediaType type) con
 
 void PlatformMediaSessionManager::beginInterruption(PlatformMediaSession::InterruptionType type)
 {
-    LOG(Media, "PlatformMediaSessionManager::beginInterruption");
+    ALWAYS_LOG(LOGIDENTIFIER);
 
     m_interrupted = true;
-    forEachSession([type] (PlatformMediaSession& session, size_t) {
+    forEachSession([type] (auto& session) {
         session.beginInterruption(type);
     });
     updateSessionState();
@@ -121,19 +124,18 @@ void PlatformMediaSessionManager::beginInterruption(PlatformMediaSession::Interr
 
 void PlatformMediaSessionManager::endInterruption(PlatformMediaSession::EndInterruptionFlags flags)
 {
-    LOG(Media, "PlatformMediaSessionManager::endInterruption");
+    ALWAYS_LOG(LOGIDENTIFIER);
 
     m_interrupted = false;
-    forEachSession([flags] (PlatformMediaSession& session, size_t) {
+    forEachSession([flags] (auto& session) {
         session.endInterruption(flags);
     });
 }
 
 void PlatformMediaSessionManager::addSession(PlatformMediaSession& session)
 {
-    LOG(Media, "PlatformMediaSessionManager::addSession - %p", &session);
-    
-    m_sessions.append(&session);
+    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
+    m_sessions.append(makeWeakPtr(session));
     if (m_interrupted)
         session.setState(PlatformMediaSession::Interrupted);
 
@@ -143,21 +145,22 @@ void PlatformMediaSessionManager::addSession(PlatformMediaSession& session)
     if (!m_audioHardwareListener)
         m_audioHardwareListener = AudioHardwareListener::create(*this);
 
+#if !RELEASE_LOG_DISABLED
+    m_logger->addLogger(session.logger());
+#endif
+
     updateSessionState();
 }
 
 void PlatformMediaSessionManager::removeSession(PlatformMediaSession& session)
 {
-    LOG(Media, "PlatformMediaSessionManager::removeSession - %p", &session);
-    
+    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
+
     size_t index = m_sessions.find(&session);
     if (index == notFound)
         return;
 
-    if (m_iteratingOverSessions)
-        m_sessions.at(index) = nullptr;
-    else
-        m_sessions.remove(index);
+    m_sessions.remove(index);
 
     if (m_sessions.isEmpty() || std::all_of(m_sessions.begin(), m_sessions.end(), std::logical_not<void>())) {
         m_remoteCommandListener = nullptr;
@@ -170,6 +173,10 @@ void PlatformMediaSessionManager::removeSession(PlatformMediaSession& session)
 #endif
     }
 
+#if !RELEASE_LOG_DISABLED
+    m_logger->removeLogger(session.logger());
+#endif
+
     updateSessionState();
 }
 
@@ -193,67 +200,81 @@ PlatformMediaSessionManager::SessionRestrictions PlatformMediaSessionManager::re
 
 bool PlatformMediaSessionManager::sessionWillBeginPlayback(PlatformMediaSession& session)
 {
-    LOG(Media, "PlatformMediaSessionManager::sessionWillBeginPlayback - %p", &session);
-    
     setCurrentSession(session);
 
     PlatformMediaSession::MediaType sessionType = session.mediaType();
     SessionRestrictions restrictions = m_restrictions[sessionType];
-    if (session.state() == PlatformMediaSession::Interrupted && restrictions & InterruptedPlaybackNotPermitted)
+    if (session.state() == PlatformMediaSession::Interrupted && restrictions & InterruptedPlaybackNotPermitted) {
+        ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning false because session.state() is Interrupted, and InterruptedPlaybackNotPermitted");
         return false;
+    }
 
-#if USE(AUDIO_SESSION)
-    if (activeAudioSessionRequired() && !AudioSession::sharedSession().tryToSetActive(true))
+    if (m_processIsSuspended) {
+        ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning false because process is suspended");
         return false;
+    }
 
-    m_becameActive = true;
+#if USE(AUDIO_SESSION)
+    if (activeAudioSessionRequired()) {
+        if (!AudioSession::sharedSession().tryToSetActive(true)) {
+            ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning false failed to set active AudioSession");
+            return false;
+        }
+
+        ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " sucessfully activated AudioSession");
+        m_becameActive = true;
+    }
 #endif
 
     if (m_interrupted)
         endInterruption(PlatformMediaSession::NoFlags);
 
-    forEachSession([&] (PlatformMediaSession& oneSession, size_t) {
-        if (&oneSession == &session)
-            return;
-        if (oneSession.mediaType() == sessionType
-            && restrictions & ConcurrentPlaybackNotPermitted
-            && oneSession.state() == PlatformMediaSession::Playing)
+    if (restrictions & ConcurrentPlaybackNotPermitted) {
+        forEachMatchingSession([&session, sessionType](auto& oneSession) {
+            return &oneSession != &session
+                && oneSession.mediaType() == sessionType
+                && oneSession.state() == PlatformMediaSession::Playing
+                && !oneSession.canPlayConcurrently(session);
+        }, [](auto& oneSession) {
             oneSession.pauseSession();
-    });
-
+        });
+    }
+    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning true");
     return true;
 }
     
 void PlatformMediaSessionManager::sessionWillEndPlayback(PlatformMediaSession& session)
 {
-    LOG(Media, "PlatformMediaSessionManager::sessionWillEndPlayback - %p", &session);
+    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
     
     if (m_sessions.size() < 2)
         return;
     
     size_t pausingSessionIndex = notFound;
     size_t lastPlayingSessionIndex = notFound;
-    anyOfSessions([&] (PlatformMediaSession& oneSession, size_t i) {
+    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
+        const auto& oneSession = *m_sessions[i];
         if (&oneSession == &session) {
             pausingSessionIndex = i;
-            return false;
+            break;
         }
         if (oneSession.state() == PlatformMediaSession::Playing) {
             lastPlayingSessionIndex = i;
-            return false;
+            break;
         }
-        return oneSession.state() != PlatformMediaSession::Playing;
-    });
+        if (oneSession.state() != PlatformMediaSession::Playing)
+            break;
+    }
     if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
         return;
     
     if (pausingSessionIndex > lastPlayingSessionIndex)
         return;
-    
+
     m_sessions.remove(pausingSessionIndex);
-    m_sessions.insert(lastPlayingSessionIndex, &session);
+    m_sessions.append(makeWeakPtr(session));
     
-    LOG(Media, "PlatformMediaSessionManager::sessionWillEndPlayback - session moved from index %zu to %zu", pausingSessionIndex, lastPlayingSessionIndex);
+    ALWAYS_LOG(LOGIDENTIFIER, "session moved from index ", pausingSessionIndex, " to ", lastPlayingSessionIndex);
 }
 
 void PlatformMediaSessionManager::sessionStateChanged(PlatformMediaSession&)
@@ -263,7 +284,7 @@ void PlatformMediaSessionManager::sessionStateChanged(PlatformMediaSession&)
 
 void PlatformMediaSessionManager::setCurrentSession(PlatformMediaSession& session)
 {
-    LOG(Media, "PlatformMediaSessionManager::setCurrentSession - %p", &session);
+    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
     
     if (m_sessions.size() < 2)
         return;
@@ -274,11 +295,11 @@ void PlatformMediaSessionManager::setCurrentSession(PlatformMediaSession& sessio
         return;
 
     m_sessions.remove(index);
-    m_sessions.insert(0, &session);
+    m_sessions.insert(0, makeWeakPtr(session));
     if (m_remoteCommandListener)
         m_remoteCommandListener->updateSupportedCommands();
     
-    LOG(Media, "PlatformMediaSessionManager::setCurrentSession - session moved from index %zu to 0", index);
+    ALWAYS_LOG(LOGIDENTIFIER, "session moved from index ", index, " to 0");
 }
     
 PlatformMediaSession* PlatformMediaSessionManager::currentSession() const
@@ -286,49 +307,41 @@ PlatformMediaSession* PlatformMediaSessionManager::currentSession() const
     if (!m_sessions.size())
         return nullptr;
 
-    return m_sessions[0];
+    return m_sessions[0].get();
 }
 
-Vector<PlatformMediaSession*> PlatformMediaSessionManager::currentSessionsMatching(const WTF::Function<bool(const PlatformMediaSession&)>& filter)
+void PlatformMediaSessionManager::applicationWillBecomeInactive()
 {
-    Vector<PlatformMediaSession*> matchingSessions;
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (filter(session))
-            matchingSessions.append(&session);
-    });
-    return matchingSessions;
-}
-
-void PlatformMediaSessionManager::applicationWillBecomeInactive() const
-{
-    LOG(Media, "PlatformMediaSessionManager::applicationWillBecomeInactive");
+    ALWAYS_LOG(LOGIDENTIFIER);
 
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted)
-            session.beginInterruption(PlatformMediaSession::ProcessInactive);
+    forEachMatchingSession([&](auto& session) {
+        return m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted;
+    }, [](auto& session) {
+        session.beginInterruption(PlatformMediaSession::ProcessInactive);
     });
 }
 
-void PlatformMediaSessionManager::applicationDidBecomeActive() const
+void PlatformMediaSessionManager::applicationDidBecomeActive()
 {
-    LOG(Media, "PlatformMediaSessionManager::applicationDidBecomeActive");
+    ALWAYS_LOG(LOGIDENTIFIER);
 
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted)
-            session.endInterruption(PlatformMediaSession::MayResumePlaying);
+    forEachMatchingSession([&](auto& session) {
+        return m_restrictions[session.mediaType()] & InactiveProcessPlaybackRestricted;
+    }, [](auto& session) {
+        session.endInterruption(PlatformMediaSession::MayResumePlaying);
     });
 }
 
-void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUnderLock) const
+void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUnderLock)
 {
-    LOG(Media, "PlatformMediaSessionManager::applicationDidEnterBackground - suspendedUnderLock(%d)", suspendedUnderLock);
+    ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock);
 
     if (m_isApplicationInBackground)
         return;
 
     m_isApplicationInBackground = true;
 
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
+    forEachSession([&] (auto& session) {
         if (suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted)
             session.beginInterruption(PlatformMediaSession::SuspendedUnderLock);
         else if (m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted)
@@ -336,21 +349,52 @@ void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUn
     });
 }
 
-void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedUnderLock) const
+void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedUnderLock)
 {
-    LOG(Media, "PlatformMediaSessionManager::applicationWillEnterForeground - suspendedUnderLock(%d)", suspendedUnderLock);
+    ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock);
 
     if (!m_isApplicationInBackground)
         return;
 
     m_isApplicationInBackground = false;
 
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if ((suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted) || m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted)
-            session.endInterruption(PlatformMediaSession::MayResumePlaying);
+    forEachMatchingSession([&](auto& session) {
+        return (suspendedUnderLock && m_restrictions[session.mediaType()] & SuspendedUnderLockPlaybackRestricted) || m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted;
+    }, [](auto& session) {
+        session.endInterruption(PlatformMediaSession::MayResumePlaying);
     });
 }
 
+void PlatformMediaSessionManager::processWillSuspend()
+{
+    if (m_processIsSuspended)
+        return;
+    m_processIsSuspended = true;
+
+#if USE(AUDIO_SESSION)
+    if (m_becameActive && shouldDeactivateAudioSession()) {
+        AudioSession::sharedSession().tryToSetActive(false);
+        ALWAYS_LOG(LOGIDENTIFIER, "tried to set inactive AudioSession");
+        m_becameActive = false;
+    }
+#endif
+}
+
+void PlatformMediaSessionManager::processDidResume()
+{
+    if (!m_processIsSuspended)
+        return;
+    m_processIsSuspended = false;
+
+#if USE(AUDIO_SESSION)
+    if (!m_becameActive && activeAudioSessionRequired()) {
+        m_becameActive = AudioSession::sharedSession().tryToSetActive(true);
+        ALWAYS_LOG(LOGIDENTIFIER, "tried to set active AudioSession, ", m_becameActive ? "succeeded" : "failed");
+    }
+#endif
+}
+
+
 void PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession& session)
 {
     if (!m_isApplicationInBackground || !(m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted))
@@ -386,7 +430,7 @@ void PlatformMediaSessionManager::systemWillSleep()
     if (m_interrupted)
         return;
 
-    forEachSession([] (PlatformMediaSession& session, size_t) {
+    forEachSession([] (auto& session) {
         session.beginInterruption(PlatformMediaSession::SystemSleep);
     });
 }
@@ -396,7 +440,7 @@ void PlatformMediaSessionManager::systemDidWake()
     if (m_interrupted)
         return;
 
-    forEachSession([] (PlatformMediaSession& session, size_t) {
+    forEachSession([] (auto& session) {
         session.endInterruption(PlatformMediaSession::MayResumePlaying);
     });
 }
@@ -406,91 +450,91 @@ void PlatformMediaSessionManager::audioOutputDeviceChanged()
     updateSessionState();
 }
 
-void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document* document)
+void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document& document)
 {
-    forEachSession([document] (PlatformMediaSession& session, size_t) {
-        if (session.client().hostingDocument() == document)
-            session.pauseSession();
+    forEachDocumentSession(document, [](auto& session) {
+        session.pauseSession();
     });
 }
 
 void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess()
 {
-    forEachSession([] (PlatformMediaSession& session, size_t) {
+    forEachSession([] (auto& session) {
         session.stopSession();
     });
 }
 
 void PlatformMediaSessionManager::suspendAllMediaPlaybackForDocument(const Document& document)
 {
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (session.client().hostingDocument() == &document)
-            session.beginInterruption(PlatformMediaSession::PlaybackSuspended);
+    forEachDocumentSession(document, [](auto& session) {
+        session.beginInterruption(PlatformMediaSession::PlaybackSuspended);
     });
 }
 
 void PlatformMediaSessionManager::resumeAllMediaPlaybackForDocument(const Document& document)
 {
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (session.client().hostingDocument() == &document)
-            session.endInterruption(PlatformMediaSession::MayResumePlaying);
+    forEachDocumentSession(document, [](auto& session) {
+        session.endInterruption(PlatformMediaSession::MayResumePlaying);
     });
 }
 
 void PlatformMediaSessionManager::suspendAllMediaBufferingForDocument(const Document& document)
 {
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (session.client().hostingDocument() == &document)
-            session.suspendBuffering();
+    forEachDocumentSession(document, [](auto& session) {
+        session.suspendBuffering();
     });
 }
 
 void PlatformMediaSessionManager::resumeAllMediaBufferingForDocument(const Document& document)
 {
-    forEachSession([&] (PlatformMediaSession& session, size_t) {
-        if (session.client().hostingDocument() == &document)
-            session.resumeBuffering();
+    forEachDocumentSession(document, [](auto& session) {
+        session.resumeBuffering();
     });
 }
 
-void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&, size_t)>& predicate) const
+Vector<WeakPtr<PlatformMediaSession>> PlatformMediaSessionManager::sessionsMatching(const WTF::Function<bool(const PlatformMediaSession&)>& filter) const
 {
-    ++m_iteratingOverSessions;
-
-    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
-        auto session = m_sessions[i];
-        if (!session)
-            continue;
-        predicate(*session, i);
+    Vector<WeakPtr<PlatformMediaSession>> matchingSessions;
+    for (auto& session : m_sessions) {
+        if (filter(*session))
+            matchingSessions.append(session);
     }
-
-    --m_iteratingOverSessions;
-    if (!m_iteratingOverSessions)
-        m_sessions.removeAll(nullptr);
+    return matchingSessions;
 }
 
-PlatformMediaSession* PlatformMediaSessionManager::findSession(const Function<bool(PlatformMediaSession&, size_t)>& predicate) const
+void PlatformMediaSessionManager::forEachMatchingSession(const Function<bool(const PlatformMediaSession&)>& predicate, const Function<void(PlatformMediaSession&)>& callback)
 {
-    ++m_iteratingOverSessions;
-
-    PlatformMediaSession* foundSession = nullptr;
-    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
-        auto session = m_sessions[i];
-        if (!session)
-            continue;
+    for (auto& session : sessionsMatching(predicate)) {
+        ASSERT(session);
+        if (session)
+            callback(*session);
+    }
+}
 
-        if (!predicate(*session, i))
-            continue;
+void PlatformMediaSessionManager::forEachDocumentSession(const Document& document, const Function<void(PlatformMediaSession&)>& callback)
+{
+    forEachMatchingSession([&document](auto& session) {
+        return session.client().hostingDocument() == &document;
+    }, [&callback](auto& session) {
+        callback(session);
+    });
+}
 
-        foundSession = session;
-        break;
+void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&)>& callback)
+{
+    auto sessions = m_sessions;
+    for (auto& session : sessions) {
+        ASSERT(session);
+        if (session)
+            callback(*session);
     }
+}
 
-    --m_iteratingOverSessions;
-    if (!m_iteratingOverSessions)
-        m_sessions.removeAll(nullptr);
-
-    return foundSession;
+bool PlatformMediaSessionManager::anyOfSessions(const Function<bool(const PlatformMediaSession&)>& predicate) const
+{
+    return WTF::anyOf(m_sessions, [&predicate](const auto& session) {
+        return predicate(*session);
+    });
 }
 
 static bool& deactivateAudioSession()
@@ -518,4 +562,11 @@ void PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary()
 
 #endif // ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
 
+#if !RELEASE_LOG_DISABLED
+WTFLogChannel& PlatformMediaSessionManager::logChannel() const
+{
+    return LogMedia;
+}
+#endif
+
 } // namespace WebCore