Index: content/browser/media/media_internals.cc |
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc |
index f0b071a4e12fb3dda001b9506df53f42b98dec13..af0d3ab659d7f069a0694b9644ac251b409e694d 100644 |
--- a/content/browser/media/media_internals.cc |
+++ b/content/browser/media/media_internals.cc |
@@ -264,8 +264,11 @@ class MediaInternals::MediaInternalsUMAHandler : public NotificationObserver { |
// Helper function to save the event payload to RendererPlayerMap. |
void SavePlayerState(const media::MediaLogEvent& event, |
+ const base::string16& event_serialized, |
int render_process_id); |
+ std::vector<base::string16> GetHistoricalEvents(); |
+ |
private: |
struct PipelineInfo { |
media::PipelineStatus last_pipeline_status; |
@@ -276,6 +279,9 @@ class MediaInternals::MediaInternalsUMAHandler : public NotificationObserver { |
std::string audio_codec_name; |
std::string video_codec_name; |
std::string video_decoder; |
+ // Remember media log events so that when a new media internals page is |
+ // opened they can be replayed. |
+ std::vector<base::string16> media_log_event_history; |
PipelineInfo() |
: last_pipeline_status(media::PIPELINE_OK), |
has_audio(false), |
@@ -321,7 +327,7 @@ void MediaInternals::MediaInternalsUMAHandler::Observe( |
// by both SavePlayerState & LogAndClearPlayersInRenderer from different |
// threads. |
// Using base::Unretained() on MediaInternalsUMAHandler is safe since |
- // it is owned by MediaInternals and share the same lifetime |
+ // it is owned by MediaInternals and shares the same lifetime. |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
base::Bind(&MediaInternalsUMAHandler::LogAndClearPlayersInRenderer, |
@@ -330,9 +336,12 @@ void MediaInternals::MediaInternalsUMAHandler::Observe( |
void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( |
const media::MediaLogEvent& event, |
+ const base::string16& event_serialized, |
int render_process_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
PlayerInfoMap& player_info = renderer_info_[render_process_id]; |
+ // This can grow unbounded.. |
+ player_info[event.id].media_log_event_history.push_back(event_serialized); |
switch (event.type) { |
case media::MediaLogEvent::PIPELINE_ERROR: { |
int status; |
@@ -450,6 +459,23 @@ void MediaInternals::MediaInternalsUMAHandler::LogAndClearPlayersInRenderer( |
ReportUMAForPipelineStatus(it->second); |
players_it->second.erase(it++); |
} |
+ renderer_info_.erase(players_it); |
+} |
+ |
+std::vector<base::string16> |
+MediaInternals::MediaInternalsUMAHandler::GetHistoricalEvents() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ std::vector<base::string16> all_events; |
+ for (const auto& renderer_info_it : renderer_info_) { |
+ for (const auto& player_info_it : renderer_info_it.second) { |
+ const auto& player_events = player_info_it.second.media_log_event_history; |
+ all_events.insert(all_events.end(), player_events.begin(), |
+ player_events.end()); |
+ } |
+ } |
+ |
+ return all_events; |
} |
MediaInternals* MediaInternals::GetInstance() { |
@@ -493,8 +519,9 @@ void MediaInternals::OnMediaEvents( |
dict.Set("params", event->params.DeepCopy()); |
} |
- SendUpdate(SerializeUpdate("media.onMediaEvent", &dict)); |
- uma_handler_->SavePlayerState(*event, render_process_id); |
+ const base::string16 update(SerializeUpdate("media.onMediaEvent", &dict)); |
+ SendUpdate(update); |
+ uma_handler_->SavePlayerState(*event, update, render_process_id); |
} |
} |
@@ -514,6 +541,12 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { |
NOTREACHED(); |
} |
+void MediaInternals::SendHistoricalMediaEvents() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ for (const auto& event : uma_handler_->GetHistoricalEvents()) |
+ SendUpdate(event); |
+} |
+ |
void MediaInternals::SendAudioStreamData() { |
base::string16 audio_stream_update; |
{ |