summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordominickn <dominickn@chromium.org>2015-12-15 03:35:58 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-15 11:36:43 +0000
commit3e7cdbf1b379398f5e1a710d22629fdf14df02cf (patch)
treefe1f8f626d8ed6d9bda0be8b82eee1556ad53187
parentbff460660c6a1f24141f379c998b4fa774dc6691 (diff)
downloadchromium_src-3e7cdbf1b379398f5e1a710d22629fdf14df02cf.zip
chromium_src-3e7cdbf1b379398f5e1a710d22629fdf14df02cf.tar.gz
chromium_src-3e7cdbf1b379398f5e1a710d22629fdf14df02cf.tar.bz2
Implement a site engagement backend for app banner triggering.
This CL adds a flag and field trial group enabling app banners to use the site engagement service for triggering. This allows banners to be triggered based on broader criteria than simply navigations. An additional UMA histogram is also added to compare the time from when an origin was first recorded as visited by the app banner system until the time when a banner should be shown. BUG=553858 Committed: https://crrev.com/936894045ed2aed9ee67b9c371a9eff94912c346 Cr-Commit-Position: refs/heads/master@{#363100} Review URL: https://codereview.chromium.org/1413343008 Cr-Commit-Position: refs/heads/master@{#365227}
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher.cc3
-rw-r--r--chrome/browser/banners/app_banner_data_fetcher_browsertest.cc7
-rw-r--r--chrome/browser/banners/app_banner_metrics.cc24
-rw-r--r--chrome/browser/banners/app_banner_metrics.h7
-rw-r--r--chrome/browser/banners/app_banner_settings_helper.cc108
-rw-r--r--chrome/browser/banners/app_banner_settings_helper.h12
-rw-r--r--chrome/browser/banners/app_banner_settings_helper_unittest.cc96
-rw-r--r--chrome/browser/engagement/site_engagement_helper_unittest.cc172
-rw-r--r--chrome/browser/engagement/site_engagement_service.cc4
-rw-r--r--chrome/browser/engagement/site_engagement_service.h1
-rw-r--r--chrome/common/chrome_switches.cc6
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--tools/metrics/histograms/histograms.xml10
13 files changed, 341 insertions, 110 deletions
diff --git a/chrome/browser/banners/app_banner_data_fetcher.cc b/chrome/browser/banners/app_banner_data_fetcher.cc
index 0090d10..321e8d3 100644
--- a/chrome/browser/banners/app_banner_data_fetcher.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher.cc
@@ -188,6 +188,9 @@ void AppBannerDataFetcher::OnBannerPromptReply(
return;
}
+ AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
+ web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
+
// Definitely going to show the banner now.
FOR_EACH_OBSERVER(Observer, observer_list_,
OnDecidedWhetherToShow(this, true));
diff --git a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
index b37df5f..c868268 100644
--- a/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher_browsertest.cc
@@ -9,8 +9,10 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
+#include "base/test/histogram_tester.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/browser/banners/app_banner_data_fetcher_desktop.h"
+#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -97,6 +99,7 @@ class AppBannerDataFetcherBrowserTest : public InProcessBrowserTest,
weak_factory_.GetWeakPtr(),
128, 128));
+ base::HistogramTester histograms;
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
scoped_ptr<TestObserver> observer(new TestObserver(fetcher.get(),
@@ -107,6 +110,10 @@ class AppBannerDataFetcherBrowserTest : public InProcessBrowserTest,
EXPECT_EQ(expected_non_web_platform, non_web_platform_);
EXPECT_EQ(expected_to_show, observer->will_show());
ASSERT_FALSE(fetcher->is_active());
+
+ // If showing the banner, ensure that the minutes histogram is recorded.
+ histograms.ExpectTotalCount(banners::kMinutesHistogram,
+ (observer->will_show() ? 1 : 0));
}
void RunBannerTest(const std::string& manifest_page,
diff --git a/chrome/browser/banners/app_banner_metrics.cc b/chrome/browser/banners/app_banner_metrics.cc
index 5ab6f59..f9bbd34 100644
--- a/chrome/browser/banners/app_banner_metrics.cc
+++ b/chrome/browser/banners/app_banner_metrics.cc
@@ -4,32 +4,48 @@
#include "chrome/browser/banners/app_banner_metrics.h"
+#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
namespace banners {
+const char kDismissEventHistogram[] = "AppBanners.DismissEvent";
+const char kDisplayEventHistogram[] = "AppBanners.DisplayEvent";
+const char kInstallEventHistogram[] = "AppBanners.InstallEvent";
+const char kMinutesHistogram[] =
+ "AppBanners.MinutesFromFirstVisitToBannerShown";
+const char kUserResponseHistogram[] = "AppBanners.UserResponse";
+
void TrackDismissEvent(int event) {
DCHECK_LT(DISMISS_EVENT_MIN, event);
DCHECK_LT(event, DISMISS_EVENT_MAX);
- UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.DismissEvent", event);
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kDismissEventHistogram, event);
}
void TrackDisplayEvent(int event) {
DCHECK_LT(DISPLAY_EVENT_MIN, event);
DCHECK_LT(event, DISPLAY_EVENT_MAX);
- UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.DisplayEvent", event);
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kDisplayEventHistogram, event);
}
void TrackInstallEvent(int event) {
DCHECK_LT(INSTALL_EVENT_MIN, event);
DCHECK_LT(event, INSTALL_EVENT_MAX);
- UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.InstallEvent", event);
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kInstallEventHistogram, event);
+}
+
+void TrackMinutesFromFirstVisitToBannerShown(int minutes) {
+ // Histogram ranges from 1 minute to the number of minutes in 21 days.
+ // This is one more day than the decay length of time for site engagement,
+ // and seven more days than the expiry of visits for the app banner
+ // navigation heuristic.
+ UMA_HISTOGRAM_CUSTOM_COUNTS(kMinutesHistogram, minutes, 1, 30240, 100);
}
void TrackUserResponse(int event) {
DCHECK_LT(USER_RESPONSE_MIN, event);
DCHECK_LT(event, USER_RESPONSE_MAX);
- UMA_HISTOGRAM_SPARSE_SLOWLY("AppBanners.UserResponse", event);
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kUserResponseHistogram, event);
}
} // namespace banners
diff --git a/chrome/browser/banners/app_banner_metrics.h b/chrome/browser/banners/app_banner_metrics.h
index 7c78179..0b0939e 100644
--- a/chrome/browser/banners/app_banner_metrics.h
+++ b/chrome/browser/banners/app_banner_metrics.h
@@ -57,9 +57,16 @@ enum UserResponse {
USER_RESPONSE_MAX = 7,
};
+extern const char kDismissEventHistogram[];
+extern const char kDisplayEventHistogram[];
+extern const char kInstallEventHistogram[];
+extern const char kMinutesHistogram[];
+extern const char kUserResponseHistogram[];
+
void TrackDismissEvent(int event);
void TrackDisplayEvent(int event);
void TrackInstallEvent(int event);
+void TrackMinutesFromFirstVisitToBannerShown(int minutes);
void TrackUserResponse(int event);
}; // namespace banners
diff --git a/chrome/browser/banners/app_banner_settings_helper.cc b/chrome/browser/banners/app_banner_settings_helper.cc
index 2f0bb43..aca24f6 100644
--- a/chrome/browser/banners/app_banner_settings_helper.cc
+++ b/chrome/browser/banners/app_banner_settings_helper.cc
@@ -8,11 +8,14 @@
#include <string>
#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "chrome/browser/banners/app_banner_data_fetcher.h"
#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -63,9 +66,11 @@ const char kBannerParamsDirectKey[] = "direct";
const char kBannerParamsIndirectKey[] = "indirect";
const char kBannerParamsTotalKey[] = "total";
const char kBannerParamsMinutesKey[] = "minutes";
+const char kBannerSiteEngagementParamsKey[] = "app_banner_triggering";
+const char kBannerSiteEngagementParamsTotalKey[] =
+ "app_banner_triggering_total";
-// Total site engagements where a banner could have been shown before
-// a banner will actually be triggered.
+// Total engagement score required before a banner will actually be triggered.
double gTotalEngagementToTrigger = 2;
// Engagement weight assigned to direct and indirect navigations.
@@ -115,10 +120,26 @@ double GetEventEngagement(ui::PageTransition transition_type) {
}
}
+// Queries variations for the maximum site engagement score required to trigger
+// the banner showing.
+void UpdateSiteEngagementToTrigger() {
+ std::string total_param = variations::GetVariationParamValue(
+ SiteEngagementService::kEngagementParams,
+ kBannerSiteEngagementParamsTotalKey);
+
+ if (!total_param.empty()) {
+ double total_engagement = -1;
+
+ if (base::StringToDouble(total_param, &total_engagement) &&
+ total_engagement > 0) {
+ AppBannerSettingsHelper::SetTotalEngagementToTrigger(total_engagement);
+ }
+ }
+}
+
// Queries variations for updates to the default engagement values assigned
// to direct and indirect navigations.
void UpdateEngagementWeights() {
- std::map<std::string, std::string> params;
std::string direct_param = variations::GetVariationParamValue(
kBannerParamsKey, kBannerParamsDirectKey);
std::string indirect_param = variations::GetVariationParamValue(
@@ -160,6 +181,16 @@ void UpdateMinutesBetweenVisits() {
}
}
+// Returns the site engagement karma score for the given origin URL under the
+// current profile.
+double GetSiteEngagementScoreForOrigin(
+ content::WebContents* web_contents,
+ const GURL& origin_url) {
+ SiteEngagementService* service = SiteEngagementService::Get(
+ Profile::FromBrowserContext(web_contents->GetBrowserContext()));
+ return service ? service->GetScore(origin_url) : 0;
+}
+
} // namespace
void AppBannerSettingsHelper::ClearHistoryForURLs(
@@ -352,6 +383,10 @@ bool AppBannerSettingsHelper::ShouldShowBanner(
return true;
}
+ // Never show a banner when the package name or URL is empty.
+ if (package_name_or_start_url.empty())
+ return false;
+
// Don't show if it has been added to the homescreen.
base::Time added_time =
GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url,
@@ -382,14 +417,17 @@ bool AppBannerSettingsHelper::ShouldShowBanner(
return false;
}
- std::vector<BannerEvent> could_show_events = GetCouldShowBannerEvents(
- web_contents, origin_url, package_name_or_start_url);
-
- // Return true if the total engagement of each applicable could show event
- // meets the trigger threshold.
double total_engagement = 0;
- for (const auto& event : could_show_events)
- total_engagement += event.engagement;
+ if (ShouldUseSiteEngagementScore()) {
+ total_engagement =
+ GetSiteEngagementScoreForOrigin(web_contents, origin_url);
+ } else {
+ std::vector<BannerEvent> could_show_events = GetCouldShowBannerEvents(
+ web_contents, origin_url, package_name_or_start_url);
+
+ for (const auto& event : could_show_events)
+ total_engagement += event.engagement;
+ }
if (total_engagement < gTotalEngagementToTrigger) {
banners::TrackDisplayEvent(banners::DISPLAY_EVENT_NOT_VISITED_ENOUGH);
@@ -405,8 +443,6 @@ AppBannerSettingsHelper::GetCouldShowBannerEvents(
const GURL& origin_url,
const std::string& package_name_or_start_url) {
std::vector<BannerEvent> result;
- if (package_name_or_start_url.empty())
- return result;
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
@@ -454,9 +490,6 @@ base::Time AppBannerSettingsHelper::GetSingleBannerEvent(
DCHECK(event != APP_BANNER_EVENT_COULD_SHOW);
DCHECK(event < APP_BANNER_EVENT_NUM_EVENTS);
- if (package_name_or_start_url.empty())
- return base::Time();
-
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
HostContentSettingsMap* settings =
@@ -480,6 +513,21 @@ base::Time AppBannerSettingsHelper::GetSingleBannerEvent(
return base::Time::FromInternalValue(internal_time);
}
+void AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
+ content::WebContents* web_contents,
+ const GURL& origin_url,
+ const std::string& package_name_or_start_url,
+ base::Time time) {
+ std::vector<BannerEvent> could_show_events = GetCouldShowBannerEvents(
+ web_contents, origin_url, package_name_or_start_url);
+
+ int minutes = 0;
+ if (could_show_events.size())
+ minutes = (time - could_show_events[0].time).InMinutes();
+
+ banners::TrackMinutesFromFirstVisitToBannerShown(minutes);
+}
+
void AppBannerSettingsHelper::SetEngagementWeights(double direct_engagement,
double indirect_engagement) {
gDirectNavigationEngagement = direct_engagement;
@@ -523,6 +571,32 @@ base::Time AppBannerSettingsHelper::BucketTimeToResolution(
}
void AppBannerSettingsHelper::UpdateFromFieldTrial() {
- UpdateEngagementWeights();
- UpdateMinutesBetweenVisits();
+ // If we are using the site engagement score, only extract the total
+ // engagement to trigger from the params variations.
+ if (ShouldUseSiteEngagementScore()) {
+ UpdateSiteEngagementToTrigger();
+ } else {
+ UpdateEngagementWeights();
+ UpdateMinutesBetweenVisits();
+ }
+}
+
+bool AppBannerSettingsHelper::ShouldUseSiteEngagementScore() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSiteEngagementAppBanner)) {
+ return true;
+ }
+
+ // This experiment is controlled under the same key as the broader site
+ // engagement experiment rather than the banner experiment. This avoids cross
+ // pollution with other site engagement experiments. However, this experiment
+ // must only be active when there is one singular group under the banner
+ // experiment, otherwise the banner and site engagement banner experiments
+ // will conflict.
+ //
+ // Making the experiment active when a variations key is present allows us
+ // to have experiments which enable multiple features under site engagement.
+ std::string param = variations::GetVariationParamValue(
+ SiteEngagementService::kEngagementParams, kBannerSiteEngagementParamsKey);
+ return !param.empty();
}
diff --git a/chrome/browser/banners/app_banner_settings_helper.h b/chrome/browser/banners/app_banner_settings_helper.h
index 3ff877c..b46bc16 100644
--- a/chrome/browser/banners/app_banner_settings_helper.h
+++ b/chrome/browser/banners/app_banner_settings_helper.h
@@ -117,6 +117,14 @@ class AppBannerSettingsHelper {
const std::string& package_name_or_start_url,
AppBannerEvent event);
+ // Record a UMA statistic measuring the minutes between the first visit to the
+ // site and the first showing of the banner.
+ static void RecordMinutesFromFirstVisitToShow(
+ content::WebContents* web_contents,
+ const GURL& origin_url,
+ const std::string& package_name_or_start_url,
+ base::Time time);
+
// Set the engagement weights assigned to direct and indirect navigations.
static void SetEngagementWeights(double direct_engagement,
double indirect_engagement);
@@ -137,6 +145,10 @@ class AppBannerSettingsHelper {
// Updates all values from field trial.
static void UpdateFromFieldTrial();
+ // Returns true if the app banner trigger condition should use the site
+ // engagement score instead of the navigation-based heuristic.
+ static bool ShouldUseSiteEngagementScore();
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AppBannerSettingsHelper);
};
diff --git a/chrome/browser/banners/app_banner_settings_helper_unittest.cc b/chrome/browser/banners/app_banner_settings_helper_unittest.cc
index 82550f1..254758a 100644
--- a/chrome/browser/banners/app_banner_settings_helper_unittest.cc
+++ b/chrome/browser/banners/app_banner_settings_helper_unittest.cc
@@ -4,8 +4,14 @@
#include <vector>
+#include "base/command_line.h"
+#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/banners/app_banner_settings_helper.h"
+#include "chrome/browser/engagement/site_engagement_service.h"
+#include "chrome/browser/engagement/site_engagement_service_factory.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
#include "ui/base/page_transition_types.h"
namespace {
@@ -731,3 +737,93 @@ TEST_F(AppBannerSettingsHelperTest, OperatesOnOrigins) {
EXPECT_TRUE(AppBannerSettingsHelper::ShouldShowBanner(
web_contents(), url, kTestPackageName, reference_time));
}
+
+TEST_F(AppBannerSettingsHelperTest, ShouldShowWithHigherTotal) {
+ AppBannerSettingsHelper::SetEngagementWeights(1, 1);
+ AppBannerSettingsHelper::SetTotalEngagementToTrigger(5);
+ GURL url(kTestURL);
+ NavigateAndCommit(url);
+
+ base::Time reference_time = GetReferenceTime();
+ base::Time second_day = reference_time + base::TimeDelta::FromDays(1);
+ base::Time third_day = reference_time + base::TimeDelta::FromDays(2);
+ base::Time fourth_day = reference_time + base::TimeDelta::FromDays(3);
+ base::Time fifth_day = reference_time + base::TimeDelta::FromDays(4);
+
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ // It should take five visits to trigger the banner.
+ AppBannerSettingsHelper::RecordBannerCouldShowEvent(
+ web_contents(), url, kTestPackageName, reference_time,
+ ui::PAGE_TRANSITION_LINK);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ AppBannerSettingsHelper::RecordBannerCouldShowEvent(
+ web_contents(), url, kTestPackageName, second_day,
+ ui::PAGE_TRANSITION_TYPED);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, second_day));
+
+ AppBannerSettingsHelper::RecordBannerCouldShowEvent(
+ web_contents(), url, kTestPackageName, third_day,
+ ui::PAGE_TRANSITION_GENERATED);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, third_day));
+
+ AppBannerSettingsHelper::RecordBannerCouldShowEvent(
+ web_contents(), url, kTestPackageName, fourth_day,
+ ui::PAGE_TRANSITION_LINK);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, fourth_day));
+
+ // Visit the site again; now it should be shown.
+ AppBannerSettingsHelper::RecordBannerCouldShowEvent(
+ web_contents(), url, kTestPackageName, fifth_day,
+ ui::PAGE_TRANSITION_TYPED);
+ EXPECT_TRUE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, fifth_day));
+}
+
+// Test that the banner triggers correctly using site engagement.
+TEST_F(AppBannerSettingsHelperTest, SiteEngagementTrigger) {
+ AppBannerSettingsHelper::SetTotalEngagementToTrigger(2);
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->AppendSwitch(switches::kEnableSiteEngagementAppBanner);
+
+ SiteEngagementService* service =
+ SiteEngagementServiceFactory::GetForProfile(profile());
+ DCHECK(service);
+
+ // Not used, but needed for method call.
+ base::Time reference_time = GetReferenceTime();
+ GURL url(kTestURL);
+
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ service->AddPoints(url, 1);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ service->AddPoints(url, 1);
+ EXPECT_TRUE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ AppBannerSettingsHelper::SetTotalEngagementToTrigger(5);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ service->AddPoints(url, 1.5);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ service->AddPoints(url, 0.5);
+ EXPECT_FALSE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+
+ service->AddPoints(url, 1.5);
+ EXPECT_TRUE(AppBannerSettingsHelper::ShouldShowBanner(
+ web_contents(), url, kTestPackageName, reference_time));
+}
diff --git a/chrome/browser/engagement/site_engagement_helper_unittest.cc b/chrome/browser/engagement/site_engagement_helper_unittest.cc
index edcbdb2..e18b1bf 100644
--- a/chrome/browser/engagement/site_engagement_helper_unittest.cc
+++ b/chrome/browser/engagement/site_engagement_helper_unittest.cc
@@ -18,15 +18,17 @@
class SiteEngagementHelperTest : public BrowserWithTestWindowTest {
public:
- // Create a SiteEngagementHelper. Called here as friend class methods cannot
- // be called in tests.
- scoped_ptr<SiteEngagementHelper> CreateHelper(
- content::WebContents* web_contents) {
- scoped_ptr<SiteEngagementHelper> helper(
- new SiteEngagementHelper(web_contents));
- DCHECK(helper.get());
-
- return helper.Pass();
+ void SetUp() override {
+ BrowserWithTestWindowTest::SetUp();
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableSiteEngagementService);
+ }
+
+ SiteEngagementHelper* GetHelper(content::WebContents* web_contents) {
+ SiteEngagementHelper* helper =
+ SiteEngagementHelper::FromWebContents(web_contents);
+ DCHECK(helper);
+ return helper;
}
void TrackingStarted(SiteEngagementHelper* helper) {
@@ -94,41 +96,41 @@ class SiteEngagementHelperTest : public BrowserWithTestWindowTest {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
SiteEngagementService* service =
SiteEngagementServiceFactory::GetForProfile(browser()->profile());
DCHECK(service);
// Check that navigation triggers engagement.
NavigateWithDisposition(url1, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate a user input trigger and ensure it is treated correctly.
- HandleUserInputAndRestartTracking(helper.get(), type);
+ HandleUserInputAndRestartTracking(helper, type);
EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate three inputs , and ensure they are treated correctly.
- HandleUserInputAndRestartTracking(helper.get(), type);
- HandleUserInputAndRestartTracking(helper.get(), type);
- HandleUserInputAndRestartTracking(helper.get(), type);
+ HandleUserInputAndRestartTracking(helper, type);
+ HandleUserInputAndRestartTracking(helper, type);
+ HandleUserInputAndRestartTracking(helper, type);
EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate inputs for a different link.
NavigateWithDisposition(url2, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
EXPECT_DOUBLE_EQ(1.2, service->GetTotalEngagementPoints());
- HandleUserInputAndRestartTracking(helper.get(), type);
+ HandleUserInputAndRestartTracking(helper, type);
EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2));
EXPECT_DOUBLE_EQ(1.25, service->GetTotalEngagementPoints());
@@ -158,48 +160,48 @@ TEST_F(SiteEngagementHelperTest, MediaEngagementAccumulation) {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
SiteEngagementService* service =
SiteEngagementServiceFactory::GetForProfile(browser()->profile());
DCHECK(service);
NavigateWithDisposition(url1, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate a foreground media input and ensure it is treated correctly.
- HandleMediaPlaying(helper.get(), false);
+ HandleMediaPlaying(helper, false);
EXPECT_DOUBLE_EQ(0.52, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate continual media playing, and ensure it is treated correctly.
- HandleMediaPlaying(helper.get(), false);
- HandleMediaPlaying(helper.get(), false);
- HandleMediaPlaying(helper.get(), false);
+ HandleMediaPlaying(helper, false);
+ HandleMediaPlaying(helper, false);
+ HandleMediaPlaying(helper, false);
EXPECT_DOUBLE_EQ(0.58, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate backgrounding the media.
- HandleMediaPlaying(helper.get(), true);
- HandleMediaPlaying(helper.get(), true);
+ HandleMediaPlaying(helper, true);
+ HandleMediaPlaying(helper, true);
EXPECT_DOUBLE_EQ(0.60, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
// Simulate inputs for a different link.
NavigateWithDisposition(url2, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
EXPECT_DOUBLE_EQ(1.1, service->GetTotalEngagementPoints());
- HandleMediaPlaying(helper.get(), false);
- HandleMediaPlaying(helper.get(), false);
+ HandleMediaPlaying(helper, false);
+ HandleMediaPlaying(helper, false);
EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.54, service->GetScore(url2));
EXPECT_DOUBLE_EQ(1.14, service->GetTotalEngagementPoints());
@@ -213,14 +215,14 @@ TEST_F(SiteEngagementHelperTest, MediaEngagement) {
browser()->tab_strip_model()->GetActiveWebContents();
base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
- SetMediaTrackerPauseTimer(helper.get(), make_scoped_ptr(media_tracker_timer));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
+ SetMediaTrackerPauseTimer(helper, make_scoped_ptr(media_tracker_timer));
SiteEngagementService* service =
SiteEngagementServiceFactory::GetForProfile(browser()->profile());
DCHECK(service);
NavigateWithDisposition(url1, CURRENT_TAB);
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
EXPECT_DOUBLE_EQ(0.50, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -237,7 +239,7 @@ TEST_F(SiteEngagementHelperTest, MediaEngagement) {
EXPECT_EQ(0, service->GetScore(url2));
EXPECT_TRUE(media_tracker_timer->IsRunning());
- MediaStoppedPlaying(helper.get());
+ MediaStoppedPlaying(helper);
media_tracker_timer->Fire();
EXPECT_DOUBLE_EQ(0.53, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -249,7 +251,7 @@ TEST_F(SiteEngagementHelperTest, MediaEngagement) {
EXPECT_EQ(0, service->GetScore(url2));
EXPECT_TRUE(media_tracker_timer->IsRunning());
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
media_tracker_timer->Fire();
EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -260,7 +262,7 @@ TEST_F(SiteEngagementHelperTest, MediaEngagement) {
EXPECT_EQ(0.5, service->GetScore(url2));
EXPECT_FALSE(media_tracker_timer->IsRunning());
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
media_tracker_timer->Fire();
EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
EXPECT_EQ(0.52, service->GetScore(url2));
@@ -272,7 +274,7 @@ TEST_F(SiteEngagementHelperTest, MediaEngagement) {
EXPECT_EQ(0.53, service->GetScore(url2));
EXPECT_TRUE(media_tracker_timer->IsRunning());
- MediaStoppedPlaying(helper.get());
+ MediaStoppedPlaying(helper);
web_contents->WasShown();
media_tracker_timer->Fire();
EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
@@ -287,7 +289,7 @@ TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
SiteEngagementService* service =
SiteEngagementServiceFactory::GetForProfile(browser()->profile());
DCHECK(service);
@@ -299,7 +301,7 @@ TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) {
0);
NavigateWithDisposition(url1, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -308,16 +310,13 @@ TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) {
histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram,
SiteEngagementMetrics::ENGAGEMENT_NAVIGATION, 1);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::RawKeyDown);
- HandleUserInputAndRestartTracking(helper.get(),
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::RawKeyDown);
+ HandleUserInputAndRestartTracking(helper,
blink::WebInputEvent::GestureTapDown);
- HandleUserInputAndRestartTracking(helper.get(),
+ HandleUserInputAndRestartTracking(helper,
blink::WebInputEvent::GestureTapDown);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::RawKeyDown);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::MouseDown);
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::RawKeyDown);
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::MouseDown);
EXPECT_DOUBLE_EQ(0.75, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -333,14 +332,12 @@ TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) {
SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE,
2);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::MouseWheel);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::MouseDown);
- HandleMediaPlaying(helper.get(), true);
- HandleUserInputAndRestartTracking(helper.get(),
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::MouseWheel);
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::MouseDown);
+ HandleMediaPlaying(helper, true);
+ HandleUserInputAndRestartTracking(helper,
blink::WebInputEvent::GestureTapDown);
- HandleMediaPlaying(helper.get(), false);
+ HandleMediaPlaying(helper, false);
EXPECT_DOUBLE_EQ(0.93, service->GetScore(url1));
EXPECT_EQ(0, service->GetScore(url2));
@@ -361,16 +358,15 @@ TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) {
1);
NavigateWithDisposition(url2, CURRENT_TAB);
- TrackingStarted(helper.get());
+ TrackingStarted(helper);
EXPECT_DOUBLE_EQ(0.93, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
EXPECT_DOUBLE_EQ(1.43, service->GetTotalEngagementPoints());
- HandleUserInputAndRestartTracking(helper.get(),
+ HandleUserInputAndRestartTracking(helper,
blink::WebInputEvent::GestureTapDown);
- HandleUserInputAndRestartTracking(helper.get(),
- blink::WebInputEvent::RawKeyDown);
+ HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::RawKeyDown);
EXPECT_DOUBLE_EQ(0.93, service->GetScore(url1));
EXPECT_DOUBLE_EQ(0.6, service->GetScore(url2));
@@ -395,9 +391,9 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
- SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer));
- SetMediaTrackerPauseTimer(helper.get(), make_scoped_ptr(media_tracker_timer));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
+ SetInputTrackerPauseTimer(helper, make_scoped_ptr(input_tracker_timer));
+ SetMediaTrackerPauseTimer(helper, make_scoped_ptr(media_tracker_timer));
SiteEngagementService* service =
SiteEngagementServiceFactory::GetForProfile(browser()->profile());
@@ -410,11 +406,11 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
// Input timer should be running for navigation delay, but media timer is
// inactive.
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
EXPECT_FALSE(media_tracker_timer->IsRunning());
// Media timer starts once media is detected as playing.
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
EXPECT_TRUE(media_tracker_timer->IsRunning());
input_tracker_timer->Fire();
@@ -425,12 +421,12 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
// Input timer should start running again after input, but the media timer
// keeps running.
EXPECT_FALSE(input_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
EXPECT_TRUE(media_tracker_timer->IsRunning());
- HandleUserInput(helper.get(), blink::WebInputEvent::RawKeyDown);
+ HandleUserInput(helper, blink::WebInputEvent::RawKeyDown);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
EXPECT_TRUE(media_tracker_timer->IsRunning());
EXPECT_DOUBLE_EQ(0.57, service->GetScore(url1));
@@ -438,13 +434,13 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
input_tracker_timer->Fire();
EXPECT_FALSE(input_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
EXPECT_TRUE(media_tracker_timer->IsRunning());
// Timer should start running again after input.
- HandleUserInput(helper.get(), blink::WebInputEvent::GestureTapDown);
+ HandleUserInput(helper, blink::WebInputEvent::GestureTapDown);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
EXPECT_TRUE(media_tracker_timer->IsRunning());
EXPECT_DOUBLE_EQ(0.62, service->GetScore(url1));
@@ -452,7 +448,7 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
input_tracker_timer->Fire();
EXPECT_FALSE(input_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
media_tracker_timer->Fire();
EXPECT_TRUE(media_tracker_timer->IsRunning());
@@ -462,7 +458,7 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
// Timer should be running for navigation delay. Media is disabled again.
NavigateWithDisposition(url2, CURRENT_TAB);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
EXPECT_FALSE(media_tracker_timer->IsRunning());
EXPECT_DOUBLE_EQ(0.64, service->GetScore(url1));
@@ -471,15 +467,15 @@ TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
input_tracker_timer->Fire();
EXPECT_FALSE(input_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
EXPECT_FALSE(media_tracker_timer->IsRunning());
- HandleUserInput(helper.get(), blink::WebInputEvent::MouseDown);
+ HandleUserInput(helper, blink::WebInputEvent::MouseDown);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
EXPECT_FALSE(media_tracker_timer->IsRunning());
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
EXPECT_TRUE(media_tracker_timer->IsRunning());
EXPECT_DOUBLE_EQ(0.64, service->GetScore(url1));
@@ -505,9 +501,9 @@ TEST_F(SiteEngagementHelperTest, ShowAndHide) {
base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
- SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer));
- SetMediaTrackerPauseTimer(helper.get(), make_scoped_ptr(media_tracker_timer));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
+ SetInputTrackerPauseTimer(helper, make_scoped_ptr(input_tracker_timer));
+ SetMediaTrackerPauseTimer(helper, make_scoped_ptr(media_tracker_timer));
NavigateWithDisposition(url1, CURRENT_TAB);
input_tracker_timer->Fire();
@@ -516,37 +512,37 @@ TEST_F(SiteEngagementHelperTest, ShowAndHide) {
web_contents->WasHidden();
EXPECT_FALSE(input_tracker_timer->IsRunning());
EXPECT_FALSE(media_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
// Showing the tab should start tracking again after another delay. Media
// tracking remains inactive.
web_contents->WasShown();
EXPECT_TRUE(input_tracker_timer->IsRunning());
EXPECT_FALSE(media_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
// Start media tracking.
- MediaStartedPlaying(helper.get());
+ MediaStartedPlaying(helper);
EXPECT_TRUE(media_tracker_timer->IsRunning());
// Hiding the tab should stop input tracking, but not media tracking.
web_contents->WasHidden();
EXPECT_FALSE(input_tracker_timer->IsRunning());
EXPECT_TRUE(media_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
// Showing the tab should start tracking again after another delay. Media
// tracking continues.
web_contents->WasShown();
EXPECT_TRUE(input_tracker_timer->IsRunning());
EXPECT_TRUE(media_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
input_tracker_timer->Fire();
media_tracker_timer->Fire();
EXPECT_FALSE(input_tracker_timer->IsRunning());
EXPECT_TRUE(media_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
}
// Ensure tracking behavior is correct for multiple navigations in a single tab.
@@ -558,26 +554,26 @@ TEST_F(SiteEngagementHelperTest, SingleTabNavigation) {
browser()->tab_strip_model()->GetActiveWebContents();
base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
- scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents));
- SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer));
+ SiteEngagementHelper* helper = GetHelper(web_contents);
+ SetInputTrackerPauseTimer(helper, make_scoped_ptr(input_tracker_timer));
// Navigation should start the initial delay timer.
NavigateWithDisposition(url1, CURRENT_TAB);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
// Navigating before the timer fires should simply reset the timer.
NavigateWithDisposition(url2, CURRENT_TAB);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
// When the timer fires, callbacks are added.
input_tracker_timer->Fire();
EXPECT_FALSE(input_tracker_timer->IsRunning());
- EXPECT_TRUE(IsTrackingInput(helper.get()));
+ EXPECT_TRUE(IsTrackingInput(helper));
// Navigation should start the initial delay timer again.
NavigateWithDisposition(url1, CURRENT_TAB);
EXPECT_TRUE(input_tracker_timer->IsRunning());
- EXPECT_FALSE(IsTrackingInput(helper.get()));
+ EXPECT_FALSE(IsTrackingInput(helper));
}
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc
index 9c9b629..f013a45 100644
--- a/chrome/browser/engagement/site_engagement_service.cc
+++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -15,6 +15,7 @@
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/values.h"
+#include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/engagement/site_engagement_eviction_policy.h"
#include "chrome/browser/engagement/site_engagement_helper.h"
@@ -279,7 +280,8 @@ bool SiteEngagementService::IsEnabled() {
// return true immediately.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSiteEngagementService) ||
- SiteEngagementEvictionPolicy::IsEnabled()) {
+ SiteEngagementEvictionPolicy::IsEnabled() ||
+ AppBannerSettingsHelper::ShouldUseSiteEngagementScore()) {
return true;
}
diff --git a/chrome/browser/engagement/site_engagement_service.h b/chrome/browser/engagement/site_engagement_service.h
index 17577bc..7f735d0 100644
--- a/chrome/browser/engagement/site_engagement_service.h
+++ b/chrome/browser/engagement/site_engagement_service.h
@@ -194,6 +194,7 @@ class SiteEngagementService : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, GetTotalUserInputPoints);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest,
CleanupOriginsOnHistoryDeletion);
+ FRIEND_TEST_ALL_PREFIXES(AppBannerSettingsHelperTest, SiteEngagementTrigger);
// Only used in tests.
SiteEngagementService(Profile* profile, scoped_ptr<base::Clock> clock);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index c9c92498..2b69dbb 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -514,6 +514,12 @@ const char kEnableSimplifiedFullscreenUI[] = "enable-simplified-fullscreen-ui";
const char kDisableSimplifiedFullscreenUI[] =
"disable-simplified-fullscreen-ui";
+// Enable the Site Engagement App Banner which triggers app install banners
+// using the site engagement service rather than a navigation-based heuristic.
+// Implicitly enables the site engagement service.
+const char kEnableSiteEngagementAppBanner[] =
+ "enable-site-engagement-app-banner";
+
// Enable the Site Engagement Eviction Policy which evicts temporary storage
// using the site engagement service. Implicitly enables the site engagement
// service.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 22914f1..433f1f5 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -148,6 +148,7 @@ extern const char kEnableSettingsWindow[];
extern const char kDisableSettingsWindow[];
extern const char kEnableSimplifiedFullscreenUI[];
extern const char kDisableSimplifiedFullscreenUI[];
+extern const char kEnableSiteEngagementAppBanner[];
extern const char kEnableSiteEngagementEvictionPolicy[];
extern const char kEnableSiteEngagementService[];
extern const char kEnableSupervisedUserManagedBookmarksFolder[];
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 25122c4..25a832f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -367,6 +367,16 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary>
</histogram>
+<histogram name="AppBanners.MinutesFromFirstVisitToBannerShown" units="minutes">
+ <owner>dominickn@chromium.org</owner>
+ <summary>
+ App banners promote an application related to the current website, and are
+ requested specifically through the current page's HTML. This stat tracks
+ the number of minutes between the first recorded visit to an origin and the
+ time when the banner is actually shown.
+ </summary>
+</histogram>
+
<histogram name="AppBanners.UserResponse" enum="AppBannersUserResponse">
<owner>dominickn@chromium.org</owner>
<summary>