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

[Audible Metrics] Fix concurrent playback histogram

The CloseNewestToExitConcurrentPlayback histogram was not
being recorded because of a race condition between closing
the tab and becoming inaudible and the web contents being
destroyed. This changes the metrics to check if a web
contents was recently audible instead of whether it is
currently audible.

BUG=936196

Change-Id: Ie3c1d8bbb0e11b099acbc2c163aeedf4b1c9d58f
Reviewed-on: https://chromium-review.googlesource.com/c/1490494Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636274}
parent c4328744
...@@ -30,15 +30,16 @@ void AudibleMetrics::UpdateAudibleWebContentsState( ...@@ -30,15 +30,16 @@ void AudibleMetrics::UpdateAudibleWebContentsState(
RemoveAudibleWebContents(web_contents); RemoveAudibleWebContents(web_contents);
} }
void AudibleMetrics::WebContentsDestroyed(const WebContents* web_contents) { void AudibleMetrics::WebContentsDestroyed(const WebContents* web_contents,
if (audible_web_contents_.find(web_contents) == audible_web_contents_.end()) bool recently_audible) {
return; if (base::ContainsKey(audible_web_contents_, web_contents))
RemoveAudibleWebContents(web_contents);
// If we have two web contents and we go down to one, we should record // If we have two web contents and we go down to one, we should record
// whether we destroyed the most recent one. This is used to determine // whether we destroyed the most recent one. This is used to determine
// whether a user closes a new or old tab after starting playback if // whether a user closes a new or old tab after starting playback if
// they have multiple tabs. // they have multiple tabs.
if (audible_web_contents_.size() == 2) { if (audible_web_contents_.size() == 1 && recently_audible) {
ExitConcurrentPlaybackContents value = ExitConcurrentPlaybackContents value =
last_audible_web_contents_.back() == web_contents last_audible_web_contents_.back() == web_contents
? ExitConcurrentPlaybackContents::kMostRecent ? ExitConcurrentPlaybackContents::kMostRecent
...@@ -48,7 +49,7 @@ void AudibleMetrics::WebContentsDestroyed(const WebContents* web_contents) { ...@@ -48,7 +49,7 @@ void AudibleMetrics::WebContentsDestroyed(const WebContents* web_contents) {
"Media.Audible.CloseNewestToExitConcurrentPlayback", value); "Media.Audible.CloseNewestToExitConcurrentPlayback", value);
} }
RemoveAudibleWebContents(web_contents); last_audible_web_contents_.remove(web_contents);
} }
void AudibleMetrics::SetClockForTest(const base::TickClock* test_clock) { void AudibleMetrics::SetClockForTest(const base::TickClock* test_clock) {
...@@ -61,6 +62,10 @@ void AudibleMetrics::AddAudibleWebContents(const WebContents* web_contents) { ...@@ -61,6 +62,10 @@ void AudibleMetrics::AddAudibleWebContents(const WebContents* web_contents) {
1, 10, 11); 1, 10, 11);
audible_web_contents_.insert(web_contents); audible_web_contents_.insert(web_contents);
// Since the web contents is newly audible then move it to the back of the
// last audible web contents list.
last_audible_web_contents_.remove(web_contents);
last_audible_web_contents_.push_back(web_contents); last_audible_web_contents_.push_back(web_contents);
if (audible_web_contents_.size() > 1 && if (audible_web_contents_.size() > 1 &&
...@@ -82,7 +87,6 @@ void AudibleMetrics::AddAudibleWebContents(const WebContents* web_contents) { ...@@ -82,7 +87,6 @@ void AudibleMetrics::AddAudibleWebContents(const WebContents* web_contents) {
void AudibleMetrics::RemoveAudibleWebContents(const WebContents* web_contents) { void AudibleMetrics::RemoveAudibleWebContents(const WebContents* web_contents) {
audible_web_contents_.erase(web_contents); audible_web_contents_.erase(web_contents);
last_audible_web_contents_.remove(web_contents);
if (audible_web_contents_.size() <= 1 && if (audible_web_contents_.size() <= 1 &&
!concurrent_web_contents_start_time_.is_null()) { !concurrent_web_contents_start_time_.is_null()) {
......
...@@ -40,7 +40,8 @@ class CONTENT_EXPORT AudibleMetrics { ...@@ -40,7 +40,8 @@ class CONTENT_EXPORT AudibleMetrics {
void UpdateAudibleWebContentsState(const WebContents* web_contents, void UpdateAudibleWebContentsState(const WebContents* web_contents,
bool audible); bool audible);
void WebContentsDestroyed(const WebContents* web_contents); void WebContentsDestroyed(const WebContents* web_contents,
bool recently_audible);
void SetClockForTest(const base::TickClock* test_clock); void SetClockForTest(const base::TickClock* test_clock);
...@@ -56,9 +57,14 @@ class CONTENT_EXPORT AudibleMetrics { ...@@ -56,9 +57,14 @@ class CONTENT_EXPORT AudibleMetrics {
size_t max_concurrent_audible_web_contents_in_session_; size_t max_concurrent_audible_web_contents_in_session_;
const base::TickClock* clock_; const base::TickClock* clock_;
// This stores the audible web contents in insertion order. // This stores the audible web contents in insertion order. We add a
// web contents to the list when it becomes audible and remove it is
// destroyed.
std::list<const WebContents*> last_audible_web_contents_; std::list<const WebContents*> last_audible_web_contents_;
// Stores all the web contents that are currently audible. We add a web
// contents to the set when it becomes currently audible and remove it when it
// is no longer audible.
std::set<const WebContents*> audible_web_contents_; std::set<const WebContents*> audible_web_contents_;
DISALLOW_COPY_AND_ASSIGN(AudibleMetrics); DISALLOW_COPY_AND_ASSIGN(AudibleMetrics);
......
...@@ -17,11 +17,6 @@ namespace content { ...@@ -17,11 +17,6 @@ namespace content {
namespace { namespace {
static const WebContents* WEB_CONTENTS_0 = reinterpret_cast<WebContents*>(0x00);
static const WebContents* WEB_CONTENTS_1 = reinterpret_cast<WebContents*>(0x01);
static const WebContents* WEB_CONTENTS_2 = reinterpret_cast<WebContents*>(0x10);
static const WebContents* WEB_CONTENTS_3 = reinterpret_cast<WebContents*>(0x11);
static const char* CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM = static const char* CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM =
"Media.Audible.ConcurrentTabsWhenStarting"; "Media.Audible.ConcurrentTabsWhenStarting";
static const char* MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM = static const char* MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM =
...@@ -63,8 +58,16 @@ class AudibleMetricsTest : public RenderViewHostTestHarness { ...@@ -63,8 +58,16 @@ class AudibleMetricsTest : public RenderViewHostTestHarness {
return histogram_tester_.GetHistogramSamplesSinceCreation(name); return histogram_tester_.GetHistogramSamplesSinceCreation(name);
} }
TestWebContents* test_web_contents() { std::unique_ptr<TestWebContents> CreateWebContents() {
return static_cast<TestWebContents*>(web_contents()); return TestWebContents::Create(GetBrowserContext(), nullptr);
}
std::unique_ptr<MediaWebContentsObserver> CreateMediaObserver(
TestWebContents* web_contents) {
std::unique_ptr<MediaWebContentsObserver> media_observer =
std::make_unique<MediaWebContentsObserver>(web_contents);
media_observer->SetAudibleMetricsForTest(audible_metrics());
return media_observer;
} }
private: private:
...@@ -105,7 +108,9 @@ TEST_F(AudibleMetricsTest, CreateAndKillDoesNothing) { ...@@ -105,7 +108,9 @@ TEST_F(AudibleMetricsTest, CreateAndKillDoesNothing) {
} }
TEST_F(AudibleMetricsTest, AudibleStart) { TEST_F(AudibleMetricsTest, AudibleStart) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -132,8 +137,10 @@ TEST_F(AudibleMetricsTest, AudibleStart) { ...@@ -132,8 +137,10 @@ TEST_F(AudibleMetricsTest, AudibleStart) {
} }
TEST_F(AudibleMetricsTest, AudibleStartAndStop) { TEST_F(AudibleMetricsTest, AudibleStartAndStop) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -159,11 +166,13 @@ TEST_F(AudibleMetricsTest, AudibleStartAndStop) { ...@@ -159,11 +166,13 @@ TEST_F(AudibleMetricsTest, AudibleStartAndStop) {
} }
TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) { TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -189,8 +198,10 @@ TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) { ...@@ -189,8 +198,10 @@ TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) {
} }
TEST_F(AudibleMetricsTest, RemoveUnknownTabIsNoOp) { TEST_F(AudibleMetricsTest, RemoveUnknownTabIsNoOp) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), false);
EXPECT_EQ(0, GetHistogramSamplesSinceTestStart( EXPECT_EQ(0, GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM)->TotalCount()); CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM)->TotalCount());
...@@ -201,10 +212,15 @@ TEST_F(AudibleMetricsTest, RemoveUnknownTabIsNoOp) { ...@@ -201,10 +212,15 @@ TEST_F(AudibleMetricsTest, RemoveUnknownTabIsNoOp) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsIncremental) { TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsIncremental) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true); std::unique_ptr<TestWebContents> web_contents_3 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_3.get(), true);
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart( GetHistogramSamplesSinceTestStart(
...@@ -217,13 +233,18 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsIncremental) { ...@@ -217,13 +233,18 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsIncremental) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionKeepTrackOfRemovedTabs) { TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionKeepTrackOfRemovedTabs) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); std::unique_ptr<TestWebContents> web_contents_3 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_3.get(), true);
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart( GetHistogramSamplesSinceTestStart(
...@@ -234,20 +255,25 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionKeepTrackOfRemovedTabs) { ...@@ -234,20 +255,25 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionKeepTrackOfRemovedTabs) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsNotCountedTwice) { TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsNotCountedTwice) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true); std::unique_ptr<TestWebContents> web_contents_3 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_3.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_3.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_3.get(), true);
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart( GetHistogramSamplesSinceTestStart(
...@@ -260,8 +286,11 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsNotCountedTwice) { ...@@ -260,8 +286,11 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsNotCountedTwice) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) { TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -273,8 +302,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) { ...@@ -273,8 +302,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
} }
// Added again: ignored. // Added again: ignored.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -286,8 +315,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) { ...@@ -286,8 +315,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
} }
// Removing both. // Removing both.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -299,8 +328,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) { ...@@ -299,8 +328,8 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
} }
// Adding them after removed, it is counted. // Adding them after removed, it is counted.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -313,8 +342,11 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) { ...@@ -313,8 +342,11 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) { TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
clock()->Advance(base::TimeDelta::FromMilliseconds(1000)); clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
...@@ -323,7 +355,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) { ...@@ -323,7 +355,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
CONCURRENT_TABS_TIME_HISTOGRAM)->TotalCount()); CONCURRENT_TABS_TIME_HISTOGRAM)->TotalCount());
// No longer concurrent. // No longer concurrent.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM)); GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
...@@ -332,7 +364,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) { ...@@ -332,7 +364,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
} }
// Stopping the second tab is a no-op. // Stopping the second tab is a no-op.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM)); GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
...@@ -342,24 +374,28 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) { ...@@ -342,24 +374,28 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
} }
TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRunsAsLongAsTwoAudibleTabs) { TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRunsAsLongAsTwoAudibleTabs) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
clock()->Advance(base::TimeDelta::FromMilliseconds(1000)); clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
clock()->Advance(base::TimeDelta::FromMilliseconds(500)); clock()->Advance(base::TimeDelta::FromMilliseconds(500));
// Mutes one of the three audible tabs. // Mutes one of the three audible tabs.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
// No record because concurrent audible tabs still running. // No record because concurrent audible tabs still running.
EXPECT_EQ(0, GetHistogramSamplesSinceTestStart( EXPECT_EQ(0, GetHistogramSamplesSinceTestStart(
CONCURRENT_TABS_TIME_HISTOGRAM)->TotalCount()); CONCURRENT_TABS_TIME_HISTOGRAM)->TotalCount());
// Mutes the first audible tab. // Mutes the first audible tab.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM)); GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
...@@ -369,73 +405,148 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRunsAsLongAsTwoAudibleTabs) { ...@@ -369,73 +405,148 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRunsAsLongAsTwoAudibleTabs) {
} }
TEST_F(AudibleMetricsTest, MediaWebContentsObserver_Audible_Muted) { TEST_F(AudibleMetricsTest, MediaWebContentsObserver_Audible_Muted) {
MediaWebContentsObserver media_observer(test_web_contents()); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
media_observer.SetAudibleMetricsForTest(audible_metrics()); std::unique_ptr<MediaWebContentsObserver> media_observer =
CreateMediaObserver(web_contents.get());
test_web_contents()->SetAudioMuted(true); web_contents->SetAudioMuted(true);
test_web_contents() web_contents->audio_stream_monitor()->set_is_currently_audible_for_testing(
->audio_stream_monitor() true);
->set_is_currently_audible_for_testing(true);
EXPECT_TRUE( EXPECT_TRUE(web_contents->audio_stream_monitor()->IsCurrentlyAudible());
test_web_contents()->audio_stream_monitor()->IsCurrentlyAudible()); EXPECT_TRUE(web_contents->IsAudioMuted());
EXPECT_TRUE(test_web_contents()->IsAudioMuted());
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
media_observer.MaybeUpdateAudibleState(); media_observer->MaybeUpdateAudibleState();
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
} }
TEST_F(AudibleMetricsTest, MediaWebContentsObserver_Audible_NotMuted) { TEST_F(AudibleMetricsTest, MediaWebContentsObserver_Audible_NotMuted) {
MediaWebContentsObserver media_observer(test_web_contents()); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
media_observer.SetAudibleMetricsForTest(audible_metrics()); std::unique_ptr<MediaWebContentsObserver> media_observer =
CreateMediaObserver(web_contents.get());
test_web_contents() web_contents->audio_stream_monitor()->set_is_currently_audible_for_testing(
->audio_stream_monitor() true);
->set_is_currently_audible_for_testing(true);
EXPECT_TRUE( EXPECT_TRUE(web_contents->audio_stream_monitor()->IsCurrentlyAudible());
test_web_contents()->audio_stream_monitor()->IsCurrentlyAudible()); EXPECT_FALSE(web_contents->IsAudioMuted());
EXPECT_FALSE(test_web_contents()->IsAudioMuted());
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
media_observer.MaybeUpdateAudibleState(); media_observer->MaybeUpdateAudibleState();
EXPECT_EQ(1, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(1, audible_metrics()->GetAudibleWebContentsSizeForTest());
} }
TEST_F(AudibleMetricsTest, MediaWebContentsObserver_NotAudible_Muted) { TEST_F(AudibleMetricsTest, MediaWebContentsObserver_NotAudible_Muted) {
MediaWebContentsObserver media_observer(test_web_contents()); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
media_observer.SetAudibleMetricsForTest(audible_metrics()); std::unique_ptr<MediaWebContentsObserver> media_observer =
CreateMediaObserver(web_contents.get());
test_web_contents()->SetAudioMuted(true); web_contents->SetAudioMuted(true);
EXPECT_FALSE( EXPECT_FALSE(web_contents->audio_stream_monitor()->IsCurrentlyAudible());
test_web_contents()->audio_stream_monitor()->IsCurrentlyAudible()); EXPECT_TRUE(web_contents->IsAudioMuted());
EXPECT_TRUE(test_web_contents()->IsAudioMuted());
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
media_observer.MaybeUpdateAudibleState(); media_observer->MaybeUpdateAudibleState();
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
} }
TEST_F(AudibleMetricsTest, MediaWebContentsObserver_NotAudible_NotMuted) { TEST_F(AudibleMetricsTest, MediaWebContentsObserver_NotAudible_NotMuted) {
MediaWebContentsObserver media_observer(test_web_contents()); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
media_observer.SetAudibleMetricsForTest(audible_metrics()); std::unique_ptr<MediaWebContentsObserver> media_observer =
CreateMediaObserver(web_contents.get());
EXPECT_FALSE( EXPECT_FALSE(web_contents->audio_stream_monitor()->IsCurrentlyAudible());
test_web_contents()->audio_stream_monitor()->IsCurrentlyAudible()); EXPECT_FALSE(web_contents->IsAudioMuted());
EXPECT_FALSE(test_web_contents()->IsAudioMuted());
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
media_observer.MaybeUpdateAudibleState(); media_observer->MaybeUpdateAudibleState();
EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest()); EXPECT_EQ(0, audible_metrics()->GetAudibleWebContentsSizeForTest());
} }
TEST_F(AudibleMetricsTest, MediaWebContentsObserver_Destroyed_RecentlyAudible) {
std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
std::unique_ptr<MediaWebContentsObserver> media_observer_1 =
CreateMediaObserver(web_contents_1.get());
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
// Even though |web_contents_1| is no longer audible it was still recently
// audible so we should count metrics from it.
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), false);
web_contents_1->audio_stream_monitor()->set_was_recently_audible_for_testing(
true);
media_observer_1->WebContentsDestroyed();
{
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CLOSE_NEWEST_TAB_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(
1, samples->GetCount(static_cast<int>(
AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent)));
}
}
TEST_F(AudibleMetricsTest,
MediaWebContentsObserver_Destroyed_RecentlyAudibleButMuted) {
std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
std::unique_ptr<MediaWebContentsObserver> media_observer_1 =
CreateMediaObserver(web_contents_1.get());
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
// Even though |web_contents_1| was recently audible it was also muted so we
// should ignore it.
web_contents_1->SetAudioMuted(true);
web_contents_1->audio_stream_monitor()->set_was_recently_audible_for_testing(
true);
media_observer_1->WebContentsDestroyed();
{
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CLOSE_NEWEST_TAB_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
EXPECT_EQ(0, samples->GetCount(0));
}
}
TEST_F(AudibleMetricsTest,
MediaWebContentsObserver_Destroyed_NotRecentlyAudible) {
std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
std::unique_ptr<MediaWebContentsObserver> media_observer_1 =
CreateMediaObserver(web_contents_1.get());
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
// |web_contents_1| was not recently audible so no metrics should be recorded.
media_observer_1->WebContentsDestroyed();
{
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CLOSE_NEWEST_TAB_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
EXPECT_EQ(0, samples->GetCount(0));
}
}
TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_IgnoreNotAudible) { TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_IgnoreNotAudible) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_0); audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents.get(), false);
audible_metrics()->WebContentsDestroyed(web_contents.get(), false);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -445,11 +556,15 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_IgnoreNotAudible) { ...@@ -445,11 +556,15 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_IgnoreNotAudible) {
} }
TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) { TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_2); audible_metrics()->WebContentsDestroyed(web_contents_2.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -460,7 +575,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) { ...@@ -460,7 +575,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) {
AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent))); AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent)));
} }
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_1); audible_metrics()->WebContentsDestroyed(web_contents_1.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -471,7 +586,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) { ...@@ -471,7 +586,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) {
AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent))); AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent)));
} }
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_0); audible_metrics()->WebContentsDestroyed(web_contents_0.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -484,11 +599,15 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) { ...@@ -484,11 +599,15 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Newest) {
} }
TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) { TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true); std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true); std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true); std::unique_ptr<TestWebContents> web_contents_2 = CreateWebContents();
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_1); audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_2.get(), true);
audible_metrics()->WebContentsDestroyed(web_contents_1.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -499,7 +618,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) { ...@@ -499,7 +618,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) {
AudibleMetrics::ExitConcurrentPlaybackContents::kOlder))); AudibleMetrics::ExitConcurrentPlaybackContents::kOlder)));
} }
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_0); audible_metrics()->WebContentsDestroyed(web_contents_0.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -509,7 +628,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) { ...@@ -509,7 +628,7 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) {
AudibleMetrics::ExitConcurrentPlaybackContents::kOlder))); AudibleMetrics::ExitConcurrentPlaybackContents::kOlder)));
} }
audible_metrics()->WebContentsDestroyed(WEB_CONTENTS_2); audible_metrics()->WebContentsDestroyed(web_contents_2.get(), true);
{ {
std::unique_ptr<base::HistogramSamples> samples( std::unique_ptr<base::HistogramSamples> samples(
...@@ -520,4 +639,26 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) { ...@@ -520,4 +639,26 @@ TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_Old) {
} }
} }
TEST_F(AudibleMetricsTest, CloseNewestAudibleTabHistogram_ToggleAudibility) {
std::unique_ptr<TestWebContents> web_contents_0 = CreateWebContents();
std::unique_ptr<TestWebContents> web_contents_1 = CreateWebContents();
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_1.get(), true);
// Toggling audibility should make |web_contents_0| the most recently audible.
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), false);
audible_metrics()->UpdateAudibleWebContentsState(web_contents_0.get(), true);
audible_metrics()->WebContentsDestroyed(web_contents_0.get(), true);
{
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CLOSE_NEWEST_TAB_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(
1, samples->GetCount(static_cast<int>(
AudibleMetrics::ExitConcurrentPlaybackContents::kMostRecent)));
}
}
} // namespace content } // namespace content
...@@ -72,7 +72,12 @@ MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents) ...@@ -72,7 +72,12 @@ MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
MediaWebContentsObserver::~MediaWebContentsObserver() = default; MediaWebContentsObserver::~MediaWebContentsObserver() = default;
void MediaWebContentsObserver::WebContentsDestroyed() { void MediaWebContentsObserver::WebContentsDestroyed() {
audible_metrics_->WebContentsDestroyed(web_contents()); AudioStreamMonitor* audio_stream_monitor =
web_contents_impl()->audio_stream_monitor();
audible_metrics_->WebContentsDestroyed(
web_contents(), audio_stream_monitor->WasRecentlyAudible() &&
!web_contents()->IsAudioMuted());
} }
void MediaWebContentsObserver::RenderFrameDeleted( void MediaWebContentsObserver::RenderFrameDeleted(
......
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