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

Unified Diff: content/browser/media/media_web_contents_observer.cc

Issue 1478643002: Refactor media out of WebContentsImpl to MediaWebContentsObserver. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix namespace for cast. Created 5 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/media_web_contents_observer.cc
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index c17a9ff23c32cc3674a1ce1bc44609e58ec7c75f..dc79efa14bbb9145f213da0fb9eeb4d2ec813e71 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -8,6 +8,8 @@
#include "base/stl_util.h"
#include "content/browser/media/cdm/browser_cdm_manager.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/frame_messages.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -20,23 +22,20 @@
namespace content {
-MediaWebContentsObserver::MediaWebContentsObserver(
- WebContents* web_contents)
- : WebContentsObserver(web_contents)
-{
-}
+MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
-MediaWebContentsObserver::~MediaWebContentsObserver() {
-}
+MediaWebContentsObserver::~MediaWebContentsObserver() {}
void MediaWebContentsObserver::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
+ ClearPowerSaveBlockers(render_frame_host);
+
#if defined(OS_ANDROID)
- uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
// Always destroy the media players before CDMs because we do not support
// detaching CDMs from media players yet. See http://crbug.com/330324
- media_player_managers_.erase(key);
-#endif
+ media_player_managers_.erase(render_frame_host);
+
// TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
// and BrowserCdmManager all run on browser UI thread. So this call is okay.
// In the future we need to support the case where MediaWebContentsObserver
@@ -46,22 +45,212 @@ void MediaWebContentsObserver::RenderFrameDeleted(
BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
if (browser_cdm_manager)
browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID());
+#endif
}
-#if defined(OS_ANDROID)
+void MediaWebContentsObserver::MaybeUpdateAudibleState(bool recently_audible) {
+ if (recently_audible) {
+ if (!audio_power_save_blocker_)
+ CreateAudioPowerSaveBlocker();
+ } else {
+ audio_power_save_blocker_.reset();
+ }
+}
bool MediaWebContentsObserver::OnMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
+ if (OnMediaPlayerDelegateMessageReceived(msg, render_frame_host))
+ return true;
+
+#if defined(OS_ANDROID)
if (OnMediaPlayerMessageReceived(msg, render_frame_host))
return true;
if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
return true;
+#endif
return false;
}
+bool MediaWebContentsObserver::OnMediaPlayerDelegateMessageReceived(
+ const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ // TODO(dalecurtis): These should no longer be FrameHostMsg.
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserver, msg,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
+ OnMediaPlayingNotification)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
+ OnMediaPausedNotification)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void MediaWebContentsObserver::OnMediaPlayingNotification(
+ RenderFrameHost* render_frame_host,
+ int64_t player_cookie,
+ bool has_video,
+ bool has_audio,
+ bool is_remote) {
+ // Ignore the videos playing remotely and don't hold the wake lock for the
+ // screen. TODO(dalecurtis): Is this correct? It means observers will not
+ // receive play and pause messages.
+ if (is_remote)
+ return;
+
+ const MediaPlayerId id(render_frame_host, player_cookie);
+ if (has_audio) {
+ AddMediaPlayerEntry(id, &active_audio_players_);
+
+ // If we don't have audio stream monitoring, allocate the audio power save
+ // blocker here instead of during NotifyNavigationStateChanged().
+ if (!audio_power_save_blocker_ &&
+ !AudioStreamMonitor::monitoring_available()) {
+ CreateAudioPowerSaveBlocker();
+ }
+ }
+
+ if (has_video) {
+ AddMediaPlayerEntry(id, &active_video_players_);
+
+ // If we're not hidden and have just created a player, create a blocker.
+ if (!video_power_save_blocker_ &&
+ !static_cast<WebContentsImpl*>(web_contents())->IsHidden()) {
+ CreateVideoPowerSaveBlocker();
+ }
+ }
+
+ // Notify observers of the new player.
+ DCHECK(has_audio || has_video);
+ static_cast<WebContentsImpl*>(web_contents())->MediaStartedPlaying(id);
+}
+
+void MediaWebContentsObserver::OnMediaPausedNotification(
+ RenderFrameHost* render_frame_host,
+ int64_t player_cookie) {
+ const MediaPlayerId id(render_frame_host, player_cookie);
+ const bool removed_audio = RemoveMediaPlayerEntry(id, &active_audio_players_);
+ const bool removed_video = RemoveMediaPlayerEntry(id, &active_video_players_);
+ MaybeReleasePowerSaveBlockers();
+
+ if (removed_audio || removed_video) {
+ // Notify observers the player has been "paused".
+ static_cast<WebContentsImpl*>(web_contents())->MediaStoppedPlaying(id);
+ }
+}
+
+void MediaWebContentsObserver::ClearPowerSaveBlockers(
+ RenderFrameHost* render_frame_host) {
+ std::set<MediaPlayerId> removed_players;
+ RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_,
+ &removed_players);
+ RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_,
+ &removed_players);
+ MaybeReleasePowerSaveBlockers();
+
+ // Notify all observers the player has been "paused".
+ WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
+ for (const auto& id : removed_players)
+ wci->MediaStoppedPlaying(id);
+}
+
+void MediaWebContentsObserver::CreateAudioPowerSaveBlocker() {
+ DCHECK(!audio_power_save_blocker_);
+ audio_power_save_blocker_ = PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ PowerSaveBlocker::kReasonAudioPlayback, "Playing audio");
+}
+
+void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() {
+ DCHECK(!video_power_save_blocker_);
+ DCHECK(!active_video_players_.empty());
+ video_power_save_blocker_ = PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ PowerSaveBlocker::kReasonVideoPlayback, "Playing video");
+// TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
+#if defined(OS_ANDROID) && !defined(USE_AURA)
+ static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
+ ->InitDisplaySleepBlocker(web_contents());
+#endif
+}
+
+void MediaWebContentsObserver::WasShown() {
+ // Restore power save blocker if there are active video players running.
+ if (!active_video_players_.empty() && !video_power_save_blocker_)
+ CreateVideoPowerSaveBlocker();
+}
+
+void MediaWebContentsObserver::WasHidden() {
+ // If there are entities capturing screenshots or video (e.g., mirroring),
+ // don't release the power save blocker.
+ if (!web_contents()->GetCapturerCount())
+ video_power_save_blocker_.reset();
+}
+
+void MediaWebContentsObserver::MaybeReleasePowerSaveBlockers() {
+ // If there are no more audio players and we don't have audio stream
+ // monitoring, release the audio power save blocker here instead of during
+ // NotifyNavigationStateChanged().
+ if (active_audio_players_.empty() &&
+ !AudioStreamMonitor::monitoring_available()) {
+ audio_power_save_blocker_.reset();
+ }
+
+ // If there are no more video players, clear the video power save blocker.
+ if (active_video_players_.empty())
+ video_power_save_blocker_.reset();
+}
+
+void MediaWebContentsObserver::AddMediaPlayerEntry(
+ const MediaPlayerId& id,
+ ActiveMediaPlayerMap* player_map) {
+ DCHECK(std::find((*player_map)[id.first].begin(),
+ (*player_map)[id.first].end(),
+ id.second) == (*player_map)[id.first].end());
+ (*player_map)[id.first].push_back(id.second);
+}
+
+bool MediaWebContentsObserver::RemoveMediaPlayerEntry(
+ const MediaPlayerId& id,
+ ActiveMediaPlayerMap* player_map) {
+ auto it = player_map->find(id.first);
+ if (it == player_map->end())
+ return false;
+
+ // Remove the player.
+ auto player_for_removal =
+ std::remove(it->second.begin(), it->second.end(), id.second);
+ if (player_for_removal == it->second.end())
+ return false;
+ it->second.erase(player_for_removal);
+
+ // If there are no players left, remove the map entry.
+ if (it->second.empty())
+ player_map->erase(it);
+
+ return true;
+}
+
+void MediaWebContentsObserver::RemoveAllMediaPlayerEntries(
+ RenderFrameHost* render_frame_host,
+ ActiveMediaPlayerMap* player_map,
+ std::set<MediaPlayerId>* removed_players) {
+ auto it = player_map->find(render_frame_host);
+ if (it == player_map->end())
+ return;
+
+ for (int64_t player_cookie : it->second)
+ removed_players->insert(MediaPlayerId(render_frame_host, player_cookie));
+
+ player_map->erase(it);
+}
+
+#if defined(OS_ANDROID)
+
bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
@@ -155,21 +344,21 @@ void MediaWebContentsObserver::OnSetCdm(RenderFrameHost* render_frame_host,
BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
RenderFrameHost* render_frame_host) {
- uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
- if (!media_player_managers_.contains(key)) {
- media_player_managers_.set(
- key,
- make_scoped_ptr(BrowserMediaPlayerManager::Create(render_frame_host)));
- }
- return media_player_managers_.get(key);
+ auto it = media_player_managers_.find(render_frame_host);
+ if (it != media_player_managers_.end())
+ return it->second;
+
+ BrowserMediaPlayerManager* manager =
+ BrowserMediaPlayerManager::Create(render_frame_host);
+ media_player_managers_.set(render_frame_host, make_scoped_ptr(manager));
+ return manager;
}
#if defined(VIDEO_HOLE)
void MediaWebContentsObserver::OnFrameInfoUpdated() {
- for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
- iter != media_player_managers_.end(); ++iter) {
- BrowserMediaPlayerManager* manager = iter->second;
- manager->OnFrameInfoUpdated();
+ for (auto it = media_player_managers_.begin();
+ it != media_player_managers_.end(); ++it) {
+ it->second->OnFrameInfoUpdated();
}
}
#endif // defined(VIDEO_HOLE)
« no previous file with comments | « content/browser/media/media_web_contents_observer.h ('k') | content/browser/web_contents/web_contents_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698