Commit 18d1b898 authored by John Delaney's avatar John Delaney Committed by Commit Bot

Add UseCounters for Conversion Measurement API

Adds Blink Usecounters for impression registration, conversion
registration, and a composite usecounter for both of those events.
These are necessary to measure the percentage of page loads using the
API, for running an origin trial.

A new test harness is added in the chrome/ layer to verify that
metrics are recorded as expected.

Bug: 1109079
Change-Id: I2f70bb3a2eac60ff45a5654169b4db959fd1d3f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2314843
Commit-Queue: John Delaney <johnidel@chromium.org>
Reviewed-by: default avatarNate Chapin <japhet@chromium.org>
Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792856}
parent 4b300f9a
file://content/browser/conversions/OWNERS
// Copyright 2020 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 "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
// Tests UseCounters recorded for the Conversion Measurement API. This is tested
// in the Chrome layer, as UseCounter recording is not used with content shell.
class ConversionsUseCounterBrowsertest : public InProcessBrowserTest {
public:
ConversionsUseCounterBrowsertest() = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
// Sets up the blink runtime feature for ConversionMeasurement.
command_line->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
net::test_server::RegisterDefaultHandlers(&server_);
server_.ServeFilesFromSourceDirectory("content/test/data");
content::SetupCrossSiteRedirector(&server_);
ASSERT_TRUE(server_.Start());
}
protected:
net::EmbeddedTestServer server_{net::EmbeddedTestServer::TYPE_HTTPS};
};
IN_PROC_BROWSER_TEST_F(ConversionsUseCounterBrowsertest,
ImpressionClicked_FeatureRecorded) {
base::HistogramTester histogram_tester;
EXPECT_TRUE(ui_test_utils::NavigateToURL(
browser(),
server_.GetURL("a.test",
"/conversions/page_with_impression_creator.html")));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
// Create an anchor tag with impression attributes and click the link. By
// default the target is set to "_top".
EXPECT_TRUE(ExecJs(web_contents, R"(
createImpressionTag("link" /* id */,
"https://a.com" /* url */,
"1" /* impression data */,
"https://a.com" /* conversion_destination */);)"));
content::TestNavigationObserver observer(web_contents);
EXPECT_TRUE(ExecJs(web_contents, "simulateClick('link');"));
observer.Wait();
histogram_tester.ExpectBucketCount(
"Blink.UseCounter.Features",
blink::mojom::WebFeature::kImpressionRegistration, 1);
histogram_tester.ExpectBucketCount(
"Blink.UseCounter.Features", blink::mojom::WebFeature::kConversionAPIAll,
1);
}
IN_PROC_BROWSER_TEST_F(ConversionsUseCounterBrowsertest,
ConversionPing_FeatureRecorded) {
base::HistogramTester histogram_tester;
EXPECT_TRUE(ui_test_utils::NavigateToURL(
browser(),
server_.GetURL("a.test",
"/conversions/page_with_conversion_redirect.html")));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
// Register a conversion with the original page as the reporting origin.
EXPECT_TRUE(ExecJs(web_contents, "registerConversion(7)"));
// Wait for the conversion redirect to be intercepted. This is indicated by
// window title changing when the img element for the conversion request fires
// an onerror event.
const base::string16 kConvertTitle = base::ASCIIToUTF16("converted");
content::TitleWatcher watcher(web_contents, kConvertTitle);
EXPECT_EQ(kConvertTitle, watcher.WaitAndGetTitle());
// Navigate to a new page to flush metrics.
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
histogram_tester.ExpectBucketCount(
"Blink.UseCounter.Features",
blink::mojom::WebFeature::kConversionRegistration, 1);
histogram_tester.ExpectBucketCount(
"Blink.UseCounter.Features", blink::mojom::WebFeature::kConversionAPIAll,
1);
}
...@@ -882,6 +882,7 @@ if (!is_android) { ...@@ -882,6 +882,7 @@ if (!is_android) {
"../browser/component_updater/component_patcher_operation_browsertest.cc", "../browser/component_updater/component_patcher_operation_browsertest.cc",
"../browser/content_index/content_index_browsertest.cc", "../browser/content_index/content_index_browsertest.cc",
"../browser/content_settings/content_settings_browsertest.cc", "../browser/content_settings/content_settings_browsertest.cc",
"../browser/conversions/conversions_usecounter_browsertest.cc",
"../browser/crash_recovery_browsertest.cc", "../browser/crash_recovery_browsertest.cc",
"../browser/custom_handlers/protocol_handler_registry_browsertest.cc", "../browser/custom_handlers/protocol_handler_registry_browsertest.cc",
"../browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc", "../browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc",
......
...@@ -12,6 +12,7 @@ function registerConversionForOrigin(data, origin) { ...@@ -12,6 +12,7 @@ function registerConversionForOrigin(data, origin) {
img.src = origin + img.src = origin +
"/server-redirect?.well-known/register-conversion?conversion-data=" + "/server-redirect?.well-known/register-conversion?conversion-data=" +
data; data;
img.onerror = function () { document.title = "converted"; };
document.body.appendChild(img); document.body.appendChild(img);
} }
......
...@@ -2688,6 +2688,9 @@ enum WebFeature { ...@@ -2688,6 +2688,9 @@ enum WebFeature {
kCrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed = 3353, kCrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed = 3353,
kPositionSticky = 3354, kPositionSticky = 3354,
kCommaSeparatorInAllowAttribute = 3355, kCommaSeparatorInAllowAttribute = 3355,
kConversionAPIAll = 3356,
kImpressionRegistration = 3357,
kConversionRegistration = 3358,
// Add new features immediately above this line. Don't change assigned // Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots. // numbers of any item, and don't reuse removed slots.
......
...@@ -423,6 +423,11 @@ base::Optional<WebImpression> HTMLAnchorElement::GetImpressionForNavigation() ...@@ -423,6 +423,11 @@ base::Optional<WebImpression> HTMLAnchorElement::GetImpressionForNavigation()
expiry = base::TimeDelta::FromMilliseconds(expiry_milliseconds); expiry = base::TimeDelta::FromMilliseconds(expiry_milliseconds);
} }
UseCounter::Count(GetExecutionContext(),
mojom::blink::WebFeature::kConversionAPIAll);
UseCounter::Count(GetExecutionContext(),
mojom::blink::WebFeature::kImpressionRegistration);
return WebImpression{conversion_destination, reporting_origin, return WebImpression{conversion_destination, reporting_origin,
impression_data, expiry}; impression_data, expiry};
} }
......
...@@ -1085,6 +1085,13 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting( ...@@ -1085,6 +1085,13 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
GetFrame()->GetRemoteNavigationAssociatedInterfaces()->GetInterface( GetFrame()->GetRemoteNavigationAssociatedInterfaces()->GetInterface(
&conversion_host); &conversion_host);
conversion_host->RegisterConversion(std::move(conversion)); conversion_host->RegisterConversion(std::move(conversion));
// Log use counters once we have a conversion.
UseCounter::Count(document_->domWindow(),
mojom::blink::WebFeature::kConversionAPIAll);
UseCounter::Count(document_->domWindow(),
mojom::blink::WebFeature::kConversionRegistration);
return true; return true;
} }
......
...@@ -28563,6 +28563,9 @@ Called by update_use_counter_feature_enum.py.--> ...@@ -28563,6 +28563,9 @@ Called by update_use_counter_feature_enum.py.-->
label="CrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed"/> label="CrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed"/>
<int value="3354" label="PositionSticky"/> <int value="3354" label="PositionSticky"/>
<int value="3355" label="CommaSeparatorInAllowAttribute"/> <int value="3355" label="CommaSeparatorInAllowAttribute"/>
<int value="3356" label="ConversionAPIAll"/>
<int value="3357" label="ImpressionRegistration"/>
<int value="3358" label="ConversionRegistration"/>
</enum> </enum>
<enum name="FeaturePolicyAllowlistType"> <enum name="FeaturePolicyAllowlistType">
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