Skip to content

Commit

Permalink
Added UMA and UKM logging after preconnected on pointerdown events wi…
Browse files Browse the repository at this point in the history
…th anchor elements.

UKM Approval: https://docs.google.com/document/d/18fo8Z09aoK9l60T3Hz9WavlE_Bjva23cYDchqLZeBZ4/edit#heading=h.k5jx6iluw4yt

Design Doc: https://docs.google.com/document/d/18fo8Z09aoK9l60T3Hz9WavlE_Bjva23cYDchqLZeBZ4/edit#

Bug: 1297312
Change-Id: I2da102b0dd3ead690408ec4d8787beea879b40f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3559171
Reviewed-by: Simon Pelchat <spelchat@chromium.org>
Reviewed-by: Max Curran <curranmax@chromium.org>
Reviewed-by: Weilun Shi <sweilun@chromium.org>
Reviewed-by: Robert Kaplow <rkaplow@chromium.org>
Commit-Queue: Jacob Stanley <jacobstanley@google.com>
Cr-Commit-Position: refs/heads/main@{#989172}
  • Loading branch information
Jacob Stanley authored and Chromium LUCI CQ committed Apr 5, 2022
1 parent 4e75d0c commit 7a8e9a5
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 3 deletions.
43 changes: 43 additions & 0 deletions chrome/browser/navigation_predictor/anchor_element_preloader.cc
Expand Up @@ -3,9 +3,19 @@
// found in the LICENSE file.

#include "chrome/browser/navigation_predictor/anchor_element_preloader.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/prefetch/prefetch_prefs.h"
#include "components/ukm/content/source_url_recorder.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/features.h"

const char kPreloadingAnchorElementPreloaderPreloadingTriggered[] =
"Preloading.AnchorElementPreloader.PreloadingTriggered";

AnchorElementPreloader::AnchorElementPreloader(
content::RenderFrameHost* render_frame_host,
Expand All @@ -24,6 +34,22 @@ void AnchorElementPreloader::Create(
}

void AnchorElementPreloader::OnPointerDown(const GURL& target) {
if (!prefetch::IsSomePreloadingEnabled(
*Profile::FromBrowserContext(render_frame_host()->GetBrowserContext())
->GetPrefs())) {
return;
}

RecordUmaPreloadedTriggered(AnchorElementPreloaderType::kPreconnect);

RecordUkmPreloadType(AnchorElementPreloaderType::kPreconnect);

if (base::GetFieldTrialParamByFeatureAsBool(
blink::features::kAnchorElementInteraction, "preconnect_holdback",
false)) {
return;
}

auto* loading_predictor = predictors::LoadingPredictorFactory::GetForProfile(
Profile::FromBrowserContext(render_frame_host()->GetBrowserContext()));

Expand All @@ -37,3 +63,20 @@ void AnchorElementPreloader::OnPointerDown(const GURL& target) {
loading_predictor->PreconnectURLIfAllowed(target, /*allow_credentials=*/true,
network_isolation_key);
}

void AnchorElementPreloader::RecordUmaPreloadedTriggered(
AnchorElementPreloaderType preload) {
base::UmaHistogramEnumeration(
kPreloadingAnchorElementPreloaderPreloadingTriggered, preload);
}

void AnchorElementPreloader::RecordUkmPreloadType(
AnchorElementPreloaderType type) {
ukm::SourceId source_id = ukm::GetSourceIdForWebContentsDocument(
content::WebContents::FromRenderFrameHost(render_frame_host()));

ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
ukm::builders::Preloading_AnchorInteraction(source_id)
.SetAnchorElementPreloaderType(static_cast<int64_t>(type))
.Record(ukm_recorder);
}
15 changes: 15 additions & 0 deletions chrome/browser/navigation_predictor/anchor_element_preloader.h
Expand Up @@ -8,6 +8,16 @@
#include "content/public/browser/document_service.h"
#include "third_party/blink/public/mojom/loader/anchor_element_interaction_host.mojom.h"

extern const char kPreloadingAnchorElementPreloaderPreloadingTriggered[];

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class AnchorElementPreloaderType {
kUnspecified = 0,
kPreconnect = 1,
kMaxValue = kPreconnect,
};

class AnchorElementPreloader
: content::DocumentService<blink::mojom::AnchorElementInteractionHost> {
public:
Expand All @@ -21,8 +31,13 @@ class AnchorElementPreloader
content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<blink::mojom::AnchorElementInteractionHost>
receiver);

// Preconnects to the given URL `target`.
void OnPointerDown(const GURL& target) override;

void RecordUmaPreloadedTriggered(AnchorElementPreloaderType);

void RecordUkmPreloadType(AnchorElementPreloaderType);
};

#endif // CHROME_BROWSER_NAVIGATION_PREDICTOR_ANCHOR_ELEMENT_PRELOADER_H_
@@ -1,7 +1,10 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chrome/browser/navigation_predictor/anchor_element_preloader.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/predictors/preconnect_manager.h"
Expand All @@ -10,11 +13,14 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/base/features.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/features.h"

namespace {
Expand All @@ -24,9 +30,13 @@ class AnchorElementPreloaderBrowserTest
public:
static constexpr char kFakeSearch[] = "https://www.fakesearch.com/";

void SetUp() override {
virtual void SetFeatures() {
feature_list_.InitAndEnableFeature(
blink::features::kAnchorElementInteraction);
}

void SetUp() override {
SetFeatures();
https_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
https_server_->ServeFilesFromSourceDirectory("chrome/test/data/preload");
Expand All @@ -41,6 +51,8 @@ class AnchorElementPreloaderBrowserTest
auto* loading_predictor =
predictors::LoadingPredictorFactory::GetForProfile(
browser()->profile());
histogram_tester_ = std::make_unique<base::HistogramTester>();
test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
ASSERT_TRUE(loading_predictor);
loading_predictor->preconnect_manager()->SetObserverForTesting(this);
}
Expand Down Expand Up @@ -74,13 +86,21 @@ class AnchorElementPreloaderBrowserTest
run_loop_->Quit();
}

ukm::TestAutoSetUkmRecorder* test_ukm_recorder() {
return test_ukm_recorder_.get();
}

base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }

protected:
int preresolve_count_;
base::test::ScopedFeatureList feature_list_;

private:
std::unique_ptr<net::EmbeddedTestServer> https_server_;
std::unique_ptr<base::RunLoop> run_loop_;
std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
};

IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, OneAnchorTest) {
Expand All @@ -92,9 +112,27 @@ IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, OneAnchorTest) {
const a = document.getElementById('anchor1');
var e = new PointerEvent('pointerdown');
a.dispatchEvent(e);
)"));
)"));
WaitForPreresolveCountForURL(1);
EXPECT_EQ(1, preresolve_count_);
ukm::SourceId ukm_source_id = ukm::GetSourceIdForWebContentsDocument(
browser()->tab_strip_model()->GetActiveWebContents());

histogram_tester()->ExpectTotalCount(
kPreloadingAnchorElementPreloaderPreloadingTriggered, 1);

histogram_tester()->ExpectUniqueSample(
kPreloadingAnchorElementPreloaderPreloadingTriggered,
AnchorElementPreloaderType::kPreconnect, 1);

auto ukm_entries = test_ukm_recorder()->GetEntries(
ukm::builders::Preloading_AnchorInteraction::kEntryName,
{ukm::builders::Preloading_AnchorInteraction::
kAnchorElementPreloaderTypeName});

EXPECT_EQ(ukm_entries.size(), 1u);

EXPECT_EQ(ukm_entries[0].source_id, ukm_source_id);
}

IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, InvalidHref) {
Expand All @@ -106,8 +144,22 @@ IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, InvalidHref) {
const a = document.getElementById('anchor2');
var e = new PointerEvent('pointerdown');
a.dispatchEvent(e);
)"));
)"));
EXPECT_EQ(0, preresolve_count_);

histogram_tester()->ExpectTotalCount(
kPreloadingAnchorElementPreloaderPreloadingTriggered, 0);

histogram_tester()->ExpectUniqueSample(
kPreloadingAnchorElementPreloaderPreloadingTriggered,
AnchorElementPreloaderType::kPreconnect, 0);

auto ukm_entries = test_ukm_recorder()->GetEntries(
ukm::builders::Preloading_AnchorInteraction::kEntryName,
{ukm::builders::Preloading_AnchorInteraction::
kAnchorElementPreloaderTypeName});

EXPECT_EQ(ukm_entries.size(), 0u);
}

IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, IframeTest) {
Expand All @@ -124,6 +176,25 @@ IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest, IframeTest) {
)"));
WaitForPreresolveCountForURL(1);
EXPECT_EQ(1, preresolve_count_);

histogram_tester()->ExpectTotalCount(
kPreloadingAnchorElementPreloaderPreloadingTriggered, 1);

histogram_tester()->ExpectUniqueSample(
kPreloadingAnchorElementPreloaderPreloadingTriggered,
AnchorElementPreloaderType::kPreconnect, 1);

ukm::SourceId ukm_source_id = ukm::GetSourceIdForWebContentsDocument(
browser()->tab_strip_model()->GetActiveWebContents());

auto ukm_entries = test_ukm_recorder()->GetEntries(
ukm::builders::Preloading_AnchorInteraction::kEntryName,
{ukm::builders::Preloading_AnchorInteraction::
kAnchorElementPreloaderTypeName});

EXPECT_EQ(ukm_entries.size(), 1u);

EXPECT_EQ(ukm_entries[0].source_id, ukm_source_id);
}

IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest,
Expand All @@ -140,5 +211,66 @@ IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderBrowserTest,
a.dispatchEvent(e);
)"));
EXPECT_EQ(0, preresolve_count_);

histogram_tester()->ExpectTotalCount(
kPreloadingAnchorElementPreloaderPreloadingTriggered, 0);

histogram_tester()->ExpectUniqueSample(
kPreloadingAnchorElementPreloaderPreloadingTriggered,
AnchorElementPreloaderType::kPreconnect, 0);

auto ukm_entries = test_ukm_recorder()->GetEntries(
ukm::builders::Preloading_AnchorInteraction::kEntryName,
{ukm::builders::Preloading_AnchorInteraction::
kAnchorElementPreloaderTypeName});

EXPECT_EQ(ukm_entries.size(), 0u);
}

class AnchorElementPreloaderHoldbackBrowserTest
: public AnchorElementPreloaderBrowserTest {
public:
void SetFeatures() override {
feature_list_holdback_.InitAndEnableFeatureWithParameters(
blink::features::kAnchorElementInteraction,
{{"preconnect_holdback", "true"}});
}

private:
base::test::ScopedFeatureList feature_list_holdback_;
};

IN_PROC_BROWSER_TEST_F(AnchorElementPreloaderHoldbackBrowserTest,
PreconnectHoldbackTest) {
const GURL& url = GetTestURL("/one_anchor.html");
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));

EXPECT_TRUE(content::ExecuteScript(
browser()->tab_strip_model()->GetActiveWebContents(),
R"(
const a = document.getElementById('anchor1');
var e = new PointerEvent('pointerdown');
a.dispatchEvent(e);
)"));
EXPECT_EQ(0, preresolve_count_);

histogram_tester()->ExpectTotalCount(
kPreloadingAnchorElementPreloaderPreloadingTriggered, 1);

histogram_tester()->ExpectUniqueSample(
kPreloadingAnchorElementPreloaderPreloadingTriggered,
AnchorElementPreloaderType::kPreconnect, 1);

ukm::SourceId ukm_source_id = ukm::GetSourceIdForWebContentsDocument(
browser()->tab_strip_model()->GetActiveWebContents());

auto ukm_entries = test_ukm_recorder()->GetEntries(
ukm::builders::Preloading_AnchorInteraction::kEntryName,
{ukm::builders::Preloading_AnchorInteraction::
kAnchorElementPreloaderTypeName});

EXPECT_EQ(ukm_entries.size(), 1u);

EXPECT_EQ(ukm_entries[0].source_id, ukm_source_id);
}
} // namespace
5 changes: 5 additions & 0 deletions tools/metrics/histograms/enums.xml
Expand Up @@ -1728,6 +1728,11 @@ Unknown properties are collapsed to zero. -->
label="0x7340, Navi 14 [Radeon RX 5500/5500M / Pro 5500M]"/>
</enum>

<enum name="AnchorElementPreloaderType">
<int value="0" label="kUnspecified"/>
<int value="1" label="kPreconnect"/>
</enum>

<enum name="Android.ChildProcessBindingStateCombination">
<int value="0" label="No waived no moderate no strong"/>
<int value="1" label="No waived no moderate has strong"/>
Expand Down
12 changes: 12 additions & 0 deletions tools/metrics/histograms/metadata/others/histograms.xml
Expand Up @@ -9372,6 +9372,18 @@ chromium-metrics-reviews@google.com.
</summary>
</histogram>

<histogram name="Preloading.AnchorElementPreloader.PreloadingTriggered"
enum="AnchorElementPreloaderType" expires_after="2022-08-28">
<owner>jacobstanley@google.com</owner>
<owner>spelchat@chromium.org</owner>
<owner>curranmax@chromium.org</owner>
<owner>chrome-brapp-loading@google.com</owner>
<summary>
Logged once for each preconnection request sent to the browser. Associated
with the Source ID of the page triggering the preconnection.
</summary>
</histogram>

<histogram name="Previews.CacheControlNoTransform.BlockedPreview"
enum="PreviewsType" expires_after="2021-08-09">
<obsolete>
Expand Down
17 changes: 17 additions & 0 deletions tools/metrics/ukm/ukm.xml
Expand Up @@ -16160,6 +16160,23 @@ be describing additional metrics about the same event.
</metric>
</event>

<event name="Preloading.AnchorInteraction">
<owner>jacobstanley@google.com</owner>
<owner>curranmax@chromium.org</owner>
<owner>chrome-brapp-loading@google.com</owner>
<summary>
Logged once for each preconnection request sent to the browser in resopnse
to the user interacting with an anchor element. Associated with the Source
ID of the page triggering the preconnection.
</summary>
<metric name="AnchorElementPreloaderType" enum="AnchorElementPreloaderType">
<summary>
One event for each preload operation that was triggered on the current
page.
</summary>
</metric>
</event>

<event name="PrerenderPageLoad" singular="True">
<owner>ksakamoto@chromium.org</owner>
<owner>nhiroki@chromium.org</owner>
Expand Down

0 comments on commit 7a8e9a5

Please sign in to comment.