Commit e4555db0 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Engagement] Track AudioContext playbacks

Adds AudioContext player tracking to MediaEngagementContentsObserver
with it's own page level timer. On MediaEngagementSession this CL
seperates significant playback into media element playback and
audio context playback. Since we may record a playback we need to
disable committing on significant playback and just record on
destroy or navigate instead.

BUG=878460

Change-Id: Ic66152f8cb5b3a6338804c04de7dd0bf5c1cb154
Reviewed-on: https://chromium-review.googlesource.com/1194992
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587899}
parent b3b25596
...@@ -337,7 +337,7 @@ class MediaEngagementPreloadBrowserTest : public InProcessBrowserTest { ...@@ -337,7 +337,7 @@ class MediaEngagementPreloadBrowserTest : public InProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(MediaEngagementBrowserTest, RecordEngagement) { IN_PROC_BROWSER_TEST_F(MediaEngagementBrowserTest, RecordEngagement) {
LoadTestPageAndWaitForPlayAndAudible("engagement_test.html", false); LoadTestPageAndWaitForPlayAndAudible("engagement_test.html", false);
AdvanceMeaningfulPlaybackTime(); AdvanceMeaningfulPlaybackTime();
ExpectScores(1, 1, 0, 0); ExpectScores(0, 0, 0, 0);
CloseTab(); CloseTab();
ExpectScores(1, 1, 1, 1); ExpectScores(1, 1, 1, 1);
} }
......
...@@ -122,6 +122,8 @@ void MediaEngagementContentsObserver::ClearPlayerStates() { ...@@ -122,6 +122,8 @@ void MediaEngagementContentsObserver::ClearPlayerStates() {
playback_timer_.Stop(); playback_timer_.Stop();
player_states_.clear(); player_states_.clear();
significant_players_.clear(); significant_players_.clear();
audio_context_players_.clear();
audio_context_timer_.Stop();
} }
void MediaEngagementContentsObserver::RegisterAudiblePlayersWithSession() { void MediaEngagementContentsObserver::RegisterAudiblePlayersWithSession() {
...@@ -270,8 +272,21 @@ void MediaEngagementContentsObserver::MediaStoppedPlaying( ...@@ -270,8 +272,21 @@ void MediaEngagementContentsObserver::MediaStoppedPlaying(
UpdatePlayerTimer(media_player_id); UpdatePlayerTimer(media_player_id);
} }
void MediaEngagementContentsObserver::AudioContextPlaybackStarted(
const AudioContextId& audio_context_id) {
audio_context_players_.insert(audio_context_id);
UpdateAudioContextTimer();
}
void MediaEngagementContentsObserver::AudioContextPlaybackStopped(
const AudioContextId& audio_context_id) {
audio_context_players_.erase(audio_context_id);
UpdateAudioContextTimer();
}
void MediaEngagementContentsObserver::DidUpdateAudioMutingState(bool muted) { void MediaEngagementContentsObserver::DidUpdateAudioMutingState(bool muted) {
UpdatePageTimer(); UpdatePageTimer();
UpdateAudioContextTimer();
} }
std::vector<MediaEngagementContentsObserver::InsignificantPlaybackReason> std::vector<MediaEngagementContentsObserver::InsignificantPlaybackReason>
...@@ -330,7 +345,23 @@ void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPlayer( ...@@ -330,7 +345,23 @@ void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPlayer(
void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPage() { void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPage() {
DCHECK(session_); DCHECK(session_);
if (session_->significant_playback_recorded()) if (session_->significant_media_element_playback_recorded())
return;
// Do not record significant playback if the tab did not make
// a sound recently.
auto* audible_helper = RecentlyAudibleHelper::FromWebContents(web_contents());
if (!audible_helper->WasRecentlyAudible())
return;
session_->RecordSignificantMediaElementPlayback();
}
void MediaEngagementContentsObserver::
OnSignificantAudioContextPlaybackTimeForPage() {
DCHECK(session_);
if (session_->significant_audio_context_playback_recorded())
return; return;
// Do not record significant playback if the tab did not make // Do not record significant playback if the tab did not make
...@@ -339,7 +370,7 @@ void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPage() { ...@@ -339,7 +370,7 @@ void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTimeForPage() {
if (!audible_helper->WasRecentlyAudible()) if (!audible_helper->WasRecentlyAudible())
return; return;
session_->RecordSignificantPlayback(); session_->RecordSignificantAudioContextPlayback();
} }
void MediaEngagementContentsObserver::RecordInsignificantReasons( void MediaEngagementContentsObserver::RecordInsignificantReasons(
...@@ -474,7 +505,7 @@ bool MediaEngagementContentsObserver::AreConditionsMet() const { ...@@ -474,7 +505,7 @@ bool MediaEngagementContentsObserver::AreConditionsMet() const {
} }
void MediaEngagementContentsObserver::UpdatePageTimer() { void MediaEngagementContentsObserver::UpdatePageTimer() {
if (!session_ || session_->significant_playback_recorded()) if (!session_ || session_->significant_media_element_playback_recorded())
return; return;
if (AreConditionsMet()) { if (AreConditionsMet()) {
...@@ -497,6 +528,35 @@ void MediaEngagementContentsObserver::UpdatePageTimer() { ...@@ -497,6 +528,35 @@ void MediaEngagementContentsObserver::UpdatePageTimer() {
} }
} }
bool MediaEngagementContentsObserver::AreAudioContextConditionsMet() const {
if (audio_context_players_.empty())
return false;
return !web_contents()->IsAudioMuted();
}
void MediaEngagementContentsObserver::UpdateAudioContextTimer() {
if (!session_ || session_->significant_audio_context_playback_recorded())
return;
if (AreAudioContextConditionsMet()) {
if (audio_context_timer_.IsRunning())
return;
if (task_runner_)
audio_context_timer_.SetTaskRunner(task_runner_);
audio_context_timer_.Start(
FROM_HERE,
MediaEngagementContentsObserver::kSignificantMediaPlaybackTime,
base::Bind(&MediaEngagementContentsObserver::
OnSignificantAudioContextPlaybackTimeForPage,
base::Unretained(this)));
} else if (audio_context_timer_.IsRunning()) {
audio_context_timer_.Stop();
}
}
void MediaEngagementContentsObserver::SetTaskRunnerForTest( void MediaEngagementContentsObserver::SetTaskRunnerForTest(
scoped_refptr<base::SequencedTaskRunner> task_runner) { scoped_refptr<base::SequencedTaskRunner> task_runner) {
task_runner_ = std::move(task_runner); task_runner_ = std::move(task_runner);
......
...@@ -39,6 +39,10 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver { ...@@ -39,6 +39,10 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver {
void DidUpdateAudioMutingState(bool muted) override; void DidUpdateAudioMutingState(bool muted) override;
void MediaMutedStatusChanged(const MediaPlayerId& id, bool muted) override; void MediaMutedStatusChanged(const MediaPlayerId& id, bool muted) override;
void MediaResized(const gfx::Size& size, const MediaPlayerId& id) override; void MediaResized(const gfx::Size& size, const MediaPlayerId& id) override;
void AudioContextPlaybackStarted(
const AudioContextId& audio_context_id) override;
void AudioContextPlaybackStopped(
const AudioContextId& audio_context_id) override;
static const gfx::Size kSignificantSize; static const gfx::Size kSignificantSize;
static const char* const kHistogramScoreAtPlaybackName; static const char* const kHistogramScoreAtPlaybackName;
...@@ -96,9 +100,14 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver { ...@@ -96,9 +100,14 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver {
void OnSignificantMediaPlaybackTimeForPlayer(const MediaPlayerId& id); void OnSignificantMediaPlaybackTimeForPlayer(const MediaPlayerId& id);
void OnSignificantMediaPlaybackTimeForPage(); void OnSignificantMediaPlaybackTimeForPage();
void OnSignificantAudioContextPlaybackTimeForPage();
void UpdatePlayerTimer(const MediaPlayerId&); void UpdatePlayerTimer(const MediaPlayerId&);
void UpdatePageTimer(); void UpdatePageTimer();
void UpdateAudioContextTimer();
bool AreConditionsMet() const; bool AreConditionsMet() const;
bool AreAudioContextConditionsMet() const;
void SetTaskRunnerForTest(scoped_refptr<base::SequencedTaskRunner>); void SetTaskRunnerForTest(scoped_refptr<base::SequencedTaskRunner>);
...@@ -114,6 +123,13 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver { ...@@ -114,6 +123,13 @@ class MediaEngagementContentsObserver : public content::WebContentsObserver {
// significant playback. // significant playback.
std::set<MediaPlayerId> significant_players_; std::set<MediaPlayerId> significant_players_;
// Timer that will fire when the playback time of any audio context reaches
// the minimum for significant media playback.
base::OneShotTimer audio_context_timer_;
// Set of active audio contexts that can produce a significant playback.
std::set<AudioContextId> audio_context_players_;
// Measures playback time for a player. // Measures playback time for a player.
class PlaybackTimer { class PlaybackTimer {
public: public:
......
...@@ -86,10 +86,13 @@ class MediaEngagementScore final { ...@@ -86,10 +86,13 @@ class MediaEngagementScore final {
int media_playbacks() const { return media_playbacks_; } int media_playbacks() const { return media_playbacks_; }
void IncrementMediaPlaybacks(); void IncrementMediaPlaybacks();
// Get the last time media was played on this origin. // Gets/sets the last time media was played on this origin.
base::Time last_media_playback_time() const { base::Time last_media_playback_time() const {
return last_media_playback_time_; return last_media_playback_time_;
} }
void set_last_media_playback_time(base::Time new_time) {
last_media_playback_time_ = new_time;
}
// Get/increment the number of audible media playbacks this origin had. // Get/increment the number of audible media playbacks this origin had.
int audible_playbacks() const { return audible_playbacks_; } int audible_playbacks() const { return audible_playbacks_; }
...@@ -152,9 +155,6 @@ class MediaEngagementScore final { ...@@ -152,9 +155,6 @@ class MediaEngagementScore final {
void set_visits_with_media_tag(int visits) { void set_visits_with_media_tag(int visits) {
visits_with_media_tag_ = visits; visits_with_media_tag_ = visits;
} }
void set_last_media_playback_time(base::Time new_time) {
last_media_playback_time_ = new_time;
}
void set_media_element_playbacks(int playbacks) { void set_media_element_playbacks(int playbacks) {
media_element_playbacks_ = playbacks; media_element_playbacks_ = playbacks;
} }
......
...@@ -321,15 +321,6 @@ MediaEngagementService::GetAllScoreDetails() const { ...@@ -321,15 +321,6 @@ MediaEngagementService::GetAllScoreDetails() const {
return details; return details;
} }
void MediaEngagementService::RecordPlayback(const GURL& url) {
if (!ShouldRecordEngagement(url))
return;
MediaEngagementScore score = CreateEngagementScore(url);
score.IncrementMediaPlaybacks();
score.Commit();
}
MediaEngagementScore MediaEngagementService::CreateEngagementScore( MediaEngagementScore MediaEngagementService::CreateEngagementScore(
const GURL& url) const { const GURL& url) const {
// If we are in incognito, |settings| will automatically have the data from // If we are in incognito, |settings| will automatically have the data from
......
...@@ -65,9 +65,6 @@ class MediaEngagementService : public KeyedService, ...@@ -65,9 +65,6 @@ class MediaEngagementService : public KeyedService,
// Record a visit of a |url|. // Record a visit of a |url|.
void RecordVisit(const GURL& url); void RecordVisit(const GURL& url);
// Record a media playback on a |url|.
void RecordPlayback(const GURL& url);
// Returns an array of engagement score details for all origins which // Returns an array of engagement score details for all origins which
// have a score. // have a score.
std::vector<media::mojom::MediaEngagementScoreDetailsPtr> GetAllScoreDetails() std::vector<media::mojom::MediaEngagementScoreDetailsPtr> GetAllScoreDetails()
...@@ -103,6 +100,8 @@ class MediaEngagementService : public KeyedService, ...@@ -103,6 +100,8 @@ class MediaEngagementService : public KeyedService,
// cleared, either partially or fully. // cleared, either partially or fully.
static const char kHistogramClearName[]; static const char kHistogramClearName[];
const base::Clock* clock() const { return clock_; }
private: private:
friend class MediaEngagementBrowserTest; friend class MediaEngagementBrowserTest;
friend class MediaEngagementContentsObserverTest; friend class MediaEngagementContentsObserverTest;
......
...@@ -162,7 +162,16 @@ class MediaEngagementServiceTest : public ChromeRenderViewHostTestHarness { ...@@ -162,7 +162,16 @@ class MediaEngagementServiceTest : public ChromeRenderViewHostTestHarness {
void RecordVisit(GURL url) { service_->RecordVisit(url); } void RecordVisit(GURL url) { service_->RecordVisit(url); }
void RecordPlayback(GURL url) { service_->RecordPlayback(url); } void RecordPlayback(GURL url) {
RecordPlaybackForService(service_.get(), url);
}
void RecordPlaybackForService(MediaEngagementService* service, GURL url) {
MediaEngagementScore score = service->CreateEngagementScore(url);
score.IncrementMediaPlaybacks();
score.set_last_media_playback_time(service->clock()->Now());
score.Commit();
}
void ExpectScores(MediaEngagementService* service, void ExpectScores(MediaEngagementService* service,
GURL url, GURL url,
...@@ -370,7 +379,7 @@ TEST_F(MediaEngagementServiceTest, IncognitoOverrideRegularProfile) { ...@@ -370,7 +379,7 @@ TEST_F(MediaEngagementServiceTest, IncognitoOverrideRegularProfile) {
} }
incognito_service->RecordVisit(kUrl1); incognito_service->RecordVisit(kUrl1);
incognito_service->RecordPlayback(kUrl2); RecordPlaybackForService(incognito_service, kUrl2);
// Score shouldn't have changed in regular profile. // Score shouldn't have changed in regular profile.
{ {
......
...@@ -49,21 +49,22 @@ bool MediaEngagementSession::IsSameOriginWith(const url::Origin& origin) const { ...@@ -49,21 +49,22 @@ bool MediaEngagementSession::IsSameOriginWith(const url::Origin& origin) const {
return origin_.IsSameOriginWith(origin); return origin_.IsSameOriginWith(origin);
} }
void MediaEngagementSession::RecordSignificantPlayback() { void MediaEngagementSession::RecordSignificantMediaElementPlayback() {
DCHECK(!significant_playback_recorded_); DCHECK(!significant_media_element_playback_recorded_);
significant_playback_recorded_ = true; significant_media_element_playback_recorded_ = true;
pending_data_to_commit_.playback = true; pending_data_to_commit_.media_element_playback = true;
// When a session was restored, visits are only recorded when there was a RecordSignificantPlayback();
// playback. Add back the visit now as this code can only be executed once }
// per session.
if (restore_status_ == RestoreType::kRestored)
pending_data_to_commit_.visit = true;
// When playback has happened, the visit can be recorded as there will be no void MediaEngagementSession::RecordSignificantAudioContextPlayback() {
// further changes. DCHECK(!significant_audio_context_playback_recorded_);
CommitPendingData();
significant_audio_context_playback_recorded_ = true;
pending_data_to_commit_.audio_context_playback = true;
RecordSignificantPlayback();
} }
void MediaEngagementSession::RecordShortPlaybackIgnored(int length_msec) { void MediaEngagementSession::RecordShortPlaybackIgnored(int length_msec) {
...@@ -89,8 +90,19 @@ void MediaEngagementSession::RegisterAudiblePlayers( ...@@ -89,8 +90,19 @@ void MediaEngagementSession::RegisterAudiblePlayers(
significant_players_delta_ += significant_players; significant_players_delta_ += significant_players;
} }
bool MediaEngagementSession::significant_playback_recorded() const { bool MediaEngagementSession::WasSignificantPlaybackRecorded() const {
return significant_playback_recorded_; return significant_media_element_playback_recorded_ ||
significant_audio_context_playback_recorded_;
}
bool MediaEngagementSession::significant_media_element_playback_recorded()
const {
return significant_media_element_playback_recorded_;
}
bool MediaEngagementSession::significant_audio_context_playback_recorded()
const {
return significant_audio_context_playback_recorded_;
} }
const url::Origin& MediaEngagementSession::origin() const { const url::Origin& MediaEngagementSession::origin() const {
...@@ -104,7 +116,7 @@ MediaEngagementSession::~MediaEngagementSession() { ...@@ -104,7 +116,7 @@ MediaEngagementSession::~MediaEngagementSession() {
if (HasPendingDataToCommit()) { if (HasPendingDataToCommit()) {
CommitPendingData(); CommitPendingData();
} else if ((restore_status_ == RestoreType::kRestored) && } else if ((restore_status_ == RestoreType::kRestored) &&
!significant_playback_recorded_) { !WasSignificantPlaybackRecorded()) {
RecordStatusHistograms(); RecordStatusHistograms();
} }
...@@ -124,6 +136,21 @@ ukm::UkmRecorder* MediaEngagementSession::GetUkmRecorder() { ...@@ -124,6 +136,21 @@ ukm::UkmRecorder* MediaEngagementSession::GetUkmRecorder() {
return ukm_recorder; return ukm_recorder;
} }
void MediaEngagementSession::RecordSignificantPlayback() {
DCHECK(WasSignificantPlaybackRecorded());
// If this was the first time we recorded significant playback then we should
// record the playback time.
if (first_significant_playback_time_.is_null())
first_significant_playback_time_ = service_->clock()->Now();
// When a session was restored, visits are only recorded when there was a
// playback. Add back the visit now as this code can only be executed once
// per session.
if (restore_status_ == RestoreType::kRestored)
pending_data_to_commit_.visit = true;
}
void MediaEngagementSession::RecordUkmMetrics() { void MediaEngagementSession::RecordUkmMetrics() {
ukm::UkmRecorder* ukm_recorder = GetUkmRecorder(); ukm::UkmRecorder* ukm_recorder = GetUkmRecorder();
if (!ukm_recorder) if (!ukm_recorder)
...@@ -142,7 +169,7 @@ void MediaEngagementSession::RecordUkmMetrics() { ...@@ -142,7 +169,7 @@ void MediaEngagementSession::RecordUkmMetrics() {
.SetPlaybacks_Total(score.media_playbacks()) .SetPlaybacks_Total(score.media_playbacks())
.SetVisits_Total(score.visits()) .SetVisits_Total(score.visits())
.SetEngagement_Score(round(score.actual_score() * 100)) .SetEngagement_Score(round(score.actual_score() * 100))
.SetPlaybacks_Delta(significant_playback_recorded_) .SetPlaybacks_Delta(significant_media_element_playback_recorded_)
.SetEngagement_IsHigh(score.high_score()) .SetEngagement_IsHigh(score.high_score())
.SetEngagement_IsHigh_Changed(high_score_changed_) .SetEngagement_IsHigh_Changed(high_score_changed_)
.SetEngagement_IsHigh_Changes(score.high_score_changes()) .SetEngagement_IsHigh_Changes(score.high_score_changes())
...@@ -155,9 +182,14 @@ void MediaEngagementSession::RecordUkmMetrics() { ...@@ -155,9 +182,14 @@ void MediaEngagementSession::RecordUkmMetrics() {
.Record(ukm_recorder); .Record(ukm_recorder);
} }
bool MediaEngagementSession::HasPendingPlaybackToCommit() const {
return pending_data_to_commit_.audio_context_playback ||
pending_data_to_commit_.media_element_playback;
}
bool MediaEngagementSession::HasPendingDataToCommit() const { bool MediaEngagementSession::HasPendingDataToCommit() const {
return pending_data_to_commit_.visit || pending_data_to_commit_.playback || return pending_data_to_commit_.visit || pending_data_to_commit_.players ||
pending_data_to_commit_.players; HasPendingPlaybackToCommit();
} }
void MediaEngagementSession::RecordStatusHistograms() const { void MediaEngagementSession::RecordStatusHistograms() const {
...@@ -165,12 +197,12 @@ void MediaEngagementSession::RecordStatusHistograms() const { ...@@ -165,12 +197,12 @@ void MediaEngagementSession::RecordStatusHistograms() const {
(restore_status_ == RestoreType::kRestored)); (restore_status_ == RestoreType::kRestored));
RecordSessionStatus(SessionStatus::kCreated); RecordSessionStatus(SessionStatus::kCreated);
if (pending_data_to_commit_.playback) if (HasPendingPlaybackToCommit())
RecordSessionStatus(SessionStatus::kSignificantPlayback); RecordSessionStatus(SessionStatus::kSignificantPlayback);
if (restore_status_ == RestoreType::kRestored) { if (restore_status_ == RestoreType::kRestored) {
RecordRestoredSessionStatus(SessionStatus::kCreated); RecordRestoredSessionStatus(SessionStatus::kCreated);
if (pending_data_to_commit_.playback) if (HasPendingPlaybackToCommit())
RecordRestoredSessionStatus(SessionStatus::kSignificantPlayback); RecordRestoredSessionStatus(SessionStatus::kSignificantPlayback);
} }
} }
...@@ -187,11 +219,20 @@ void MediaEngagementSession::CommitPendingData() { ...@@ -187,11 +219,20 @@ void MediaEngagementSession::CommitPendingData() {
if (pending_data_to_commit_.visit) if (pending_data_to_commit_.visit)
score.IncrementVisits(); score.IncrementVisits();
if (significant_playback_recorded_ && pending_data_to_commit_.playback) { if (WasSignificantPlaybackRecorded() && HasPendingPlaybackToCommit()) {
const base::Time old_time = score.last_media_playback_time(); const base::Time old_time = score.last_media_playback_time();
score.IncrementMediaPlaybacks(); score.IncrementMediaPlaybacks();
if (pending_data_to_commit_.audio_context_playback)
score.IncrementAudioContextPlaybacks();
if (pending_data_to_commit_.media_element_playback)
score.IncrementMediaElementPlaybacks();
// Use the stored significant playback time.
score.set_last_media_playback_time(first_significant_playback_time_);
// This code should be reached once and |time_since_playback_for_ukm_| can't // This code should be reached once and |time_since_playback_for_ukm_| can't
// be set. // be set.
DCHECK(time_since_playback_for_ukm_.is_zero()); DCHECK(time_since_playback_for_ukm_.is_zero());
...@@ -221,6 +262,7 @@ void MediaEngagementSession::CommitPendingData() { ...@@ -221,6 +262,7 @@ void MediaEngagementSession::CommitPendingData() {
// If the high state has changed store that in a bool. // If the high state has changed store that in a bool.
high_score_changed_ = previous_high_value != score.high_score(); high_score_changed_ = previous_high_value != score.high_score();
pending_data_to_commit_.visit = pending_data_to_commit_.playback = pending_data_to_commit_.visit = pending_data_to_commit_.players =
pending_data_to_commit_.players = false; pending_data_to_commit_.audio_context_playback =
pending_data_to_commit_.media_element_playback = false;
} }
...@@ -37,8 +37,13 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> { ...@@ -37,8 +37,13 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> {
// Returns whether the session's origin is same origin with |origin|. // Returns whether the session's origin is same origin with |origin|.
bool IsSameOriginWith(const url::Origin& origin) const; bool IsSameOriginWith(const url::Origin& origin) const;
// Record that the session received a significant playback. // Record that the session received a significant playback from a media
void RecordSignificantPlayback(); // element.
void RecordSignificantMediaElementPlayback();
// Record that the session received a significant playback from an audio
// context.
void RecordSignificantAudioContextPlayback();
// Record the length of an ignored media playback. // Record the length of an ignored media playback.
void RecordShortPlaybackIgnored(int length_msec); void RecordShortPlaybackIgnored(int length_msec);
...@@ -48,7 +53,11 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> { ...@@ -48,7 +53,11 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> {
void RegisterAudiblePlayers(int32_t audible_players, void RegisterAudiblePlayers(int32_t audible_players,
int32_t significant_players); int32_t significant_players);
bool significant_playback_recorded() const; // Whether any significant playback was recorded.
bool WasSignificantPlaybackRecorded() const;
bool significant_media_element_playback_recorded() const;
bool significant_audio_context_playback_recorded() const;
const url::Origin& origin() const; const url::Origin& origin() const;
private: private:
...@@ -61,9 +70,17 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> { ...@@ -61,9 +70,17 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> {
// Returns the UkmRecorder with the right source id set. // Returns the UkmRecorder with the right source id set.
ukm::UkmRecorder* GetUkmRecorder(); ukm::UkmRecorder* GetUkmRecorder();
// Records a significant playback that is either a media element or an audio
// context playback.
void RecordSignificantPlayback();
// Record the score and change in score to UKM. // Record the score and change in score to UKM.
void RecordUkmMetrics(); void RecordUkmMetrics();
// Returns whether the session has a pending playback that needs to be
// committed into the database.
bool HasPendingPlaybackToCommit() const;
// Returns whether the session has data that needs to be committed into the // Returns whether the session has data that needs to be committed into the
// database. // database.
bool HasPendingDataToCommit() const; bool HasPendingDataToCommit() const;
...@@ -93,14 +110,19 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> { ...@@ -93,14 +110,19 @@ class MediaEngagementSession : public base::RefCounted<MediaEngagementSession> {
int32_t audible_players_total_ = 0; int32_t audible_players_total_ = 0;
int32_t significant_players_total_ = 0; int32_t significant_players_total_ = 0;
bool significant_playback_recorded_ = false; bool significant_media_element_playback_recorded_ = false;
bool significant_audio_context_playback_recorded_ = false;
struct PendingDataToCommit { struct PendingDataToCommit {
bool visit = true; bool visit = true;
bool playback = false; bool audio_context_playback = false;
bool media_element_playback = false;
bool players = false; bool players = false;
}; };
PendingDataToCommit pending_data_to_commit_; PendingDataToCommit pending_data_to_commit_;
// The time the first significant playback occurred.
base::Time first_significant_playback_time_;
// The time between significant playbacks to be recorded to UKM. // The time between significant playbacks to be recorded to UKM.
base::TimeDelta time_since_playback_for_ukm_; base::TimeDelta time_since_playback_for_ukm_;
......
...@@ -31,10 +31,16 @@ MediaEngagementWebUIBrowserTest.prototype = { ...@@ -31,10 +31,16 @@ MediaEngagementWebUIBrowserTest.prototype = {
GEN('MediaEngagementService* service ='); GEN('MediaEngagementService* service =');
GEN(' MediaEngagementServiceFactory::GetForProfile('); GEN(' MediaEngagementServiceFactory::GetForProfile(');
GEN(' browser()->profile());'); GEN(' browser()->profile());');
GEN('service->RecordVisit(GURL("' + EXAMPLE_URL_1 + '"));'); GEN('MediaEngagementScore score1 =');
GEN('service->RecordVisit(GURL("' + EXAMPLE_URL_2 + '"));'); GEN(' service->CreateEngagementScore(GURL("' + EXAMPLE_URL_1 + '"));');
GEN('service->RecordPlayback(GURL("' + EXAMPLE_URL_1 + '"));'); GEN('score1.IncrementVisits();');
GEN('service->RecordPlayback(GURL("' + EXAMPLE_URL_2 + '"));'); GEN('score1.IncrementMediaPlaybacks();');
GEN('score1.Commit();');
GEN('MediaEngagementScore score2 =');
GEN(' service->CreateEngagementScore(GURL("' + EXAMPLE_URL_2 + '"));');
GEN('score2.IncrementVisits();');
GEN('score2.IncrementMediaPlaybacks();');
GEN('score2.Commit();');
}, },
extraLibraries: [ extraLibraries: [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment