Commit fbd57753 authored by Michael Crouse's avatar Michael Crouse Committed by Commit Bot

Record whether the navigated host was covered by a recent hints fetch.

This change records for each HTTPS navigation if the host has had hints
fetched for it recently. The change also removes expired entries from
the pref on update and limits the maximum number of hosts allowed to be
added to the pref controlled by a finch parameter.

Bug: 994931
Change-Id: Ia40f345a1d57994469823b5e757a4900c633ec2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1762791Reviewed-by: default avatarJesse Doherty <jwd@chromium.org>
Reviewed-by: default avatarRobert Ogden <robertogden@chromium.org>
Commit-Queue: Michael Crouse <mcrouse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689569}
parent 7734d9fc
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
#include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "components/optimization_guide/hints_fetcher.h"
#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/proto/hints.pb.h" #include "components/optimization_guide/proto/hints.pb.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
...@@ -53,6 +55,23 @@ void FlushMetricsForNavigation( ...@@ -53,6 +55,23 @@ void FlushMetricsForNavigation(
builder.Record(ukm::UkmRecorder::Get()); builder.Record(ukm::UkmRecorder::Get());
} }
// Records if the host for the current navigation was successfully
// covered by a HintsFetch. HintsFetching must be enabled and only HTTPS
// navigations are logged.
void MaybeRecordHintsFetcherCoverage(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->GetURL().SchemeIs(url::kHttpsScheme))
return;
if (!optimization_guide::features::IsHintsFetchingEnabled())
return;
optimization_guide::HintsFetcher::RecordHintsFetcherCoverage(
Profile::FromBrowserContext(
navigation_handle->GetWebContents()->GetBrowserContext())
->GetPrefs(),
navigation_handle->GetURL().GetOrigin().host());
}
} // namespace } // namespace
OptimizationGuideWebContentsObserver::OptimizationGuideWebContentsObserver( OptimizationGuideWebContentsObserver::OptimizationGuideWebContentsObserver(
...@@ -91,10 +110,13 @@ OptimizationGuideNavigationData* OptimizationGuideWebContentsObserver:: ...@@ -91,10 +110,13 @@ OptimizationGuideNavigationData* OptimizationGuideWebContentsObserver::
void OptimizationGuideWebContentsObserver::DidStartNavigation( void OptimizationGuideWebContentsObserver::DidStartNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!navigation_handle->IsInMainFrame()) if (!navigation_handle->IsInMainFrame())
return; return;
// Record the HintsFetcher coverage for the navigation, regardless if the
// keyed service is active or not.
MaybeRecordHintsFetcherCoverage(navigation_handle);
if (!optimization_guide_keyed_service_) if (!optimization_guide_keyed_service_)
return; return;
...@@ -109,6 +131,10 @@ void OptimizationGuideWebContentsObserver::DidRedirectNavigation( ...@@ -109,6 +131,10 @@ void OptimizationGuideWebContentsObserver::DidRedirectNavigation(
if (!navigation_handle->IsInMainFrame()) if (!navigation_handle->IsInMainFrame())
return; return;
// Record the HintsFetcher coverage for the navigation, regardless if the
// keyed service is active or not.
MaybeRecordHintsFetcherCoverage(navigation_handle);
if (!optimization_guide_keyed_service_) if (!optimization_guide_keyed_service_)
return; return;
......
...@@ -368,7 +368,7 @@ IN_PROC_BROWSER_TEST_F(HintsFetcherBrowserTest, ...@@ -368,7 +368,7 @@ IN_PROC_BROWSER_TEST_F(HintsFetcherBrowserTest,
SetUpComponentUpdateHints(https_url()); SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample // Expect that the browser initialization will record at least one sample
// in each of the follow histograms as One Platform Hints are enabled. // in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached( EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester, histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
...@@ -379,9 +379,9 @@ IN_PROC_BROWSER_TEST_F(HintsFetcherBrowserTest, ...@@ -379,9 +379,9 @@ IN_PROC_BROWSER_TEST_F(HintsFetcherBrowserTest,
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.Status", 1),
1); 1);
histogram_tester->ExpectBucketCount( histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, 1); "OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, 1);
histogram_tester->ExpectBucketCount( histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK, "OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1); 1);
histogram_tester->ExpectUniqueSample( histogram_tester->ExpectUniqueSample(
...@@ -439,7 +439,7 @@ IN_PROC_BROWSER_TEST_F( ...@@ -439,7 +439,7 @@ IN_PROC_BROWSER_TEST_F(
SetUpComponentUpdateHints(https_url()); SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample // Expect that the browser initialization will record at least one sample
// in each of the follow histograms as One Platform Hints are enabled. // in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached( EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester, histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
...@@ -484,7 +484,7 @@ IN_PROC_BROWSER_TEST_P( ...@@ -484,7 +484,7 @@ IN_PROC_BROWSER_TEST_P(
SetUpComponentUpdateHints(https_url()); SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample // Expect that the browser initialization will record at least one sample
// in each of the follow histograms as One Platform Hints are enabled. // in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached( EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester, histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
...@@ -500,7 +500,7 @@ IN_PROC_BROWSER_TEST_P( ...@@ -500,7 +500,7 @@ IN_PROC_BROWSER_TEST_P(
histogram_tester->ExpectBucketCount( histogram_tester->ExpectBucketCount(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, "OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK,
1); 1);
histogram_tester->ExpectBucketCount( histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK, "OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1); 1);
histogram_tester->ExpectUniqueSample( histogram_tester->ExpectUniqueSample(
...@@ -517,7 +517,7 @@ IN_PROC_BROWSER_TEST_P( ...@@ -517,7 +517,7 @@ IN_PROC_BROWSER_TEST_P(
histogram_tester->ExpectBucketCount( histogram_tester->ExpectBucketCount(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, "OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK,
1); 1);
histogram_tester->ExpectBucketCount( histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK, "OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1); 1);
histogram_tester->ExpectTotalCount( histogram_tester->ExpectTotalCount(
...@@ -562,7 +562,7 @@ IN_PROC_BROWSER_TEST_F( ...@@ -562,7 +562,7 @@ IN_PROC_BROWSER_TEST_F(
SetUpComponentUpdateHints(https_url()); SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample // Expect that the browser initialization will record at least one sample
// in each of the follow histograms as OnePlatform Hints are enabled. // in each of the following histograms as OnePlatform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached( EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester, histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
...@@ -640,7 +640,7 @@ IN_PROC_BROWSER_TEST_F( ...@@ -640,7 +640,7 @@ IN_PROC_BROWSER_TEST_F(
SetUpComponentUpdateHints(https_url()); SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample // Expect that the browser initialization will record at least one sample
// in each of the follow histograms as OnePlatform Hints are enabled. // in each of the following histograms as OnePlatform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached( EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester, histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1), "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
...@@ -707,3 +707,119 @@ IN_PROC_BROWSER_TEST_F( ...@@ -707,3 +707,119 @@ IN_PROC_BROWSER_TEST_F(
histogram_tester->ExpectTotalCount( histogram_tester->ExpectTotalCount(
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 0); "OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 0);
} }
IN_PROC_BROWSER_TEST_F(HintsFetcherBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherHostCovered)) {
const base::HistogramTester* histogram_tester = GetHistogramTester();
// Whitelist NoScript for https_url()'s' host.
SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample
// in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
1);
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", 1),
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, 1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount", 1, 1);
// Navigation to a host in the seeded site engagement service; it should
// be recorded as covered by the hints fetcher.
ui_test_utils::NavigateToURL(browser(), GURL("https://example1.com"));
RetryForHistogramUntilCountReached(
histogram_tester, "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch",
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 1);
}
IN_PROC_BROWSER_TEST_F(
HintsFetcherBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherHostNotCovered)) {
const base::HistogramTester* histogram_tester = GetHistogramTester();
// Whitelist NoScript for https_url()'s' host.
SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample
// in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
1);
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", 1),
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, 1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount", 1, 1);
// Navigate to a host not in the seeded site engagement service; it
// should be recorded as not covered by the hints fetcher.
ui_test_utils::NavigateToURL(browser(), GURL("https://unSeenHost.com"));
RetryForHistogramUntilCountReached(
histogram_tester, "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch",
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 1);
}
IN_PROC_BROWSER_TEST_F(
HintsFetcherBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherHostCoveredNotHTTPS)) {
const base::HistogramTester* histogram_tester = GetHistogramTester();
// Whitelist NoScript for https_url()'s' host.
SetUpComponentUpdateHints(https_url());
// Expect that the browser initialization will record at least one sample
// in each of the following histograms as One Platform Hints are enabled.
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.HostCount", 1),
1);
EXPECT_GE(RetryForHistogramUntilCountReached(
histogram_tester,
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", 1),
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.Status", net::HTTP_OK, 1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK,
1);
histogram_tester->ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount", 1, 1);
// Navigate to a HTTP host; the navigation should not be recorded.
ui_test_utils::NavigateToURL(browser(), GURL("http://example1.com"));
histogram_tester->ExpectTotalCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", 0);
}
...@@ -66,6 +66,25 @@ void HintsFetcher::SetTimeClockForTesting(const base::Clock* time_clock) { ...@@ -66,6 +66,25 @@ void HintsFetcher::SetTimeClockForTesting(const base::Clock* time_clock) {
time_clock_ = time_clock; time_clock_ = time_clock;
} }
// static
void HintsFetcher::RecordHintsFetcherCoverage(PrefService* pref_service,
const std::string& host) {
DictionaryPrefUpdate hosts_fetched(
pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
base::Optional<double> value =
hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
if (!value) {
UMA_HISTOGRAM_BOOLEAN(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false);
return;
}
base::Time host_valid_time = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromSecondsD(*value));
UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintsFetcher.WasHostCoveredByFetch",
host_valid_time > base::Time::Now());
}
bool HintsFetcher::FetchOptimizationGuideServiceHints( bool HintsFetcher::FetchOptimizationGuideServiceHints(
const std::vector<std::string>& hosts, const std::vector<std::string>& hosts,
HintsFetchedCallback hints_fetched_callback) { HintsFetchedCallback hints_fetched_callback) {
...@@ -183,10 +202,43 @@ void HintsFetcher::HandleResponse(const std::string& get_hints_response_data, ...@@ -183,10 +202,43 @@ void HintsFetcher::HandleResponse(const std::string& get_hints_response_data,
} }
void HintsFetcher::UpdateHostsSuccessfullyFetched() { void HintsFetcher::UpdateHostsSuccessfullyFetched() {
if (hosts_fetched_.size() == 0)
return;
DictionaryPrefUpdate hosts_fetched_list( DictionaryPrefUpdate hosts_fetched_list(
pref_service_, prefs::kHintsFetcherHostsSuccessfullyFetched); pref_service_, prefs::kHintsFetcherHostsSuccessfullyFetched);
// Remove any expired hosts.
std::vector<std::string> entries_to_remove;
for (const auto& it : hosts_fetched_list->DictItems()) {
if (base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromSecondsD(
it.second.GetDouble())) < time_clock_->Now()) {
entries_to_remove.emplace_back(it.first);
}
}
for (const auto& host : entries_to_remove) {
hosts_fetched_list->Remove(host, nullptr);
}
if (hosts_fetched_.empty())
return;
// Ensure there is enough space in the dictionary pref for the
// most recent set of hosts to be stored.
if (hosts_fetched_list->size() + hosts_fetched_.size() >
features::MaxHostsForRecordingSuccessfullyCovered()) {
entries_to_remove.clear();
size_t num_entries_to_remove =
hosts_fetched_list->size() + hosts_fetched_.size() -
features::MaxHostsForRecordingSuccessfullyCovered();
for (const auto& it : hosts_fetched_list->DictItems()) {
if (entries_to_remove.size() >= num_entries_to_remove)
break;
entries_to_remove.emplace_back(it.first);
}
for (const auto& host : entries_to_remove) {
hosts_fetched_list->Remove(host, nullptr);
}
}
// Add the covered hosts in |hosts_fetched_| to the dictionary pref.
base::Time host_invalid_time = base::Time host_invalid_time =
time_clock_->Now() + kHintsFetcherHostFetchedValidDuration; time_clock_->Now() + kHintsFetcherHostFetchedValidDuration;
for (const std::string& host : hosts_fetched_) { for (const std::string& host : hosts_fetched_) {
...@@ -194,6 +246,8 @@ void HintsFetcher::UpdateHostsSuccessfullyFetched() { ...@@ -194,6 +246,8 @@ void HintsFetcher::UpdateHostsSuccessfullyFetched() {
HashHostForDictionary(host), HashHostForDictionary(host),
host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF()); host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF());
} }
DCHECK_LE(hosts_fetched_list->size(),
features::MaxHostsForRecordingSuccessfullyCovered());
hosts_fetched_.clear(); hosts_fetched_.clear();
} }
......
...@@ -63,6 +63,11 @@ class HintsFetcher { ...@@ -63,6 +63,11 @@ class HintsFetcher {
// HintsFetcherHostsSuccessfullyFetched dictionary pref. // HintsFetcherHostsSuccessfullyFetched dictionary pref.
static void ClearHostsSuccessfullyFetched(PrefService* pref_service); static void ClearHostsSuccessfullyFetched(PrefService* pref_service);
// Record whether the host was covered by a hints fetch and any returned
// hints would not have expired.
static void RecordHintsFetcherCoverage(PrefService* pref_serivce,
const std::string& host);
private: private:
// URL loader completion callback. // URL loader completion callback.
void OnURLLoadComplete(std::unique_ptr<std::string> response_body); void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h" #include "base/test/simple_test_clock.h"
...@@ -19,6 +21,7 @@ ...@@ -19,6 +21,7 @@
#include "components/optimization_guide/optimization_guide_features.h" #include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/optimization_guide_prefs.h" #include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h" #include "components/prefs/testing_pref_service.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
...@@ -74,6 +77,18 @@ class HintsFetcherTest : public testing::Test { ...@@ -74,6 +77,18 @@ class HintsFetcherTest : public testing::Test {
network::mojom::ConnectionType::CONNECTION_4G); network::mojom::ConnectionType::CONNECTION_4G);
} }
void SeedCoveredHosts(const std::vector<std::string>& hosts,
base::Time host_invalid_time) {
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
for (const std::string& host : hosts) {
hosts_fetched->SetDoubleKey(
HashHostForDictionary(host),
host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF());
}
}
PrefService* pref_service() { return pref_service_.get(); } PrefService* pref_service() { return pref_service_.get(); }
const base::Clock* GetMockClock() const { const base::Clock* GetMockClock() const {
...@@ -108,6 +123,10 @@ class HintsFetcherTest : public testing::Test { ...@@ -108,6 +123,10 @@ class HintsFetcherTest : public testing::Test {
} }
} }
void SimulateNavigation(const std::string& host) {
HintsFetcher::RecordHintsFetcherCoverage(pref_service(), host);
}
private: private:
void RunUntilIdle() { void RunUntilIdle() {
task_environment_.RunUntilIdle(); task_environment_.RunUntilIdle();
...@@ -240,4 +259,140 @@ TEST_F(HintsFetcherTest, HintsFetchClearHostsSuccessfullyFetched) { ...@@ -240,4 +259,140 @@ TEST_F(HintsFetcherTest, HintsFetchClearHostsSuccessfullyFetched) {
} }
} }
TEST_F(HintsFetcherTest, HintsFetcherHostsCovered) {
base::HistogramTester histogram_tester;
std::vector<std::string> hosts{"host1.com", "host2.com"};
base::Time host_invalid_time =
base::Time::Now() + base::TimeDelta().FromHours(1);
SeedCoveredHosts(hosts, host_invalid_time);
SimulateNavigation(hosts[0]);
SimulateNavigation(hosts[1]);
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
}
TEST_F(HintsFetcherTest, HintsFetcherCoveredHostExpired) {
base::HistogramTester histogram_tester;
std::string response_content;
std::vector<std::string> hosts{"host1.com", "host2.com"};
base::Time host_invalid_time =
GetMockClock()->Now() - base::TimeDelta().FromHours(1);
SeedCoveredHosts(hosts, host_invalid_time);
// Fetch hints for new hosts.
std::vector<std::string> hosts_valid{"host3.com", "hosts4.com"};
EXPECT_TRUE(FetchHints(hosts_valid));
VerifyHasPendingFetchRequests();
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_TRUE(hints_fetched());
// The first pair of hosts should be recorded as failed to be
// covered by a recent hints fetcher as they have expired.
SimulateNavigation(hosts[0]);
SimulateNavigation(hosts[1]);
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 2);
// The first pair of hosts should be removed from the dictionary
// pref as they have expired.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
EXPECT_EQ(2u, hosts_fetched->size());
// Navigations to the valid hosts should be recorded as successfully
// covered.
SimulateNavigation(hosts_valid[0]);
SimulateNavigation(hosts_valid[1]);
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
}
TEST_F(HintsFetcherTest, HintsFetcherHostNotCovered) {
base::HistogramTester histogram_tester;
std::vector<std::string> hosts{"host1.com", "host2.com"};
base::Time host_invalid_time =
base::Time::Now() + base::TimeDelta().FromHours(1);
SeedCoveredHosts(hosts, host_invalid_time);
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
EXPECT_EQ(2u, hosts_fetched->size());
SimulateNavigation(hosts[0]);
SimulateNavigation(hosts[1]);
SimulateNavigation("newhost.com");
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 1);
}
TEST_F(HintsFetcherTest, HintsFetcherRemoveExpiredOnSuccessfullyFetched) {
base::HistogramTester histogram_tester;
std::string response_content;
std::vector<std::string> hosts_expired{"host1.com", "host2.com"};
base::Time host_invalid_time =
GetMockClock()->Now() - base::TimeDelta().FromHours(1);
SeedCoveredHosts(hosts_expired, host_invalid_time);
std::vector<std::string> hosts_valid{"host3.com", "host4.com"};
EXPECT_TRUE(FetchHints(hosts_valid));
VerifyHasPendingFetchRequests();
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_TRUE(hints_fetched());
// The two expired hosts should be removed from the dictionary pref as they
// have expired.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
EXPECT_EQ(2u, hosts_fetched->size());
SimulateNavigation(hosts_expired[0]);
SimulateNavigation(hosts_expired[1]);
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 2);
SimulateNavigation(hosts_valid[0]);
SimulateNavigation(hosts_valid[1]);
histogram_tester.ExpectBucketCount(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
}
TEST_F(HintsFetcherTest, HintsFetcherSuccessfullyFetchedHostsFull) {
base::HistogramTester histogram_tester;
std::string response_content;
std::vector<std::string> hosts;
size_t max_hosts =
optimization_guide::features::MaxHostsForRecordingSuccessfullyCovered();
for (size_t i = 0; i < max_hosts - 1; i++) {
hosts.push_back("host" + base::NumberToString(i) + ".com");
}
base::Time host_expiry_time =
GetMockClock()->Now() + base::TimeDelta().FromHours(1);
SeedCoveredHosts(hosts, host_expiry_time);
std::vector<std::string> extra_hosts{"extra1.com", "extra2.com"};
EXPECT_TRUE(FetchHints(extra_hosts));
VerifyHasPendingFetchRequests();
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_TRUE(hints_fetched());
// Navigations to both the extra hosts should be recorded.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
EXPECT_EQ(200u, hosts_fetched->size());
SimulateNavigation(extra_hosts[0]);
SimulateNavigation(extra_hosts[1]);
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
}
} // namespace optimization_guide } // namespace optimization_guide
...@@ -68,6 +68,12 @@ size_t MaxHostsForOptimizationGuideServiceHintsFetch() { ...@@ -68,6 +68,12 @@ size_t MaxHostsForOptimizationGuideServiceHintsFetch() {
"max_hosts_for_optimization_guide_service_hints_fetch", 30); "max_hosts_for_optimization_guide_service_hints_fetch", 30);
} }
size_t MaxHostsForRecordingSuccessfullyCovered() {
return GetFieldTrialParamByFeatureAsInt(
features::kOptimizationHintsFetching,
"max_hosts_for_recording_successfully_covered", 200);
}
base::TimeDelta StoredFetchedHintsFreshnessDuration() { base::TimeDelta StoredFetchedHintsFreshnessDuration() {
return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt( return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt(
features::kOptimizationHintsFetching, features::kOptimizationHintsFetching,
......
...@@ -33,6 +33,10 @@ size_t MaxHintsFetcherTopHostBlacklistSize(); ...@@ -33,6 +33,10 @@ size_t MaxHintsFetcherTopHostBlacklistSize();
// remote Optimzation Guide Service. // remote Optimzation Guide Service.
size_t MaxHostsForOptimizationGuideServiceHintsFetch(); size_t MaxHostsForOptimizationGuideServiceHintsFetch();
// The maximum number of hosts allowed to be stored as covered by the hints
// fetcher.
size_t MaxHostsForRecordingSuccessfullyCovered();
// The amount of time a fetched hint will be considered fresh enough // The amount of time a fetched hint will be considered fresh enough
// to be used and remain in the HintCacheStore. // to be used and remain in the HintCacheStore.
base::TimeDelta StoredFetchedHintsFreshnessDuration(); base::TimeDelta StoredFetchedHintsFreshnessDuration();
......
...@@ -91924,6 +91924,16 @@ uploading your change for review. ...@@ -91924,6 +91924,16 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="OptimizationGuide.HintsFetcher.WasHostCoveredByFetch"
enum="Boolean" expires_after="M82">
<owner>mcrouse@chromium.org</owner>
<owner>dougarnett@chromium.org</owner>
<summary>
Records whether the host being navigated to was included in a hints fetch
and any hints returned have not since expired.
</summary>
</histogram>
<histogram name="OptimizationGuide.HintsLoadedPercentage" units="%" <histogram name="OptimizationGuide.HintsLoadedPercentage" units="%"
expires_after="2019-12-31"> expires_after="2019-12-31">
<owner>dougarnett@chromium.org</owner> <owner>dougarnett@chromium.org</owner>
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