Commit 5f8ae062 authored by Ryan Sturm's avatar Ryan Sturm Committed by Commit Bot

Restrict prefetching in NavigationPredictor to the links sent to the

UKM (the links in the top urls list).

Rather than prefetching the link with the highest navigation score
overall, NavigationPredictor should only consider the link with the
highest navigation score _of the links sent to the UKM_. This essentially
restricts the links that can be prefetched to the links with the top 10
highest area ranks.

Bug: 995547
Change-Id: I27cc7d5316993132c5835fa83858d9f0fa85a53f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1761526
Commit-Queue: Ryan Sturm <ryansturm@chromium.org>
Reviewed-by: default avatarMichael Crouse <mcrouse@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690148}
parent aded6b9e
...@@ -1003,12 +1003,6 @@ void NavigationPredictor::MaybeTakeActionOnLoad( ...@@ -1003,12 +1003,6 @@ void NavigationPredictor::MaybeTakeActionOnLoad(
sorted_navigation_scores) { sorted_navigation_scores) {
DCHECK(!browser_context_->IsOffTheRecord()); DCHECK(!browser_context_->IsOffTheRecord());
// |sorted_navigation_scores| are sorted in descending order, the first one
// has the highest navigation score.
UMA_HISTOGRAM_COUNTS_100(
"AnchorElementMetrics.Visible.HighestNavigationScore",
static_cast<int>(sorted_navigation_scores[0]->score));
std::string action_histogram_name = std::string action_histogram_name =
source_is_default_search_engine_page_ source_is_default_search_engine_page_
? "NavigationPredictor.OnDSE.ActionTaken" ? "NavigationPredictor.OnDSE.ActionTaken"
...@@ -1085,23 +1079,43 @@ base::Optional<GURL> NavigationPredictor::GetUrlToPrefetch( ...@@ -1085,23 +1079,43 @@ base::Optional<GURL> NavigationPredictor::GetUrlToPrefetch(
if (source_is_default_search_engine_page_) if (source_is_default_search_engine_page_)
return base::nullopt; return base::nullopt;
if (sorted_navigation_scores.empty()) if (sorted_navigation_scores.empty() || top_urls_.empty())
return base::nullopt; return base::nullopt;
// Find which URL in |top_urls_| has the highest navigation score.
double highest_navigation_score;
base::Optional<GURL> url_to_prefetch;
for (const auto& nav_score : sorted_navigation_scores) {
auto url_iter =
std::find(top_urls_.begin(), top_urls_.end(), nav_score->url);
if (url_iter != top_urls_.end()) {
url_to_prefetch = nav_score->url;
highest_navigation_score = nav_score->score;
break;
}
}
UMA_HISTOGRAM_COUNTS_100(
"AnchorElementMetrics.Visible.HighestNavigationScore",
static_cast<int>(highest_navigation_score));
if (!url_to_prefetch)
return url_to_prefetch;
// Only the same origin URLs are eligible for prefetching. If the URL with // Only the same origin URLs are eligible for prefetching. If the URL with
// the highest score is from a different origin, then we skip prefetching // the highest score is from a different origin, then we skip prefetching
// since same origin URLs are not likely to be clicked. // since same origin URLs are not likely to be clicked.
if (url::Origin::Create(sorted_navigation_scores[0]->url) != if (url::Origin::Create(url_to_prefetch.value()) != document_origin) {
document_origin) {
return base::nullopt; return base::nullopt;
} }
// If the prediction score of the highest scoring URL is less than the // If the prediction score of the highest scoring URL is less than the
// threshold, then return. // threshold, then return.
if (sorted_navigation_scores[0]->score < prefetch_url_score_threshold_) if (highest_navigation_score < prefetch_url_score_threshold_)
return base::nullopt; return base::nullopt;
return sorted_navigation_scores[0]->url; return url_to_prefetch;
} }
base::Optional<url::Origin> NavigationPredictor::GetOriginToPreconnect( base::Optional<url::Origin> NavigationPredictor::GetOriginToPreconnect(
......
...@@ -27,7 +27,7 @@ namespace { ...@@ -27,7 +27,7 @@ namespace {
class TestNavigationPredictor : public NavigationPredictor { class TestNavigationPredictor : public NavigationPredictor {
public: public:
explicit TestNavigationPredictor( TestNavigationPredictor(
mojo::InterfaceRequest<AnchorElementMetricsHost> request, mojo::InterfaceRequest<AnchorElementMetricsHost> request,
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
bool init_feature_list) bool init_feature_list)
...@@ -79,6 +79,29 @@ class TestNavigationPredictor : public NavigationPredictor { ...@@ -79,6 +79,29 @@ class TestNavigationPredictor : public NavigationPredictor {
int calls_to_prefetch_ = 0; int calls_to_prefetch_ = 0;
}; };
class TestNavigationPredictorBasedOnScroll : public TestNavigationPredictor {
public:
TestNavigationPredictorBasedOnScroll(
mojo::InterfaceRequest<AnchorElementMetricsHost> request,
content::RenderFrameHost* render_frame_host,
bool init_feature_list)
: TestNavigationPredictor(std::move(request),
render_frame_host,
init_feature_list) {}
~TestNavigationPredictorBasedOnScroll() override {}
// Override CalculateAnchorNavigationScore so the only metric that has
// any weight is the ratio distance to the top of the document.
double CalculateAnchorNavigationScore(
const blink::mojom::AnchorElementMetrics& metrics,
double document_engagement_score,
double target_engagement_score,
int area_rank) const override {
return metrics.ratio_distance_root_top;
}
};
class NavigationPredictorTest : public ChromeRenderViewHostTestHarness { class NavigationPredictorTest : public ChromeRenderViewHostTestHarness {
public: public:
NavigationPredictorTest() = default; NavigationPredictorTest() = default;
...@@ -722,11 +745,62 @@ class NavigationPredictorPrefetchAfterPreconnectEnabledTest ...@@ -722,11 +745,62 @@ class NavigationPredictorPrefetchAfterPreconnectEnabledTest
void SetUp() override { void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
predictor_service_helper_ = std::make_unique<TestNavigationPredictor>( predictor_service_helper_ =
mojo::MakeRequest(&predictor_service_), main_rfh(), false); std::make_unique<TestNavigationPredictorBasedOnScroll>(
mojo::MakeRequest(&predictor_service_), main_rfh(), false);
}
blink::mojom::AnchorElementMetricsPtr CreateMetricsPtrWithRatioDistance(
const std::string& source_url,
const std::string& target_url,
float ratio_area,
float ratio_distance) const {
auto metrics = blink::mojom::AnchorElementMetrics::New();
metrics->source_url = GURL(source_url);
metrics->target_url = GURL(target_url);
metrics->ratio_area = ratio_area;
metrics->ratio_distance_root_top = ratio_distance;
return metrics;
} }
}; };
// Tests that a prefetch only occurs for the URL with the highest navigation
// score in |top_urls_|, not the URL with the highest navigation score overall.
TEST_F(NavigationPredictorPrefetchAfterPreconnectEnabledTest,
PrefetchOnlyURLInTopURLs) {
const std::string source = "https://example1.com";
const std::string url_to_prefetch = "https://example1.com/large";
// Simulate the case where the highest navigation score in |navigation_scores|
// doesn't contain any of the URLs in |top_urls_| by overriding
// |CalculateAnchorNavigationScore| to only take ratio distance into account.
std::vector<blink::mojom::AnchorElementMetricsPtr> metrics;
// The URL with the largest navigation score overall will be that with the
// highest ratio distance.
metrics.push_back(CreateMetricsPtrWithRatioDistance(
source, "https://example2.com/small", 1, 10));
// However, |top_urls_| will contain the top 10 links that have the highest
// ratio area, so the link with the highest ratio distance will not appear
// in the list.
metrics.push_back(
CreateMetricsPtrWithRatioDistance(source, url_to_prefetch, 10, 5));
for (int i = 0; i < 9; i++) {
metrics.push_back(CreateMetricsPtrWithRatioDistance(
source,
std::string("https://example2.com/xsmall")
.append(base::NumberToString(i)),
10, 0));
}
predictor_service()->ReportAnchorElementMetricsOnLoad(std::move(metrics),
GetDefaultViewport());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(prefetch_url().value(), url_to_prefetch);
}
// Test that a prefetch after preconnect occurs only when the current tab is // Test that a prefetch after preconnect occurs only when the current tab is
// in the foreground, and that it does not occur multiple times for the same // in the foreground, and that it does not occur multiple times for the same
// URL. // URL.
......
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