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 4ff3491de482542efe4781d46d153e896df8eef4..436a160bcfba194feaf42976b9868834afa0b33b 100644 |
--- a/content/browser/media/session/audio_focus_manager.cc |
+++ b/content/browser/media/session/audio_focus_manager.cc |
@@ -4,6 +4,7 @@ |
#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" |
@@ -14,13 +15,18 @@ AudioFocusManager::AudioFocusEntry::AudioFocusEntry( |
AudioFocusManager* audio_focus_manager, |
AudioFocusType type) |
: WebContentsObserver(web_contents), |
- audio_focus_manager_(audio_focus_manager) {} |
+ audio_focus_manager_(audio_focus_manager), |
+ type_(type) {} |
AudioFocusManager::AudioFocusType |
AudioFocusManager::AudioFocusEntry::type() const { |
return type_; |
} |
+MediaSession* AudioFocusManager::AudioFocusEntry::ToMediaSession() const { |
+ return MediaSession::Get(web_contents()); |
+} |
+ |
void AudioFocusManager::AudioFocusEntry::WebContentsDestroyed() { |
audio_focus_manager_->OnWebContentsDestroyed(web_contents()); |
// |this| will be destroyed now. |
@@ -35,80 +41,76 @@ void AudioFocusManager::RequestAudioFocus(MediaSession* media_session, |
AudioFocusType type) { |
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(); |
+ if (!audio_focus_stack_.empty() && |
+ audio_focus_stack_.back()->web_contents() == web_contents && |
+ audio_focus_stack_.back()->type() == type && |
Zhiqiang Zhang (Slow)
2016/09/08 14:18:26
Maybe we could access |audio_focus_type_| from Med
|
+ audio_focus_stack_.back()->ToMediaSession()->IsActive()) { |
return; |
} |
- DCHECK(type == AudioFocusType::Gain); |
- RequestAudioFocusGain(web_contents); |
-} |
- |
-void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) { |
- AbandonAudioFocusInternal(media_session->web_contents()); |
-} |
- |
-AudioFocusManager::AudioFocusManager() = default; |
- |
-AudioFocusManager::~AudioFocusManager() = default; |
- |
-void AudioFocusManager::RequestAudioFocusGain(WebContents* web_contents) { |
- MaybeRemoveTransientEntry(web_contents); |
- |
- if (focus_entry_) { |
- if (focus_entry_->web_contents() == web_contents) |
- return; |
+ MaybeRemoveFocusEntry(web_contents); |
- MediaSession* other_session = |
- MediaSession::Get(focus_entry_->web_contents()); |
- if (other_session->IsActive()) |
- other_session->Suspend(MediaSession::SuspendType::SYSTEM); |
+ if (type == AudioFocusType::GainTransientMayDuck) { |
+ for (const auto& focus_entry : audio_focus_stack_) { |
+ focus_entry->ToMediaSession()->StartDucking(); |
+ } |
+ } else { |
+ for (const auto& focus_entry : audio_focus_stack_) { |
Zhiqiang Zhang (Slow)
2016/09/08 14:18:26
These for-loops visiting the full stack might be s
|
+ MediaSession* session = focus_entry->ToMediaSession(); |
+ if (session->IsActive()) |
+ session->Suspend(MediaSession::SuspendType::SYSTEM); |
+ session->DisallowPepperOverrideDucking(); |
+ } |
} |
- focus_entry_.reset( |
- new AudioFocusEntry(web_contents, this, AudioFocusType::Gain)); |
- MaybeStartDucking(); |
+ audio_focus_stack_.push_back(base::MakeUnique<AudioFocusEntry>( |
+ web_contents, this, type)); |
+ audio_focus_stack_.back()->ToMediaSession()->StopDucking(); |
+ audio_focus_stack_.back()->ToMediaSession()->AllowPepperOverrideDucking(); |
} |
-void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) { |
- AbandonAudioFocusInternal(web_contents); |
-} |
- |
-void AudioFocusManager::AbandonAudioFocusInternal(WebContents* web_contents) { |
- MaybeRemoveTransientEntry(web_contents); |
- MaybeRemoveFocusEntry(web_contents); |
-} |
+void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) { |
+ WebContents* web_contents = media_session->web_contents(); |
-void AudioFocusManager::MaybeStartDucking() const { |
- if (TransientMayDuckEntriesCount() != 1 || !focus_entry_) |
+ if (audio_focus_stack_.back()->web_contents() != web_contents) { |
+ MaybeRemoveFocusEntry(web_contents); |
return; |
+ } |
- MediaSession::Get(focus_entry_->web_contents())->StartDucking(); |
-} |
- |
-void AudioFocusManager::MaybeStopDucking() const { |
- if (TransientMayDuckEntriesCount() != 0 || !focus_entry_) |
+ audio_focus_stack_.back()->ToMediaSession()->DisallowPepperOverrideDucking(); |
+ audio_focus_stack_.pop_back(); |
+ if (audio_focus_stack_.empty()) |
return; |
- MediaSession::Get(focus_entry_->web_contents())->StopDucking(); |
+ // Allow the top-most MediaSession having Pepper to unduck pepper event it's |
+ // not active. |
+ for (auto iter = audio_focus_stack_.rbegin(); |
+ iter != audio_focus_stack_.rend(); ++iter) { |
+ if ((*iter)->ToMediaSession()->HasPepper()) { |
+ (*iter)->ToMediaSession()->AllowPepperOverrideDucking(); |
+ break; |
+ } |
+ } |
+ // Only try to unduck the new MediaSession on top. The session might be still |
+ // inactive but it will not be resumed (so it does surprise the user). |
+ audio_focus_stack_.back()->ToMediaSession()->StopDucking(); |
} |
-int AudioFocusManager::TransientMayDuckEntriesCount() const { |
- return transient_entries_.size(); |
-} |
+AudioFocusManager::AudioFocusManager() = default; |
-void AudioFocusManager::MaybeRemoveTransientEntry(WebContents* web_contents) { |
- transient_entries_.erase(web_contents); |
- MaybeStopDucking(); |
+AudioFocusManager::~AudioFocusManager() = default; |
+ |
+void AudioFocusManager::OnWebContentsDestroyed(WebContents* web_contents) { |
+ AbandonAudioFocus(MediaSession::Get(web_contents)); |
} |
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(); |
+ for (auto iter = audio_focus_stack_.begin(); iter != audio_focus_stack_.end(); |
+ ++iter) { |
+ if (web_contents == (*iter)->web_contents()) { |
+ audio_focus_stack_.erase(iter); |
+ return; |
+ } |
} |
} |