Chromium Code Reviews| Index: content/browser/web_contents/web_contents_impl.cc |
| diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc |
| index 501ae9aa0f4ed99da6be0385031b7cc5c55f39de..5c98256548fcedd504bd0a5c58d7cbd1573243e4 100644 |
| --- a/content/browser/web_contents/web_contents_impl.cc |
| +++ b/content/browser/web_contents/web_contents_impl.cc |
| @@ -111,6 +111,13 @@ |
| #include "base/mac/foundation_util.h" |
| #endif |
| +// Only do audio stream monitoring for platforms that use it for the tab media |
| +// indicator UI or the OOM killer. |
| +#if !defined(OS_ANDROID) && !defined(OS_IOS) |
| +#define AUDIO_STREAM_MONITORING |
|
jam
2014/09/02 19:50:33
nit: use a boolean member in this class that is in
DaleCurtis
2014/09/04 21:59:06
I instead plumbing a bit which is defined where th
|
| +#include "content/browser/media/audio_stream_monitor.h" |
| +#endif |
| + |
| // Cross-Site Navigations |
| // |
| // If a WebContentsImpl is told to navigate to a different web site (as |
| @@ -1042,6 +1049,10 @@ void WebContentsImpl::WasShown() { |
| rvh->ResizeRectChanged(GetRootWindowResizerRect()); |
| } |
| + // Restore power save blocker if there are active video players running. |
| + if (!active_media_players_.empty()) |
| + CreatePowerSaveBlocker(); |
| + |
| FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown()); |
| should_normally_be_visible_ = true; |
| @@ -1066,6 +1077,9 @@ void WebContentsImpl::WasHidden() { |
| } |
| } |
| + // Release any video power save blockers held as video is not visible. |
| + power_save_blocker_.reset(); |
| + |
| FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden()); |
| should_normally_be_visible_ = false; |
| @@ -2388,6 +2402,15 @@ void WebContentsImpl::InsertCSS(const std::string& css) { |
| GetMainFrame()->GetRoutingID(), css)); |
| } |
| +bool WebContentsImpl::WasRecentlyAudible() { |
| +#if !defined(AUDIO_STREAM_MONITORING) |
| + return false; |
| +#else |
| + AudioStreamMonitor* const monitor = AudioStreamMonitor::FromWebContents(this); |
| + return monitor ? monitor->WasRecentlyAudible() : false; |
| +#endif |
| +} |
| + |
| bool WebContentsImpl::FocusLocationBarByDefault() { |
| NavigationEntry* entry = controller_.GetVisibleEntry(); |
| if (entry && entry->GetURL() == GURL(url::kAboutBlankURL)) |
| @@ -2999,42 +3022,61 @@ void WebContentsImpl::OnUpdateFaviconURL( |
| DidUpdateFaviconURL(candidates)); |
| } |
| +void WebContentsImpl::CreatePowerSaveBlocker() { |
| + DCHECK(!power_save_blocker_); |
| + DCHECK(!active_media_players_.empty()); |
| + power_save_blocker_ = PowerSaveBlocker::Create( |
| + PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video"); |
| +#if defined(OS_ANDROID) |
| + static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get()) |
| + ->InitDisplaySleepBlocker(GetView()->GetNativeView()); |
| +#endif |
| +} |
| + |
| void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie, |
| bool has_video, |
| bool has_audio) { |
| #if !defined(OS_CHROMEOS) |
| - scoped_ptr<PowerSaveBlocker> blocker; |
| - if (has_video) { |
| - blocker = PowerSaveBlocker::Create( |
| - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing video"); |
| -#if defined(OS_ANDROID) |
| - static_cast<PowerSaveBlockerImpl*>(blocker.get()) |
| - ->InitDisplaySleepBlocker(GetView()->GetNativeView()); |
| +#if defined(AUDIO_STREAM_MONITORING) |
| + // Don't handle audio if audio level analysis is available. |
| + if (!has_video) |
| + return; |
| #endif |
| - } else if (has_audio) { |
| - blocker = PowerSaveBlocker::Create( |
|
miu
2014/09/02 21:04:39
I'm not sure the blocker is set up correctly for p
DaleCurtis
2014/09/03 18:48:55
It ends up being correct since Androids PowerSaveB
|
| - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing audio"); |
| - } |
| - if (blocker) { |
| - uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_message_source_); |
| - if (!power_save_blockers_.contains(key)) { |
| - power_save_blockers_.add(key, |
| - make_scoped_ptr(new PowerSaveBlockerMapEntry)); |
| - } |
| - PowerSaveBlockerMapEntry* map_entry = |
| - power_save_blockers_.get(key); |
| - map_entry->set(player_cookie, blocker.Pass()); |
| - } |
| + // Track current status to see if we need to create a new blocker. |
| + const bool had_no_player = active_media_players_.empty(); |
| + |
| + // Store tracking entries based on the RenderFrameHost. |
| + const uintptr_t key = |
| + reinterpret_cast<uintptr_t>(render_frame_message_source_); |
| + |
| + ActiveMediaPlayerMap::iterator it = active_media_players_.find(key); |
| + if (it != active_media_players_.end()) |
| + it->second++; |
| + else |
| + active_media_players_[key] = 1; |
| + |
| + // If we're not hidden and just created a new video player, create a blocker. |
| + if (had_no_player && !active_media_players_.empty() && !IsHidden()) |
| + CreatePowerSaveBlocker(); |
| #endif // !defined(OS_CHROMEOS) |
| } |
| void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) { |
| #if !defined(OS_CHROMEOS) |
| - uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_message_source_); |
| - PowerSaveBlockerMapEntry* map_entry = power_save_blockers_.get(key); |
| - if (map_entry) |
| - map_entry->erase(player_cookie); |
| + ActiveMediaPlayerMap::iterator it = active_media_players_.find( |
| + reinterpret_cast<uintptr_t>(render_frame_message_source_)); |
| + if (it == active_media_players_.end()) |
| + return; |
| + it->second--; |
| + DCHECK_GE(it->second, 0); |
| + // If there are no more active players in this RenderFrameHost, remove entry. |
| + if (!it->second) |
| + active_media_players_.erase(it); |
| + // If there are no more active players at all, clear the power blocker. |
| + if (active_media_players_.empty()) { |
| + power_save_blocker_.reset(); |
| + } |
| #endif // !defined(OS_CHROMEOS) |
| } |
| @@ -4203,17 +4245,22 @@ BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { |
| void WebContentsImpl::ClearPowerSaveBlockers( |
| RenderFrameHost* render_frame_host) { |
| #if !defined(OS_CHROMEOS) |
| - uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host); |
| - scoped_ptr<PowerSaveBlockerMapEntry> map_entry = |
| - power_save_blockers_.take_and_erase(key); |
| - if (map_entry) |
| - map_entry->clear(); |
| + ActiveMediaPlayerMap::iterator it = active_media_players_.find( |
| + reinterpret_cast<uintptr_t>(render_frame_message_source_)); |
| + if (it == active_media_players_.end()) |
| + return; |
| + active_media_players_.erase(it); |
| + |
| + // If there are no more active players at all, clear the power blocker. |
| + if (active_media_players_.empty()) |
| + power_save_blocker_.reset(); |
| #endif |
| } |
| void WebContentsImpl::ClearAllPowerSaveBlockers() { |
| #if !defined(OS_CHROMEOS) |
| - power_save_blockers_.clear(); |
| + active_media_players_.clear(); |
| + power_save_blocker_.reset(); |
| #endif |
| } |