Changeset 207688 in webkit


Ignore:
Timestamp:
Oct 21, 2016 11:37:47 AM (8 years ago)
Author:
jer.noble@apple.com
Message:

WebCore::PlatformMediaSession::stopSession + 13
https://bugs.webkit.org/show_bug.cgi?id=163799

Reviewed by Eric Carlson.

Because m_sessions can be mutated by removeSession() while iterating over m_sessions, and because
PlatformMediaSessions are not refcounted, it is not enough to copy m_sessions into a copied Vector
before iterating. Instead, wrap iteration of m_sessions in a convenience function, which sets an
iteration counter which, when cleared, removes all null entries from m_session. In parallel, modify
removeSession() to check this iteration counter, and replace the session with a null value rather
than mutating the m_sessions vector itself.

  • platform/audio/PlatformMediaSessionManager.cpp:

(WebCore::PlatformMediaSessionManager::has):
(WebCore::PlatformMediaSessionManager::activeAudioSessionRequired):
(WebCore::PlatformMediaSessionManager::canProduceAudio):
(WebCore::PlatformMediaSessionManager::removeSession):
(WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback):
(WebCore::PlatformMediaSessionManager::sessionWillEndPlayback):
(WebCore::PlatformMediaSessionManager::currentSessionsMatching):
(WebCore::PlatformMediaSessionManager::applicationWillEnterBackground):
(WebCore::PlatformMediaSessionManager::applicationDidEnterForeground):
(WebCore::PlatformMediaSessionManager::systemWillSleep):
(WebCore::PlatformMediaSessionManager::systemDidWake):
(WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForDocument):
(WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess):
(WebCore::PlatformMediaSessionManager::forEachSession):
(WebCore::PlatformMediaSessionManager::anyOfSessions):

  • platform/audio/PlatformMediaSessionManager.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r207687 r207688  
     12016-10-21  Jer Noble  <jer.noble@apple.com>
     2
     3        WebCore::PlatformMediaSession::stopSession + 13
     4        https://bugs.webkit.org/show_bug.cgi?id=163799
     5
     6        Reviewed by Eric Carlson.
     7
     8        Because m_sessions can be mutated by removeSession() while iterating over m_sessions, and because
     9        PlatformMediaSessions are not refcounted, it is not enough to copy m_sessions into a copied Vector
     10        before iterating. Instead, wrap iteration of m_sessions in a convenience function, which sets an
     11        iteration counter which, when cleared, removes all null entries from m_session. In parallel, modify
     12        removeSession() to check this iteration counter, and replace the session with a null value rather
     13        than mutating the m_sessions vector itself.
     14
     15        * platform/audio/PlatformMediaSessionManager.cpp:
     16        (WebCore::PlatformMediaSessionManager::has):
     17        (WebCore::PlatformMediaSessionManager::activeAudioSessionRequired):
     18        (WebCore::PlatformMediaSessionManager::canProduceAudio):
     19        (WebCore::PlatformMediaSessionManager::removeSession):
     20        (WebCore::PlatformMediaSessionManager::sessionWillBeginPlayback):
     21        (WebCore::PlatformMediaSessionManager::sessionWillEndPlayback):
     22        (WebCore::PlatformMediaSessionManager::currentSessionsMatching):
     23        (WebCore::PlatformMediaSessionManager::applicationWillEnterBackground):
     24        (WebCore::PlatformMediaSessionManager::applicationDidEnterForeground):
     25        (WebCore::PlatformMediaSessionManager::systemWillSleep):
     26        (WebCore::PlatformMediaSessionManager::systemDidWake):
     27        (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForDocument):
     28        (WebCore::PlatformMediaSessionManager::stopAllMediaPlaybackForProcess):
     29        (WebCore::PlatformMediaSessionManager::forEachSession):
     30        (WebCore::PlatformMediaSessionManager::anyOfSessions):
     31        * platform/audio/PlatformMediaSessionManager.h:
     32
    1332016-10-21  Darin Adler  <darin@apple.com>
    234
  • trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp

    r206315 r207688  
    7878    ASSERT(type >= PlatformMediaSession::None && type <= PlatformMediaSession::WebAudio);
    7979
    80     for (auto* session : m_sessions) {
    81         if (session->mediaType() == type)
    82             return true;
    83     }
    84 
    85     return false;
     80    return anyOfSessions([type] (PlatformMediaSession& session, size_t) {
     81        return session.mediaType() == type;
     82    });
    8683}
    8784
    8885bool PlatformMediaSessionManager::activeAudioSessionRequired() const
    8986{
    90     for (auto* session : m_sessions) {
    91         if (session->activeAudioSessionRequired())
    92             return true;
    93     }
    94    
    95     return false;
     87    return anyOfSessions([] (PlatformMediaSession& session, size_t) {
     88        return session.activeAudioSessionRequired();
     89    });
    9690}
    9791
    9892bool PlatformMediaSessionManager::canProduceAudio() const
    9993{
    100     for (auto* session : m_sessions) {
    101         if (session->canProduceAudio())
    102             return true;
    103     }
    104 
    105     return false;
     94    return anyOfSessions([] (PlatformMediaSession& session, size_t) {
     95        return session.canProduceAudio();
     96    });
    10697}
    10798
     
    164155    if (index == notFound)
    165156        return;
    166    
    167     m_sessions.remove(index);
    168 
    169     if (m_sessions.isEmpty()) {
     157
     158    if (m_iteratingOverSessions)
     159        m_sessions.at(index) = nullptr;
     160    else
     161        m_sessions.remove(index);
     162
     163    if (m_sessions.isEmpty() || std::all_of(m_sessions.begin(), m_sessions.end(), std::logical_not<void>())) {
    170164        m_remoteCommandListener = nullptr;
    171165        m_audioHardwareListener = nullptr;
     
    212206        endInterruption(PlatformMediaSession::NoFlags);
    213207
    214     Vector<PlatformMediaSession*> sessions = m_sessions;
    215     for (auto* oneSession : sessions) {
    216         if (oneSession == &session)
    217             continue;
    218         if (oneSession->mediaType() == sessionType
     208    forEachSession([&] (PlatformMediaSession& oneSession, size_t) {
     209        if (&oneSession == &session)
     210            return;
     211        if (oneSession.mediaType() == sessionType
    219212            && restrictions & ConcurrentPlaybackNotPermitted
    220             && oneSession->state() == PlatformMediaSession::Playing)
    221             oneSession->pauseSession();
    222     }
     213            && oneSession.state() == PlatformMediaSession::Playing)
     214            oneSession.pauseSession();
     215    });
    223216
    224217    updateSessionState();
     
    235228    size_t pausingSessionIndex = notFound;
    236229    size_t lastPlayingSessionIndex = notFound;
    237     for (size_t i = 0; i < m_sessions.size(); ++i) {
    238         PlatformMediaSession* oneSession = m_sessions[i];
    239        
    240         if (oneSession == &session) {
     230    anyOfSessions([&] (PlatformMediaSession& oneSession, size_t i) {
     231        if (&oneSession == &session) {
    241232            pausingSessionIndex = i;
    242             continue;
     233            return false;
    243234        }
    244         if (oneSession->state() == PlatformMediaSession::Playing) {
     235        if (oneSession.state() == PlatformMediaSession::Playing) {
    245236            lastPlayingSessionIndex = i;
    246             continue;
     237            return false;
    247238        }
    248         if (oneSession->state() != PlatformMediaSession::Playing)
    249             break;
    250     }
     239        return oneSession.state() != PlatformMediaSession::Playing;
     240    });
    251241    if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
    252242        return;
     
    292282{
    293283    Vector<PlatformMediaSession*> matchingSessions;
    294     for (auto& session : m_sessions) {
    295         if (filter(*session))
    296             matchingSessions.append(session);
    297     }
     284    forEachSession([&] (PlatformMediaSession& session, size_t) {
     285        if (filter(session))
     286            matchingSessions.append(&session);
     287    });
    298288    return matchingSessions;
    299289}
     
    314304   
    315305    Vector<PlatformMediaSession*> sessions = m_sessions;
    316     for (auto* session : sessions) {
    317         if (m_restrictions[session->mediaType()] & BackgroundProcessPlaybackRestricted)
    318             session->beginInterruption(PlatformMediaSession::EnteringBackground);
    319     }
     306    forEachSession([&] (PlatformMediaSession& session, size_t) {
     307        if (m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted)
     308            session.beginInterruption(PlatformMediaSession::EnteringBackground);
     309    });
    320310}
    321311
     
    330320
    331321    Vector<PlatformMediaSession*> sessions = m_sessions;
    332     for (auto* session : sessions) {
    333         if (m_restrictions[session->mediaType()] & BackgroundProcessPlaybackRestricted)
    334             session->endInterruption(PlatformMediaSession::MayResumePlaying);
    335     }
     322    forEachSession([&] (PlatformMediaSession& session, size_t) {
     323        if (m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted)
     324            session.endInterruption(PlatformMediaSession::MayResumePlaying);
     325    });
    336326}
    337327
     
    377367        return;
    378368
    379     for (auto* session : m_sessions)
    380         session->beginInterruption(PlatformMediaSession::SystemSleep);
     369    forEachSession([] (PlatformMediaSession& session, size_t) {
     370        session.beginInterruption(PlatformMediaSession::SystemSleep);
     371    });
    381372}
    382373
     
    386377        return;
    387378
    388     for (auto* session : m_sessions)
    389         session->endInterruption(PlatformMediaSession::MayResumePlaying);
     379    forEachSession([] (PlatformMediaSession& session, size_t) {
     380        session.endInterruption(PlatformMediaSession::MayResumePlaying);
     381    });
    390382}
    391383
     
    397389void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(const Document* document)
    398390{
    399     Vector<PlatformMediaSession*> sessions = m_sessions;
    400     for (auto* session : sessions) {
    401         if (session->client().hostingDocument() == document)
    402             session->pauseSession();
     391    forEachSession([document] (PlatformMediaSession& session, size_t) {
     392        if (session.client().hostingDocument() == document)
     393            session.pauseSession();
     394    });
     395}
     396
     397void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess()
     398{
     399    forEachSession([] (PlatformMediaSession& session, size_t) {
     400        session.stopSession();
     401    });
     402}
     403
     404void PlatformMediaSessionManager::forEachSession(std::function<void(PlatformMediaSession&, size_t)> func) const
     405{
     406    ++m_iteratingOverSessions;
     407
     408    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
     409        auto session = m_sessions[i];
     410        if (!session)
     411            continue;
     412        func(*session, i);
    403413    }
    404 }
    405 
    406 void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess()
    407 {
    408     Vector<PlatformMediaSession*> sessions = m_sessions;
    409     for (auto* session : sessions)
    410         session->stopSession();
     414
     415    --m_iteratingOverSessions;
     416    if (!m_iteratingOverSessions)
     417        m_sessions.removeAll(nullptr);
     418}
     419
     420bool PlatformMediaSessionManager::anyOfSessions(std::function<bool(PlatformMediaSession&, size_t)> func) const
     421{
     422    ++m_iteratingOverSessions;
     423
     424    bool found = false;
     425    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
     426        auto session = m_sessions[i];
     427        if (!session)
     428            continue;
     429
     430        if (!func(*session, i))
     431            continue;
     432
     433        found = true;
     434        break;
     435    }
     436
     437    --m_iteratingOverSessions;
     438    if (!m_iteratingOverSessions)
     439        m_sessions.removeAll(nullptr);
     440
     441    return found;
    411442}
    412443
  • trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h

    r206771 r207688  
    121121
    122122    void updateSessionState();
     123    void forEachSession(std::function<void(PlatformMediaSession&, size_t)>) const;
     124    bool anyOfSessions(std::function<bool(PlatformMediaSession&, size_t)>) const;
    123125
    124126    // RemoteCommandListenerClient
     
    136138
    137139    SessionRestrictions m_restrictions[PlatformMediaSession::WebAudio + 1];
    138     Vector<PlatformMediaSession*> m_sessions;
     140    mutable Vector<PlatformMediaSession*> m_sessions;
    139141    std::unique_ptr<RemoteCommandListener> m_remoteCommandListener;
    140142    std::unique_ptr<SystemSleepListener> m_systemSleepListener;
     
    149151    mutable bool m_isApplicationInBackground { false };
    150152    bool m_willIgnoreSystemInterruptions { false };
     153    mutable int m_iteratingOverSessions { 0 };
    151154};
    152155
Note: See TracChangeset for help on using the changeset viewer.