Commit 01e95d9a authored by Sophie Chang's avatar Sophie Chang Committed by Commit Bot

Add UKM around prefetch accuracy stats

Bug: 1092329
Change-Id: I65f6cc0f5534859a4b55cf86c916015030e01af0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2295780Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Commit-Queue: Sophie Chang <sophiechang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789186}
parent 877111f1
......@@ -114,6 +114,23 @@ void PageRequestSummary::UpdateOrAddResource(
subresource_urls.insert(resource_load_info.final_url);
}
void PageRequestSummary::AddPreconnectAttempt(const GURL& preconnect_url) {
url::Origin preconnect_origin = url::Origin::Create(preconnect_url);
if (preconnect_origin == url::Origin::Create(main_frame_url)) {
// Do not count preconnect to main frame origin in number of origins
// preconnected to.
return;
}
preconnect_origins.insert(preconnect_origin);
}
void PageRequestSummary::AddPrefetchAttempt(const GURL& prefetch_url) {
prefetch_urls.insert(prefetch_url);
if (!first_prefetch_initiated)
first_prefetch_initiated = base::TimeTicks::Now();
}
void PageRequestSummary::UpdateOrAddToOrigins(
const url::Origin& origin,
const blink::mojom::CommonNetworkInfoPtr& network_info) {
......@@ -200,6 +217,32 @@ void LoadingDataCollector::RecordResourceLoadComplete(
page_request_summary.UpdateOrAddResource(resource_load_info);
}
void LoadingDataCollector::RecordPreconnectInitiated(
const NavigationID& navigation_id,
const GURL& preconnect_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto nav_it = inflight_navigations_.find(navigation_id);
if (nav_it == inflight_navigations_.end())
return;
auto& page_request_summary = *nav_it->second;
page_request_summary.AddPreconnectAttempt(preconnect_url);
}
void LoadingDataCollector::RecordPrefetchInitiated(
const NavigationID& navigation_id,
const GURL& prefetch_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto nav_it = inflight_navigations_.find(navigation_id);
if (nav_it == inflight_navigations_.end())
return;
auto& page_request_summary = *nav_it->second;
page_request_summary.AddPrefetchAttempt(prefetch_url);
}
void LoadingDataCollector::RecordMainFrameLoadComplete(
const NavigationID& navigation_id,
const base::Optional<OptimizationGuidePrediction>&
......
......@@ -44,6 +44,8 @@ struct PageRequestSummary {
~PageRequestSummary();
void UpdateOrAddResource(
const blink::mojom::ResourceLoadInfo& resource_load_info);
void AddPreconnectAttempt(const GURL& preconnect_url);
void AddPrefetchAttempt(const GURL& prefetch_url);
ukm::SourceId ukm_source_id;
GURL main_frame_url;
......@@ -56,9 +58,19 @@ struct PageRequestSummary {
// is kept per navigation, but the summary is updated several times.
std::map<url::Origin, OriginRequestSummary> origins;
// Set of origins for which preconnects were initiated.
base::flat_set<url::Origin> preconnect_origins;
// Set of seen resource URLs.
base::flat_set<GURL> subresource_urls;
// Set of resource URLs for which prefetches were initiated.
base::flat_set<GURL> prefetch_urls;
// The time for which the first resource prefetch was initiated for the
// navigation.
base::Optional<base::TimeTicks> first_prefetch_initiated;
private:
void UpdateOrAddToOrigins(
const url::Origin& origin,
......@@ -86,6 +98,13 @@ class LoadingDataCollector {
const NavigationID& navigation_id,
const blink::mojom::ResourceLoadInfo& resource_load_info);
// Called when a preconnect is initiated for the navigation.
virtual void RecordPreconnectInitiated(const NavigationID& navigation_id,
const GURL& preconnect_url);
// Called when a prefetch is initiated for the navigation.
virtual void RecordPrefetchInitiated(const NavigationID& navigation_id,
const GURL& prefetch_url);
// Called when the main frame of a page completes loading. We treat this point
// as the "completion" of the navigation. The resources requested by the page
// up to this point are the only ones considered.
......@@ -119,6 +138,10 @@ class LoadingDataCollector {
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ManyNavigations);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordResourceLoadComplete);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordPreconnectInitiatedNoInflightNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordPrefetchInitiatedNoInflightNavigation);
static void SetAllowPortInUrlsForTesting(bool state);
......
......@@ -205,10 +205,42 @@ TEST_F(LoadingDataCollectorTest, SimpleNavigation) {
collector_->RecordFinishNavigation(navigation_id, navigation_id,
/* is_error_page */ false);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
auto* page_request_summary =
collector_->inflight_navigations_.begin()->second.get();
// Ensure that the finish time of the navigation is recorded.
EXPECT_NE(
collector_->inflight_navigations_.begin()->second->navigation_committed,
base::TimeTicks::Max());
EXPECT_NE(page_request_summary->navigation_committed, base::TimeTicks::Max());
// Main frame origin should not be recorded.
collector_->RecordPreconnectInitiated(navigation_id,
navigation_id.main_frame_url);
collector_->RecordPreconnectInitiated(navigation_id,
GURL("http://static.google.com"));
EXPECT_EQ(1u, page_request_summary->preconnect_origins.size());
EXPECT_NE(page_request_summary->preconnect_origins.end(),
page_request_summary->preconnect_origins.find(
url::Origin::Create(GURL("http://static.google.com"))));
collector_->RecordPrefetchInitiated(navigation_id,
GURL("http://google.com/style1.css"));
EXPECT_TRUE(page_request_summary->first_prefetch_initiated.has_value());
base::TimeTicks first_prefetch_initiated =
collector_->inflight_navigations_.begin()
->second->first_prefetch_initiated.value();
collector_->RecordPrefetchInitiated(navigation_id,
GURL("http://google.com/style2.css"));
// The first prefetch initiated request time should still hold.
EXPECT_EQ(first_prefetch_initiated,
page_request_summary->first_prefetch_initiated.value());
EXPECT_EQ(2u, page_request_summary->prefetch_urls.size());
EXPECT_NE(page_request_summary->prefetch_urls.end(),
page_request_summary->prefetch_urls.find(
GURL("http://google.com/style1.css")));
EXPECT_NE(page_request_summary->prefetch_urls.end(),
page_request_summary->prefetch_urls.find(
GURL("http://google.com/style2.css")));
std::vector<blink::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(CreateResourceLoadInfo("http://www.google.com"));
......@@ -386,4 +418,23 @@ TEST_F(LoadingDataCollectorTest, RecordResourceLoadComplete) {
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
}
TEST_F(LoadingDataCollectorTest,
RecordPreconnectInitiatedNoInflightNavigation) {
const SessionID kTabId = SessionID::FromSerializedValue(1);
// If there is no inflight navigation, nothing happens.
auto navigation_id = CreateNavigationID(kTabId, "http://www.google.com");
collector_->RecordPreconnectInitiated(navigation_id,
GURL("http://google.com/"));
EXPECT_TRUE(collector_->inflight_navigations_.empty());
}
TEST_F(LoadingDataCollectorTest, RecordPrefetchInitiatedNoInflightNavigation) {
const SessionID kTabId = SessionID::FromSerializedValue(1);
// If there is no inflight navigation, nothing happens.
auto navigation_id = CreateNavigationID(kTabId, "http://www.google.com");
collector_->RecordPrefetchInitiated(navigation_id,
GURL("http://google.com/style1.css"));
EXPECT_TRUE(collector_->inflight_navigations_.empty());
}
} // namespace predictors
......@@ -181,6 +181,8 @@ bool LoadingPredictor::OnNavigationStarted(const NavigationID& navigation_id) {
loading_data_collector()->RecordStartNavigation(navigation_id);
CleanupAbandonedHintsAndNavigations(navigation_id);
active_navigations_.emplace(navigation_id);
active_urls_to_navigations_[navigation_id.main_frame_url].insert(
navigation_id);
return PrepareForPageLoad(navigation_id.main_frame_url,
HintOrigin::NAVIGATION);
}
......@@ -194,6 +196,14 @@ void LoadingPredictor::OnNavigationFinished(
loading_data_collector()->RecordFinishNavigation(
old_navigation_id, new_navigation_id, is_error_page);
if (active_urls_to_navigations_.find(old_navigation_id.main_frame_url) !=
active_urls_to_navigations_.end()) {
active_urls_to_navigations_[old_navigation_id.main_frame_url].erase(
old_navigation_id);
if (active_urls_to_navigations_[old_navigation_id.main_frame_url].empty()) {
active_urls_to_navigations_.erase(old_navigation_id.main_frame_url);
}
}
active_navigations_.erase(old_navigation_id);
CancelPageLoadHint(old_navigation_id.main_frame_url);
}
......@@ -285,6 +295,20 @@ void LoadingPredictor::HandleOmniboxHint(const GURL& url, bool preconnectable) {
}
}
void LoadingPredictor::PreconnectInitiated(const GURL& url,
const GURL& preconnect_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (shutdown_)
return;
auto nav_id_set_it = active_urls_to_navigations_.find(url);
if (nav_id_set_it == active_urls_to_navigations_.end())
return;
for (const auto& nav_id : nav_id_set_it->second)
loading_data_collector_->RecordPreconnectInitiated(nav_id, preconnect_url);
}
void LoadingPredictor::PreconnectFinished(
std::unique_ptr<PreconnectStats> stats) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......@@ -296,6 +320,20 @@ void LoadingPredictor::PreconnectFinished(
stats_collector_->RecordPreconnectStats(std::move(stats));
}
void LoadingPredictor::PrefetchInitiated(const GURL& url,
const GURL& prefetch_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (shutdown_)
return;
auto nav_id_set_it = active_urls_to_navigations_.find(url);
if (nav_id_set_it == active_urls_to_navigations_.end())
return;
for (const auto& nav_id : nav_id_set_it->second)
loading_data_collector_->RecordPrefetchInitiated(nav_id, prefetch_url);
}
void LoadingPredictor::PrefetchFinished(std::unique_ptr<PrefetchStats> stats) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (shutdown_)
......
......@@ -90,9 +90,12 @@ class LoadingPredictor : public KeyedService,
}
// PreconnectManager::Delegate:
void PreconnectInitiated(const GURL& url,
const GURL& preconnect_url) override;
void PreconnectFinished(std::unique_ptr<PreconnectStats> stats) override;
// PrefetchManager::Delegate:
void PrefetchInitiated(const GURL& url, const GURL& prefetch_url) override;
void PrefetchFinished(std::unique_ptr<PrefetchStats> stats) override;
size_t GetActiveHintsSizeForTesting() { return active_hints_.size(); }
......@@ -162,6 +165,7 @@ class LoadingPredictor : public KeyedService,
std::unique_ptr<PrefetchManager> prefetch_manager_;
std::map<GURL, base::TimeTicks> active_hints_;
std::set<NavigationID> active_navigations_;
std::map<GURL, std::set<NavigationID>> active_urls_to_navigations_;
bool shutdown_ = false;
size_t total_hints_activated_ = 0;
......
......@@ -207,26 +207,34 @@ TEST_F(LoadingPredictorTest, TestMainFrameResponseClearsNavigations) {
const SessionID tab_id = SessionID::FromSerializedValue(12);
const auto& active_navigations = predictor_->active_navigations_;
const auto& active_hints = predictor_->active_hints_;
const auto& active_urls_to_navigations =
predictor_->active_urls_to_navigations_;
auto navigation_id = CreateNavigationID(tab_id, url);
predictor_->OnNavigationStarted(navigation_id);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_FALSE(active_hints.empty());
EXPECT_NE(active_urls_to_navigations.find(GURL(url)),
active_urls_to_navigations.end());
predictor_->OnNavigationFinished(navigation_id, navigation_id, false);
EXPECT_TRUE(active_navigations.empty());
EXPECT_TRUE(active_hints.empty());
EXPECT_TRUE(active_urls_to_navigations.empty());
// With redirects.
predictor_->OnNavigationStarted(navigation_id);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_FALSE(active_hints.empty());
EXPECT_NE(active_urls_to_navigations.find(GURL(url)),
active_urls_to_navigations.end());
auto new_navigation_id = CreateNavigationID(tab_id, redirected);
predictor_->OnNavigationFinished(navigation_id, new_navigation_id, false);
EXPECT_TRUE(active_navigations.empty());
EXPECT_TRUE(active_hints.empty());
EXPECT_TRUE(active_urls_to_navigations.empty());
}
TEST_F(LoadingPredictorTest, TestMainFrameRequestDoesntCancelExternalHint) {
......
......@@ -227,6 +227,41 @@ void LoadingStatsCollector::RecordPageRequestSummary(
}
recorded_ukm = true;
}
if (!summary.preconnect_origins.empty()) {
builder.SetSubresourceOriginPreconnectsInitiated(
std::min(ukm_cap, summary.preconnect_origins.size()));
const auto& actual_subresource_origins = summary.origins;
size_t correctly_predicted_subresource_origins_initiated = std::count_if(
summary.preconnect_origins.begin(), summary.preconnect_origins.end(),
[&actual_subresource_origins](const url::Origin& subresource_origin) {
return actual_subresource_origins.find(subresource_origin) !=
actual_subresource_origins.end();
});
builder.SetCorrectSubresourceOriginPreconnectsInitiated(
std::min(ukm_cap, correctly_predicted_subresource_origins_initiated));
recorded_ukm = true;
}
if (!summary.prefetch_urls.empty()) {
builder.SetSubresourcePrefetchesInitiated(
std::min(ukm_cap, summary.prefetch_urls.size()));
const auto& actual_subresource_urls = summary.subresource_urls;
size_t correctly_predicted_subresource_prefetches_initiated = std::count_if(
summary.prefetch_urls.begin(), summary.prefetch_urls.end(),
[&actual_subresource_urls](const GURL& subresource_url) {
return actual_subresource_urls.find(subresource_url) !=
actual_subresource_urls.end();
});
builder.SetCorrectSubresourcePrefetchesInitiated(std::min(
ukm_cap, correctly_predicted_subresource_prefetches_initiated));
recorded_ukm = true;
}
if (summary.first_prefetch_initiated) {
DCHECK(!summary.prefetch_urls.empty());
builder.SetNavigationStartToFirstSubresourcePrefetchInitiated(
(summary.first_prefetch_initiated.value() - summary.navigation_started)
.InMilliseconds());
recorded_ukm = true;
}
auto it = preconnect_stats_.find(initial_url);
if (it != preconnect_stats_.end()) {
......
......@@ -133,6 +133,11 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectPrecisionRecallMetrics) {
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources, now);
summary.navigation_committed = now + base::TimeDelta::FromMilliseconds(3);
summary.preconnect_origins = {
url::Origin::Create(GURL(gen(1))),
url::Origin::Create(GURL(gen(2))),
url::Origin::Create(GURL(gen(3))),
};
stats_collector_->RecordPageRequestSummary(summary, base::nullopt);
......@@ -164,6 +169,16 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectPrecisionRecallMetrics) {
entry,
ukm::builders::LoadingPredictor::kNavigationStartToNavigationCommitName,
3);
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::
kSubresourceOriginPreconnectsInitiatedName,
3);
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::
kCorrectSubresourceOriginPreconnectsInitiatedName,
1);
// Make sure optimization guide metrics are not recorded.
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
......@@ -181,10 +196,21 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectPrecisionRecallMetrics) {
entry,
ukm::builders::LoadingPredictor::
kOptimizationGuidePredictionCorrectlyPredictedSubresourcesName));
// Make sure prefetch metrics are not recorded since no prefetches were
// initiated.
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
kNavigationStartToFirstSubresourcePrefetchInitiatedName));
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry,
ukm::builders::LoadingPredictor::kSubresourcePrefetchesInitiatedName));
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
kCorrectSubresourcePrefetchesInitiatedName));
}
TEST_F(LoadingStatsCollectorTest,
TestPreconnectPrecisionRecallMetricsWithOptimizationGuide) {
TestPrecisionRecallMetricsWithOptimizationGuide) {
const std::string main_frame_url = "http://google.com/?query=cats";
auto gen = [](int index) {
return base::StringPrintf("http://cdn%d.google.com/script.js", index);
......@@ -224,6 +250,12 @@ TEST_F(LoadingStatsCollectorTest,
gen(100), network::mojom::RequestDestination::kScript));
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources, now);
summary.prefetch_urls = {
GURL(gen(1)),
GURL(gen(2)),
GURL(gen(3)),
};
summary.first_prefetch_initiated = now + base::TimeDelta::FromMilliseconds(1);
stats_collector_->RecordPageRequestSummary(summary,
optimization_guide_prediction);
......@@ -245,6 +277,19 @@ TEST_F(LoadingStatsCollectorTest,
ukm::builders::LoadingPredictor::kEntryName);
EXPECT_EQ(1u, entries.size());
auto* entry = entries[0];
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::kSubresourcePrefetchesInitiatedName, 3);
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::
kCorrectSubresourcePrefetchesInitiatedName,
1);
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::
kNavigationStartToFirstSubresourcePrefetchInitiatedName,
1);
ukm_recorder_->ExpectEntryMetric(
entry,
ukm::builders::LoadingPredictor::kOptimizationGuidePredictionDecisionName,
......@@ -281,6 +326,14 @@ TEST_F(LoadingStatsCollectorTest,
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
kLocalPredictionCorrectlyPredictedOriginsName));
// Make sure preconnect metrics are not recorded since no preconnects were
// initiated.
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
kSubresourceOriginPreconnectsInitiatedName));
EXPECT_FALSE(ukm_recorder_->EntryHasMetric(
entry, ukm::builders::LoadingPredictor::
kCorrectSubresourceOriginPreconnectsInitiatedName));
}
TEST_F(LoadingStatsCollectorTest, TestRedirectStatusNoRedirect) {
......
......@@ -229,8 +229,10 @@ void PreconnectManager::TryToLaunchPreresolveJobs() {
job->url, job->network_isolation_key,
base::BindOnce(&PreconnectManager::OnProxyLookupFinished,
weak_factory_.GetWeakPtr(), job_id));
if (info)
if (info) {
++info->inflight_count;
delegate_->PreconnectInitiated(info->url, job->url);
}
++inflight_preresolves_count_;
} else {
preresolve_jobs_.Remove(job_id);
......
......@@ -115,6 +115,10 @@ class PreconnectManager {
public:
virtual ~Delegate() {}
// Called when a preconnect to |preconnect_url| is initiated for |url|.
virtual void PreconnectInitiated(const GURL& url,
const GURL& preconnect_url) = 0;
// Called when all preresolve jobs for the |stats->url| are finished. Note
// that some preconnect jobs can be still in progress, because they are
// fire-and-forget.
......
......@@ -191,6 +191,7 @@ blink::mojom::ResourceType GetResourceType(
}
return blink::mojom::ResourceType::kSubResource;
}
void PrefetchManager::PrefetchUrl(
std::unique_ptr<PrefetchJob> job,
scoped_refptr<network::SharedURLLoaderFactory> factory) {
......@@ -254,6 +255,8 @@ void PrefetchManager::PrefetchUrl(
kPrefetchTrafficAnnotation, base::ThreadTaskRunnerHandle::Get(),
/*cors_exempt_header_list=*/base::nullopt);
delegate_->PrefetchInitiated(info.url, job->url);
// The idea of prefetching is for the network service to put the response in
// the http cache. So from the prefetching layer, nothing needs to be done
// with the response, so just drain it.
......
......@@ -64,6 +64,11 @@ class PrefetchManager {
public:
virtual ~Delegate() = default;
// Called when a prefetch is initiated. |prefetch_url| is the subresource
// being prefetched, and |url| is the main frame of the navigation.
virtual void PrefetchInitiated(const GURL& url,
const GURL& prefetch_url) = 0;
// Called when all prefetch jobs for the |stats->url| are finished.
// Called on the UI thread.
virtual void PrefetchFinished(std::unique_ptr<PrefetchStats> stats) = 0;
......
......@@ -39,10 +39,16 @@ namespace predictors {
namespace {
using ::testing::UnorderedElementsAreArray;
class FakePrefetchManagerDelegate
: public PrefetchManager::Delegate,
public base::SupportsWeakPtr<FakePrefetchManagerDelegate> {
public:
void PrefetchInitiated(const GURL& url, const GURL& prefetch_url) override {
prefetched_urls_for_main_frame_url_[url].insert(prefetch_url);
}
void PrefetchFinished(std::unique_ptr<PrefetchStats> stats) override {
finished_urls_.insert(stats->url);
auto iter = done_callbacks_.find(stats->url);
......@@ -62,7 +68,18 @@ class FakePrefetchManagerDelegate
loop.Run();
}
base::flat_set<GURL> GetPrefetchedURLsForURL(const GURL& url) const {
auto it = prefetched_urls_for_main_frame_url_.find(url);
if (it == prefetched_urls_for_main_frame_url_.end())
return {};
return it->second;
}
void ClearPrefetchedURLs() { prefetched_urls_for_main_frame_url_ = {}; }
private:
base::flat_map<GURL, base::flat_set<GURL>>
prefetched_urls_for_main_frame_url_;
base::flat_set<GURL> finished_urls_;
base::flat_map<GURL, base::OnceClosure> done_callbacks_;
};
......@@ -145,6 +162,9 @@ TEST_F(PrefetchManagerTest, OneMainFrameUrlOnePrefetch) {
prefetch_manager_->Start(main_frame_url, {request});
loop.Run();
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray({subresource_url}));
fake_delegate_->WaitForPrefetchFinished(main_frame_url);
}
......@@ -184,14 +204,22 @@ TEST_F(PrefetchManagerTest, OneMainFrameUrlMultiplePrefetch) {
prefetch_manager_->Start(main_frame_url, std::move(requests));
// Wait for requests up to the inflight limit.
for (size_t i = 0; i < responses.size() - 1; i++)
std::vector<GURL> prefetched_urls;
for (size_t i = 0; i < responses.size() - 1; i++) {
prefetched_urls.push_back(test_server.GetURL(paths[i]));
responses[i]->WaitForRequest();
}
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray(prefetched_urls));
// Verify there is a queued job. Pump the run loop just to give the manager a
// chance to incorrectly start the queued job and fail the expectation.
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GetQueuedJobsCount(), 1u);
fake_delegate_->ClearPrefetchedURLs();
// Finish one request.
responses.front()->Send("hi");
responses.front()->Done();
......@@ -200,6 +228,9 @@ TEST_F(PrefetchManagerTest, OneMainFrameUrlMultiplePrefetch) {
responses.back()->WaitForRequest();
EXPECT_EQ(GetQueuedJobsCount(), 0u);
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray({test_server.GetURL(paths.back())}));
// Finish all requests.
for (size_t i = 1; i < responses.size(); i++) {
responses[i]->Send("hi");
......@@ -237,13 +268,17 @@ TEST_F(PrefetchManagerTest, MultipleMainFrameUrlMultiplePrefetch) {
ASSERT_TRUE(test_server_handle);
// The request URLs can only be constructed after the server is started.
for (size_t i = 0; i < count; i++) {
std::vector<GURL> expected_prefetch_requests_for_main_frame_url;
for (size_t i = 0; i < count - 1; i++) {
GURL url = test_server.GetURL(paths[i]);
requests.push_back(CreateScriptRequest(url, main_frame_url));
expected_prefetch_requests_for_main_frame_url.push_back(url);
}
{
GURL url = test_server.GetURL(paths[count]);
std::vector<GURL> expected_prefetch_requests_for_main_frame_url2;
for (size_t i = count - 1; i < count + 1; i++) {
GURL url = test_server.GetURL(paths[i]);
requests.push_back(CreateScriptRequest(url, main_frame_url2));
expected_prefetch_requests_for_main_frame_url2.push_back(url);
}
// Start the prefetching.
......@@ -263,6 +298,15 @@ TEST_F(PrefetchManagerTest, MultipleMainFrameUrlMultiplePrefetch) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GetQueuedJobsCount(), 1u);
EXPECT_THAT(
fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray(expected_prefetch_requests_for_main_frame_url));
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url2),
UnorderedElementsAreArray(
{expected_prefetch_requests_for_main_frame_url2.front()}));
fake_delegate_->ClearPrefetchedURLs();
// Finish one request.
responses.front()->Send("hi");
responses.front()->Done();
......@@ -271,6 +315,13 @@ TEST_F(PrefetchManagerTest, MultipleMainFrameUrlMultiplePrefetch) {
responses.back()->WaitForRequest();
EXPECT_EQ(GetQueuedJobsCount(), 0u);
// We don't expect any more requests for |main_frame_url| to be initiated and
// we expect the last request for |main_frame_url2| to go out.
EXPECT_TRUE(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url).empty());
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url2),
UnorderedElementsAreArray(
{expected_prefetch_requests_for_main_frame_url2.back()}));
// Finish all requests.
for (size_t i = 1; i < responses.size(); i++) {
responses[i]->Send("hi");
......@@ -321,9 +372,11 @@ TEST_F(PrefetchManagerTest, Stop) {
ASSERT_TRUE(test_server_handle);
// The request URLs can only be constructed after the server is started.
std::vector<GURL> expected_prefetch_requests;
for (size_t i = 0; i < limit; i++) {
GURL url = test_server.GetURL(paths[i]);
requests.push_back(CreateScriptRequest(url, main_frame_url));
expected_prefetch_requests.push_back(url);
}
// This request should never be seen.
requests.push_back(CreateScriptRequest(
......@@ -352,12 +405,18 @@ TEST_F(PrefetchManagerTest, Stop) {
}
fake_delegate_->WaitForPrefetchFinished(main_frame_url);
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray(expected_prefetch_requests));
// The request for URL2 should be requested.
response2->WaitForRequest();
response2->Send("hi");
response2->Done();
fake_delegate_->WaitForPrefetchFinished(main_frame_url2);
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url2),
UnorderedElementsAreArray({test_server.GetURL(path2)}));
}
TEST_F(PrefetchManagerTest, StopAndStart) {
......@@ -398,9 +457,11 @@ TEST_F(PrefetchManagerTest, StopAndStart) {
ASSERT_TRUE(test_server_handle);
// The request URLs can only be constructed after the server is started.
std::vector<GURL> expected_prefetch_requests;
for (size_t i = 0; i < limit; i++) {
GURL url = test_server.GetURL(paths[i]);
requests.push_back(CreateScriptRequest(url, main_frame_url));
expected_prefetch_requests.push_back(url);
}
// This request should never be seen.
requests.push_back(CreateScriptRequest(
......@@ -413,10 +474,14 @@ TEST_F(PrefetchManagerTest, StopAndStart) {
for (auto& response : responses) {
response->WaitForRequest();
}
EXPECT_THAT(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url),
UnorderedElementsAreArray(expected_prefetch_requests));
// Call stop.
prefetch_manager_->Stop(main_frame_url);
fake_delegate_->ClearPrefetchedURLs();
// Call start again. These requests will be coalesced
// with the stopped info, and will just be dropped.
prefetch_manager_->Start(main_frame_url, requests);
......@@ -430,6 +495,9 @@ TEST_F(PrefetchManagerTest, StopAndStart) {
}
fake_delegate_->WaitForPrefetchFinished(main_frame_url);
// We don't expect any additional requests to be started.
EXPECT_TRUE(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url).empty());
// Restart requests. These requests will work as normal.
prefetch_manager_->Start(main_frame_url, requests);
for (auto& response : responses2) {
......@@ -439,6 +507,9 @@ TEST_F(PrefetchManagerTest, StopAndStart) {
}
fake_delegate_->WaitForPrefetchFinished(main_frame_url);
// Prefetches should have been initiated with the second start.
EXPECT_FALSE(fake_delegate_->GetPrefetchedURLsForURL(main_frame_url).empty());
}
class HeaderInjectingThrottle : public blink::URLLoaderThrottle {
......
......@@ -5221,6 +5221,23 @@ be describing additional metrics about the same event.
Predictor. This event will be recorded once per page load on
DocumentOnLoadCompletedInMainFrame().
</summary>
<metric name="CorrectSubresourceOriginPreconnectsInitiated">
<summary>
The number of subresource origin preconnects that were initiated by the
Loading Predictor for the navigation and were actually used by the page
load, excluding the main frame URL's origin. If more than 100 subresource
origins were preconnected to and were actually used by the page load, this
will be capped at 100.
</summary>
</metric>
<metric name="CorrectSubresourcePrefetchesInitiated">
<summary>
The number of subresource prefetches that were initiated by the Loading
Predictor for the navigation and were actually used by the page load. If
more than 100 subresources were prefetched and were actually used by the
page load, this will be capped at 100.
</summary>
</metric>
<metric name="LocalPredictionCorrectlyPredictedOrigins">
<summary>
The number of subresource origins that were correctly predicted by the
......@@ -5239,6 +5256,12 @@ be describing additional metrics about the same event.
100.
</summary>
</metric>
<metric name="NavigationStartToFirstSubresourcePrefetchInitiated">
<summary>
The time (in milliseconds) that elapsed between navigation start and the
first subresource prefetch that was initiated based on these predictions.
</summary>
</metric>
<metric name="NavigationStartToNavigationCommit">
<summary>
The time (in milliseconds) that elapsed between navigation start and the
......@@ -5293,6 +5316,21 @@ be describing additional metrics about the same event.
subresources were predicted, this will be capped at 100.
</summary>
</metric>
<metric name="SubresourceOriginPreconnectsInitiated">
<summary>
The number of subresource origins that were initiated by the Loading
Predictor and were preconnected to, excluding the main frame URL's origin.
If more than 100 subresource origins were preconnected to, this will be
capped at 100.
</summary>
</metric>
<metric name="SubresourcePrefetchesInitiated">
<summary>
The number of subresource prefetches that were initiated by the Loading
Predictor for the navigation. If more than 100 subresources were
prefetched, this will be capped at 100.
</summary>
</metric>
</event>
<event name="LocalNetworkRequests">
......
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