Index: content/browser/media/session/media_session_impl.cc |
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc |
index 022efebc1331af527436b75cc650e019644d8266..bb6041d4bb0ec0ea1dd5ec7c3b466e660d488952 100644 |
--- a/content/browser/media/session/media_session_impl.cc |
+++ b/content/browser/media/session/media_session_impl.cc |
@@ -65,6 +65,8 @@ MediaSessionImpl* MediaSessionImpl::Get(WebContents* web_contents) { |
MediaSessionImpl::~MediaSessionImpl() { |
DCHECK(players_.empty()); |
+ DCHECK(pepper_players_.empty()); |
+ DCHECK(one_shot_players_.empty()); |
DCHECK(audio_focus_state_ == State::INACTIVE); |
for (auto& observer : observers_) |
observer.MediaSessionDestroyed(); |
@@ -101,16 +103,13 @@ void MediaSessionImpl::SetMetadata( |
bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, |
int player_id, |
media::MediaContentType media_content_type) { |
- if (media_content_type == media::MediaContentType::Uncontrollable) |
- return true; |
+ if (media_content_type == media::MediaContentType::OneShot) |
+ return AddOneShotPlayer(observer, player_id); |
if (media_content_type == media::MediaContentType::Pepper) |
return AddPepperPlayer(observer, player_id); |
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); |
- // Determine the audio focus type required for playing the new player. |
- // TODO(zqzhang): handle duckable and uncontrollable. |
- // See https://crbug.com/639277. |
AudioFocusManager::AudioFocusType required_audio_focus_type; |
if (media_content_type == media::MediaContentType::Persistent) { |
required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; |
@@ -142,7 +141,7 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, |
players_.clear(); |
players_.insert(PlayerIdentifier(observer, player_id)); |
- UpdateWebContents(); |
+ DispatchStateChange(); |
return true; |
} |
@@ -157,6 +156,16 @@ void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer, |
if (it != pepper_players_.end()) |
pepper_players_.erase(it); |
+ it = one_shot_players_.find(PlayerIdentifier(observer, player_id)); |
+ if (it != one_shot_players_.end()) { |
+ one_shot_players_.erase(it); |
+ |
+ // The session may become controllable after all one-shot players are |
+ // removed. |
+ if (one_shot_players_.empty()) |
+ DispatchStateChange(); |
+ } |
+ |
AbandonSystemAudioFocusIfNeeded(); |
} |
@@ -175,6 +184,18 @@ void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) { |
++it; |
} |
+ for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) { |
+ if (it->observer == observer) |
+ one_shot_players_.erase(it++); |
+ else |
+ ++it; |
+ |
+ // The session may become controllable after all one-shot players are |
+ // removed. |
+ if (one_shot_players_.empty()) |
+ DispatchStateChange(); |
+ } |
+ |
AbandonSystemAudioFocusIfNeeded(); |
} |
@@ -191,7 +212,8 @@ void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer, |
// to this session (e.g. a silent video) is paused. MediaSessionImpl |
// should ignore the paused player for this case. |
if (!players_.count(PlayerIdentifier(observer, player_id)) && |
- !pepper_players_.count(PlayerIdentifier(observer, player_id))) { |
+ !pepper_players_.count(PlayerIdentifier(observer, player_id)) && |
+ !one_shot_players_.count(PlayerIdentifier(observer, player_id))) { |
return; |
} |
@@ -203,6 +225,13 @@ void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer, |
return; |
} |
+ // If the player is a one-shot player, just remove it since it is not expected |
+ // to resume a one-shot player via resuming MediaSession. |
+ if (one_shot_players_.count(PlayerIdentifier(observer, player_id))) { |
+ RemovePlayer(observer, player_id); |
+ return; |
+ } |
+ |
// Otherwise, suspend the session. |
DCHECK(!IsSuspended()); |
OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); |
@@ -294,9 +323,11 @@ bool MediaSessionImpl::IsSuspended() const { |
bool MediaSessionImpl::IsControllable() const { |
// Only media session having focus Gain can be controllable unless it is |
- // inactive. |
+ // inactive. Also, the session will be uncontrollable if it contains one-shot |
+ // players. |
return audio_focus_state_ != State::INACTIVE && |
- audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain; |
+ audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain && |
+ (one_shot_players_.empty()); |
} |
bool MediaSessionImpl::HasPepper() const { |
@@ -324,6 +355,8 @@ MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() { |
void MediaSessionImpl::RemoveAllPlayersForTest() { |
players_.clear(); |
+ pepper_players_.clear(); |
+ one_shot_players_.clear(); |
whywhat
2016/11/03 14:32:17
nit: I feel there's more code duplication here w.r
Zhiqiang Zhang (Slow)
2016/11/04 14:10:54
Yeah, I feel this too. But as pepper_players_ is l
|
AbandonSystemAudioFocusIfNeeded(); |
} |
@@ -335,6 +368,9 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type, |
// UI suspend cannot use State::INACTIVE. |
DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED); |
+ if (!one_shot_players_.empty()) |
+ return; |
+ |
if (audio_focus_state_ != State::ACTIVE) |
return; |
@@ -376,7 +412,7 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type, |
for (const auto& it : pepper_players_) |
it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); |
- UpdateWebContents(); |
+ DispatchStateChange(); |
} |
void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) { |
@@ -391,7 +427,7 @@ void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) { |
for (const auto& it : pepper_players_) |
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); |
- UpdateWebContents(); |
+ DispatchStateChange(); |
} |
MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) |
@@ -423,16 +459,16 @@ bool MediaSessionImpl::RequestSystemAudioFocus( |
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() { |
if (audio_focus_state_ == State::INACTIVE || !players_.empty() || |
- !pepper_players_.empty()) { |
+ !pepper_players_.empty() || !one_shot_players_.empty()) { |
return; |
} |
delegate_->AbandonAudioFocus(); |
SetAudioFocusState(State::INACTIVE); |
- UpdateWebContents(); |
+ DispatchStateChange(); |
} |
-void MediaSessionImpl::UpdateWebContents() { |
+void MediaSessionImpl::DispatchStateChange() { |
media_session_state_listeners_.Notify(audio_focus_state_); |
for (auto& observer : observers_) |
observer.MediaSessionStateChanged(IsControllable(), IsSuspended()); |
@@ -466,6 +502,19 @@ bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer, |
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); |
+ DispatchStateChange(); |
+ return true; |
+} |
+ |
+bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer, |
+ int player_id) { |
+ // Don't check whether the request is successful or not. One-shot players |
+ // should play uninterrupted. |
whywhat
2016/11/03 14:32:16
that means we'd play them even if the user is in t
Zhiqiang Zhang (Slow)
2016/11/04 14:10:54
OK, let's give a chance for the players to respond
|
+ RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain); |
+ |
+ one_shot_players_.insert(PlayerIdentifier(observer, player_id)); |
+ |
+ DispatchStateChange(); |
return true; |
} |