Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(790)

Unified Diff: content/browser/media/session/media_session_impl.cc

Issue 2526533002: Allow MediaSession in iframes to be routed (Closed)
Patch Set: Addressed Anton's comments and updated selection strategy Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 1b5e706c47a32b0167e2306d9c7b7dc3cd5b1a41..04b4353922273179a4fdeffed98634670ab7ab9e 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include "content/browser/media/session/audio_focus_delegate.h"
+#include "content/browser/media/session/media_session_controller.h"
#include "content/browser/media/session/media_session_player_observer.h"
#include "content/browser/media/session/media_session_service_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -25,6 +26,15 @@ namespace {
const double kDefaultVolumeMultiplier = 1.0;
const double kDuckingVolumeMultiplier = 0.2;
+size_t ComputeFrameDepth(RenderFrameHost* rfh) {
+ size_t depth = 0;
+ while (rfh) {
+ ++depth;
+ rfh = rfh->GetParent();
+ }
+ return depth;
+}
+
} // anonymous namespace
using MediaSessionSuspendedSource =
@@ -89,11 +99,6 @@ void MediaSessionImpl::WebContentsDestroyed() {
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSessionImpl::SetMediaSessionService(
- MediaSessionServiceImpl* service) {
- service_ = service;
-}
-
void MediaSessionImpl::AddObserver(MediaSessionObserver* observer) {
observers_.AddObserver(observer);
}
@@ -102,13 +107,18 @@ void MediaSessionImpl::RemoveObserver(MediaSessionObserver* observer) {
observers_.RemoveObserver(observer);
}
-void MediaSessionImpl::SetMetadata(
+void MediaSessionImpl::NotifyMediaSessionMetadataChange(
const base::Optional<MediaMetadata>& metadata) {
- metadata_ = metadata;
for (auto& observer : observers_)
observer.MediaSessionMetadataChanged(metadata);
}
+void MediaSessionImpl::NotifyMediaSessionActionsChange(
+ const std::set<blink::mojom::MediaSessionAction>& actions) {
+ for (auto& observer : observers_)
+ observer.MediaSessionActionsChanged(actions);
+}
+
bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
int player_id,
media::MediaContentType media_content_type) {
@@ -150,8 +160,9 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
normal_players_.clear();
normal_players_.insert(PlayerIdentifier(observer, player_id));
- NotifyAboutStateChange();
+ UpdateRoutedService();
+ NotifyAboutStateChange();
return true;
}
@@ -174,6 +185,7 @@ void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
one_shot_players_.erase(it);
AbandonSystemAudioFocusIfNeeded();
+ UpdateRoutedService();
// The session may become controllable after removing a one-shot player.
// However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
@@ -207,6 +219,7 @@ void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
}
AbandonSystemAudioFocusIfNeeded();
+ UpdateRoutedService();
// The session may become controllable after removing a one-shot player.
// However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
@@ -299,24 +312,6 @@ void MediaSessionImpl::Stop(SuspendType suspend_type) {
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSessionImpl::DidReceiveAction(
- blink::mojom::MediaSessionAction action) {
- if (service_)
- service_->GetClient()->DidReceiveAction(action);
-}
-
-void MediaSessionImpl::OnMediaSessionEnabledAction(
- blink::mojom::MediaSessionAction action) {
- for (auto& observer : observers_)
- observer.MediaSessionEnabledAction(action);
-}
-
-void MediaSessionImpl::OnMediaSessionDisabledAction(
- blink::mojom::MediaSessionAction action) {
- for (auto& observer : observers_)
- observer.MediaSessionDisabledAction(action);
-}
-
void MediaSessionImpl::StartDucking() {
if (is_ducking_)
return;
@@ -470,7 +465,7 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
audio_focus_type_(
AudioFocusManager::AudioFocusType::GainTransientMayDuck),
is_ducking_(false),
- service_(nullptr) {
+ routed_service_(nullptr) {
#if defined(OS_ANDROID)
session_android_.reset(new MediaSessionAndroid(this));
#endif // defined(OS_ANDROID)
@@ -552,4 +547,111 @@ bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
return true;
}
+// MediaSessionService-related methods
+
+void MediaSessionImpl::OnServiceCreated(
+ MediaSessionServiceImpl* service) {
+ services_[service->GetRenderFrameHost()] = service;
+}
+
+void MediaSessionImpl::OnServiceDestroyed(
+ MediaSessionServiceImpl* service) {
+ services_.erase(service->GetRenderFrameHost());
+}
+
+void MediaSessionImpl::OnMediaSessionMetadataChanged(
+ MediaSessionServiceImpl* service) {
+ if (service != routed_service_)
+ return;
+
+ NotifyMediaSessionMetadataChange(routed_service_->metadata());
+}
+
+void MediaSessionImpl::OnMediaSessionActionsChanged(
+ MediaSessionServiceImpl* service) {
+ if (service != routed_service_)
+ return;
+
+ NotifyMediaSessionActionsChange(routed_service_->actions());
+}
+
+void MediaSessionImpl::DidReceiveAction(
+ blink::mojom::MediaSessionAction action) {
+ if (!routed_service_)
+ return;
+
+ routed_service_->GetClient()->DidReceiveAction(action);
+}
+
+bool MediaSessionImpl::IsServiceActiveForRenderFrameHost(
+ RenderFrameHost* rfh) {
+ if (!services_.count(rfh))
+ return false;
+
+ return services_[rfh]->metadata().has_value() ||
+ !services_[rfh]->actions().empty();
+}
+
+void MediaSessionImpl::UpdateRoutedService() {
+ MediaSessionServiceImpl* new_service = ComputeServiceForRouting();
+ if (new_service == routed_service_)
+ return;
+
+ routed_service_ = new_service;
+ if (routed_service_) {
+ NotifyMediaSessionMetadataChange(routed_service_->metadata());
+ NotifyMediaSessionActionsChange(routed_service_->actions());
+ } else {
+ NotifyMediaSessionMetadataChange(base::nullopt);
+ NotifyMediaSessionActionsChange(
+ std::set<blink::mojom::MediaSessionAction>());
+ }
+}
+
+MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() {
+ // The service selection strategy is: Select a frame that has a playing/paused
whywhat 2016/11/30 22:16:41 is there a test possible for this?
Zhiqiang Zhang (Slow) 2016/12/01 16:34:41 Added unit tests.
+ // player and has a corresponding MediaSessionService and return the
+ // corresponding MediaSessionService. If multiple frames satisfy the criteria,
+ // prefer the top-most frame.
+ MediaSessionServiceImpl* best_service = nullptr;
+ size_t min_depth = std::numeric_limits<size_t>::max();
+
+ for (const auto& player : normal_players_) {
whywhat 2016/11/30 22:16:41 I wonder if there's a potential bottleneck - ideal
Zhiqiang Zhang (Slow) 2016/12/01 16:34:41 Done. Now we collect all the frames first and then
+ ComputeServiceForRoutingInternal(
+ player.observer, &best_service, &min_depth);
+ }
+
+ for (const auto& player : one_shot_players_) {
+ ComputeServiceForRoutingInternal(
+ player.observer, &best_service, &min_depth);
+ }
+
+ for (const auto& player : pepper_players_) {
+ ComputeServiceForRoutingInternal(
+ player.observer, &best_service, &min_depth);
+ }
+
+ return best_service;
+}
+
+void MediaSessionImpl::ComputeServiceForRoutingInternal(
+ MediaSessionPlayerObserver* player_observer,
+ MediaSessionServiceImpl** best_service,
+ size_t* min_depth) {
+ MediaSessionController* controller =
+ static_cast<MediaSessionController*>(player_observer);
whywhat 2016/11/30 22:16:41 nit: could we avoid this assumption that MSC is th
Zhiqiang Zhang (Slow) 2016/12/01 16:34:41 Added a `GetRenderFrameHost()` method to MediaSess
+ if (!controller)
+ return;
+
+ RenderFrameHost* rfh = controller->GetFrameOrientedId().first;
+ if (!services_.count(rfh))
+ return;
+
+ size_t depth = ComputeFrameDepth(rfh);
+ if (depth < *min_depth) {
+ *best_service = services_[rfh];
+ *min_depth = depth;
+ }
+}
+
} // namespace content
« no previous file with comments | « content/browser/media/session/media_session_impl.h ('k') | content/browser/media/session/media_session_service_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698