Chromium Code Reviews| 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; |
| } |