| Index: content/browser/media/session/audio_focus_manager.cc
|
| diff --git a/content/browser/media/session/audio_focus_manager.cc b/content/browser/media/session/audio_focus_manager.cc
|
| index cad3c5e292356e3b977cf00304d58d56dadd6520..4ff3491de482542efe4781d46d153e896df8eef4 100644
|
| --- a/content/browser/media/session/audio_focus_manager.cc
|
| +++ b/content/browser/media/session/audio_focus_manager.cc
|
| @@ -4,11 +4,27 @@
|
|
|
| #include "content/browser/media/session/audio_focus_manager.h"
|
|
|
| -#include "base/memory/ptr_util.h"
|
| #include "content/browser/media/session/media_session.h"
|
| #include "content/public/browser/web_contents.h"
|
|
|
| namespace content {
|
| +
|
| +AudioFocusManager::AudioFocusEntry::AudioFocusEntry(
|
| + WebContents* web_contents,
|
| + AudioFocusManager* audio_focus_manager,
|
| + AudioFocusType type)
|
| + : WebContentsObserver(web_contents),
|
| + audio_focus_manager_(audio_focus_manager) {}
|
| +
|
| +AudioFocusManager::AudioFocusType
|
| +AudioFocusManager::AudioFocusEntry::type() const {
|
| + return type_;
|
| +}
|
| +
|
| +void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() {
|
| + audio_focus_manager_->OnWebContentsDestroyed(web_contents());
|
| + // |this| will be destroyed now.
|
| +}
|
|
|
| // static
|
| AudioFocusManager* AudioFocusManager::GetInstance() {
|
| @@ -17,77 +33,83 @@
|
|
|
| void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
|
| AudioFocusType type) {
|
| - if (!audio_focus_stack_.empty() &&
|
| - audio_focus_stack_.back() == media_session &&
|
| - audio_focus_stack_.back()->audio_focus_type() == type &&
|
| - audio_focus_stack_.back()->IsActive()) {
|
| - // Early returning if |media_session| is already on top (has focus) and is
|
| - // active.
|
| + WebContents* web_contents = media_session->web_contents();
|
| +
|
| + if (type == AudioFocusType::GainTransientMayDuck) {
|
| + MaybeRemoveFocusEntry(web_contents);
|
| + transient_entries_[web_contents].reset(
|
| + new AudioFocusEntry(web_contents, this, type));
|
| + MaybeStartDucking();
|
| return;
|
| }
|
|
|
| - MaybeRemoveFocusEntry(media_session);
|
| -
|
| - // TODO(zqzhang): It seems like MediaSession is exposed to AudioFocusManager
|
| - // too much. Maybe it's better to do some abstraction and refactoring to clean
|
| - // up the relation between AudioFocusManager and MediaSession.
|
| - // See https://crbug.com/651069
|
| - if (type == AudioFocusType::GainTransientMayDuck) {
|
| - for (const auto old_session : audio_focus_stack_) {
|
| - old_session->StartDucking();
|
| - }
|
| - } else {
|
| - for (const auto old_session : audio_focus_stack_) {
|
| - if (old_session->IsActive()) {
|
| - if (old_session->HasPepper())
|
| - old_session->StartDucking();
|
| - else
|
| - old_session->Suspend(MediaSession::SuspendType::SYSTEM);
|
| - }
|
| - }
|
| - }
|
| -
|
| - audio_focus_stack_.push_back(media_session);
|
| - audio_focus_stack_.back()->StopDucking();
|
| + DCHECK(type == AudioFocusType::Gain);
|
| + RequestAudioFocusGain(web_contents);
|
| }
|
|
|
| void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
|
| - if (audio_focus_stack_.empty())
|
| - return;
|
| -
|
| - if (audio_focus_stack_.back() != media_session) {
|
| - MaybeRemoveFocusEntry(media_session);
|
| - return;
|
| - }
|
| -
|
| - audio_focus_stack_.pop_back();
|
| - if (audio_focus_stack_.empty())
|
| - return;
|
| -
|
| - // Allow the top-most MediaSession having Pepper to unduck pepper even if it's
|
| - // not active.
|
| - for (auto iter = audio_focus_stack_.rbegin();
|
| - iter != audio_focus_stack_.rend(); ++iter) {
|
| - if (!(*iter)->HasPepper())
|
| - continue;
|
| -
|
| - MediaSession* pepper_session = *iter;
|
| - pepper_session->StopDucking();
|
| - MaybeRemoveFocusEntry(pepper_session);
|
| - audio_focus_stack_.push_back(pepper_session);
|
| - return;
|
| - }
|
| - // Only try to unduck the new MediaSession on top. The session might be still
|
| - // inactive but it will not be resumed (so it doesn't surprise the user).
|
| - audio_focus_stack_.back()->StopDucking();
|
| + AbandonAudioFocusInternal(media_session->web_contents());
|
| }
|
|
|
| AudioFocusManager::AudioFocusManager() = default;
|
|
|
| AudioFocusManager::~AudioFocusManager() = default;
|
|
|
| -void AudioFocusManager::MaybeRemoveFocusEntry(MediaSession* media_session) {
|
| - audio_focus_stack_.remove(media_session);
|
| +void AudioFocusManager::RequestAudioFocusGain(WebContents* web_contents) {
|
| + MaybeRemoveTransientEntry(web_contents);
|
| +
|
| + if (focus_entry_) {
|
| + if (focus_entry_->web_contents() == web_contents)
|
| + return;
|
| +
|
| + MediaSession* other_session =
|
| + MediaSession::Get(focus_entry_->web_contents());
|
| + if (other_session->IsActive())
|
| + other_session->Suspend(MediaSession::SuspendType::SYSTEM);
|
| + }
|
| +
|
| + focus_entry_.reset(
|
| + new AudioFocusEntry(web_contents, this, AudioFocusType::Gain));
|
| + MaybeStartDucking();
|
| +}
|
| +
|
| +void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) {
|
| + AbandonAudioFocusInternal(web_contents);
|
| +}
|
| +
|
| +void AudioFocusManager::AbandonAudioFocusInternal(WebContents* web_contents) {
|
| + MaybeRemoveTransientEntry(web_contents);
|
| + MaybeRemoveFocusEntry(web_contents);
|
| +}
|
| +
|
| +void AudioFocusManager::MaybeStartDucking() const {
|
| + if (TransientMayDuckEntriesCount() != 1 || !focus_entry_)
|
| + return;
|
| +
|
| + MediaSession::Get(focus_entry_->web_contents())->StartDucking();
|
| +}
|
| +
|
| +void AudioFocusManager::MaybeStopDucking() const {
|
| + if (TransientMayDuckEntriesCount() != 0 || !focus_entry_)
|
| + return;
|
| +
|
| + MediaSession::Get(focus_entry_->web_contents())->StopDucking();
|
| +}
|
| +
|
| +int AudioFocusManager::TransientMayDuckEntriesCount() const {
|
| + return transient_entries_.size();
|
| +}
|
| +
|
| +void AudioFocusManager::MaybeRemoveTransientEntry(WebContents* web_contents) {
|
| + transient_entries_.erase(web_contents);
|
| + MaybeStopDucking();
|
| +}
|
| +
|
| +void AudioFocusManager::MaybeRemoveFocusEntry(WebContents* web_contents) {
|
| + if (focus_entry_ && focus_entry_->web_contents() == web_contents) {
|
| + MediaSession::Get(focus_entry_->web_contents())->StopDucking();
|
| + focus_entry_.reset();
|
| + }
|
| }
|
|
|
| } // namespace content
|
|
|