Commit 2d2df4de authored by John Delaney's avatar John Delaney Committed by Commit Bot

Report ad resource sizes by mime type

Record the size of ad resources according to MIME type. This will help us
understand which resources are using up more network bytes and allow
us to better estimate the effect any ad intervention will have. Only
HTML/JS/CSS/Image/Video are recorded as they are expected to capture most
of the resources commonly seen in ads. It is expected that these metrics
will not be completely accurate because requests do not always contain
the correct content type. It is assumed that the MIME type in the response
header is a suitable proxy resource type.

Bug: 881049
Change-Id: I000466fb3fe5467c4f73527cb4cedbd7709d7c3f
Reviewed-on: https://chromium-review.googlesource.com/1219900
Commit-Queue: John Delaney <johnidel@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593087}
parent 05351fa0
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "net/base/mime_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace { namespace {
...@@ -370,7 +372,7 @@ void AdsPageLoadMetricsObserver::UpdateResource( ...@@ -370,7 +372,7 @@ void AdsPageLoadMetricsObserver::UpdateResource(
// Update resource map. // Update resource map.
if (resource->is_complete) { if (resource->is_complete) {
RecordResourceHistogram(resource); RecordResourceHistograms(resource);
if (it != page_resources_.end()) if (it != page_resources_.end())
page_resources_.erase(it); page_resources_.erase(it);
} else { } else {
...@@ -386,7 +388,45 @@ void AdsPageLoadMetricsObserver::UpdateResource( ...@@ -386,7 +388,45 @@ void AdsPageLoadMetricsObserver::UpdateResource(
} }
} }
void AdsPageLoadMetricsObserver::RecordResourceHistogram( void AdsPageLoadMetricsObserver::RecordResourceMimeHistograms(
const page_load_metrics::mojom::ResourceDataUpdatePtr& resource) {
if (blink::IsSupportedImageMimeType(resource->mime_type)) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.Image",
resource->received_data_length);
} else if (blink::IsSupportedJavascriptMimeType(resource->mime_type)) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.JS",
resource->received_data_length);
} else {
std::string top_level_type;
std::string subtype;
if (!net::ParseMimeTypeWithoutParameter(resource->mime_type,
&top_level_type, &subtype)) {
// Log invalid mime types as "Other".
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.Other",
resource->received_data_length);
return;
}
if (top_level_type.compare("video") == 0) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.Video",
resource->received_data_length);
} else if (top_level_type.compare("text") == 0 &&
subtype.compare("css") == 0) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.CSS",
resource->received_data_length);
} else if (top_level_type.compare("text") == 0 &&
subtype.compare("html") == 0) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.HTML",
resource->received_data_length);
} else {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mime.Other",
resource->received_data_length);
}
}
}
void AdsPageLoadMetricsObserver::RecordResourceHistograms(
const page_load_metrics::mojom::ResourceDataUpdatePtr& resource) { const page_load_metrics::mojom::ResourceDataUpdatePtr& resource) {
if (resource->is_main_frame_resource && resource->reported_as_ad_resource) { if (resource->is_main_frame_resource && resource->reported_as_ad_resource) {
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mainframe.AdResource", PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Mainframe.AdResource",
...@@ -401,6 +441,10 @@ void AdsPageLoadMetricsObserver::RecordResourceHistogram( ...@@ -401,6 +441,10 @@ void AdsPageLoadMetricsObserver::RecordResourceHistogram(
PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Subframe.VanillaResource", PAGE_BYTES_HISTOGRAM("Ads.ResourceUsage.Size.Subframe.VanillaResource",
resource->received_data_length); resource->received_data_length);
} }
// Only report sizes by mime type for ad resources.
if (resource->reported_as_ad_resource)
RecordResourceMimeHistograms(resource);
} }
void AdsPageLoadMetricsObserver::RecordPageResourceTotalHistograms() { void AdsPageLoadMetricsObserver::RecordPageResourceTotalHistograms() {
...@@ -426,7 +470,7 @@ void AdsPageLoadMetricsObserver::RecordHistograms() { ...@@ -426,7 +470,7 @@ void AdsPageLoadMetricsObserver::RecordHistograms() {
RecordHistogramsForType(AD_TYPE_ALL); RecordHistogramsForType(AD_TYPE_ALL);
RecordPageResourceTotalHistograms(); RecordPageResourceTotalHistograms();
for (auto const& kv : page_resources_) for (auto const& kv : page_resources_)
RecordResourceHistogram(kv.second); RecordResourceHistograms(kv.second);
} }
void AdsPageLoadMetricsObserver::RecordHistogramsForType(int ad_type) { void AdsPageLoadMetricsObserver::RecordHistogramsForType(int ad_type) {
......
...@@ -117,7 +117,12 @@ class AdsPageLoadMetricsObserver ...@@ -117,7 +117,12 @@ class AdsPageLoadMetricsObserver
void UpdateResource( void UpdateResource(
const page_load_metrics::mojom::ResourceDataUpdatePtr& resource); const page_load_metrics::mojom::ResourceDataUpdatePtr& resource);
void RecordResourceHistogram( // Records size of resources by mime type.
void RecordResourceMimeHistograms(
const page_load_metrics::mojom::ResourceDataUpdatePtr& resource);
// Records per-resource histograms.
void RecordResourceHistograms(
const page_load_metrics::mojom::ResourceDataUpdatePtr& resource); const page_load_metrics::mojom::ResourceDataUpdatePtr& resource);
void RecordPageResourceTotalHistograms(); void RecordPageResourceTotalHistograms();
void RecordHistograms(); void RecordHistograms();
......
...@@ -371,3 +371,38 @@ IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverResourceBrowserTest, ...@@ -371,3 +371,38 @@ IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverResourceBrowserTest,
histogram_tester.ExpectBucketCount( histogram_tester.ExpectBucketCount(
"PageLoad.Clients.Ads.Resources.Bytes.Unfinished", 1, 1); "PageLoad.Clients.Ads.Resources.Bytes.Unfinished", 1, 1);
} }
// Verify that Mime type metrics are recorded correctly.
IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverResourceBrowserTest,
RecordedMimeMetrics) {
base::HistogramTester histogram_tester;
embedded_test_server()->ServeFilesFromSourceDirectory(
"chrome/test/data/ad_tagging");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
auto waiter = CreateAdsPageLoadMetricsTestWaiter();
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
ui_test_utils::NavigateToURL(
browser(),
embedded_test_server()->GetURL("foo.com", "/frame_factory.html"));
contents->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("createFrame('multiple_mimes.html', 'test');"));
waiter->AddMinimumAdResourceExpectation(8);
waiter->Wait();
// Close all tabs to log metrics, as the video resource request is incomplete.
browser()->tab_strip_model()->CloseAllTabs();
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.HTML", 1);
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.CSS", 1);
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.JS", 3);
// Note: png and video/webm mime types are not set explicitly by the
// embedded_test_server.
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.Image", 1);
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.Video", 1);
histogram_tester.ExpectTotalCount("Ads.ResourceUsage.Size.Mime.Other", 1);
}
...@@ -182,6 +182,9 @@ struct ResourceDataUpdate { ...@@ -182,6 +182,9 @@ struct ResourceDataUpdate {
// Whether this resource was loaded in the top-level frame. // Whether this resource was loaded in the top-level frame.
bool is_main_frame_resource; bool is_main_frame_resource;
// Mime type for the resource found in the network response header.
string mime_type;
}; };
// Sent from renderer to browser process when the PageLoadTiming for the // Sent from renderer to browser process when the PageLoadTiming for the
......
...@@ -21,6 +21,8 @@ PageResourceDataUse::PageResourceDataUse() ...@@ -21,6 +21,8 @@ PageResourceDataUse::PageResourceDataUse()
reported_as_ad_resource_(false), reported_as_ad_resource_(false),
is_main_frame_resource_(false) {} is_main_frame_resource_(false) {}
PageResourceDataUse::PageResourceDataUse(const PageResourceDataUse& other) =
default;
PageResourceDataUse::~PageResourceDataUse() = default; PageResourceDataUse::~PageResourceDataUse() = default;
void PageResourceDataUse::DidStartResponse( void PageResourceDataUse::DidStartResponse(
...@@ -29,6 +31,7 @@ void PageResourceDataUse::DidStartResponse( ...@@ -29,6 +31,7 @@ void PageResourceDataUse::DidStartResponse(
resource_id_ = resource_id; resource_id_ = resource_id;
data_reduction_proxy_compression_ratio_estimate_ = data_reduction_proxy_compression_ratio_estimate_ =
data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head); data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head);
mime_type_ = response_head.mime_type;
total_received_bytes_ = 0; total_received_bytes_ = 0;
last_update_bytes_ = 0; last_update_bytes_ = 0;
} }
...@@ -85,6 +88,7 @@ mojom::ResourceDataUpdatePtr PageResourceDataUse::GetResourceDataUpdate() { ...@@ -85,6 +88,7 @@ mojom::ResourceDataUpdatePtr PageResourceDataUse::GetResourceDataUpdate() {
data_reduction_proxy_compression_ratio_estimate_; data_reduction_proxy_compression_ratio_estimate_;
resource_data_update->reported_as_ad_resource = reported_as_ad_resource_; resource_data_update->reported_as_ad_resource = reported_as_ad_resource_;
resource_data_update->is_main_frame_resource = is_main_frame_resource_; resource_data_update->is_main_frame_resource = is_main_frame_resource_;
resource_data_update->mime_type = mime_type_;
return resource_data_update; return resource_data_update;
} }
} // namespace page_load_metrics } // namespace page_load_metrics
...@@ -20,6 +20,7 @@ namespace page_load_metrics { ...@@ -20,6 +20,7 @@ namespace page_load_metrics {
class PageResourceDataUse { class PageResourceDataUse {
public: public:
PageResourceDataUse(); PageResourceDataUse();
PageResourceDataUse(const PageResourceDataUse& other);
~PageResourceDataUse(); ~PageResourceDataUse();
void DidStartResponse(int resource_id, void DidStartResponse(int resource_id,
...@@ -67,6 +68,8 @@ class PageResourceDataUse { ...@@ -67,6 +68,8 @@ class PageResourceDataUse {
bool reported_as_ad_resource_; bool reported_as_ad_resource_;
bool is_main_frame_resource_; bool is_main_frame_resource_;
std::string mime_type_;
DISALLOW_ASSIGN(PageResourceDataUse); DISALLOW_ASSIGN(PageResourceDataUse);
}; };
......
<html>
<script src="ad_script.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<img src="pixel.png"></img>
<video src="bear-320x240-video-only.webm" preload="auto"></video>
<iframe src="test.pdf"></iframe>
</html>
/*
* Copyright 2014 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.
*/
/* Fake style sheet */
This diff was suppressed by a .gitattributes entry.
...@@ -32,6 +32,8 @@ const char kMockHttpHeadersExtension[] = "mock-http-headers"; ...@@ -32,6 +32,8 @@ const char kMockHttpHeadersExtension[] = "mock-http-headers";
std::string GetContentType(const base::FilePath& path) { std::string GetContentType(const base::FilePath& path) {
if (path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) if (path.MatchesExtension(FILE_PATH_LITERAL(".crx")))
return "application/x-chrome-extension"; return "application/x-chrome-extension";
if (path.MatchesExtension(FILE_PATH_LITERAL(".css")))
return "text/css";
if (path.MatchesExtension(FILE_PATH_LITERAL(".exe"))) if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
return "application/octet-stream"; return "application/octet-stream";
if (path.MatchesExtension(FILE_PATH_LITERAL(".gif"))) if (path.MatchesExtension(FILE_PATH_LITERAL(".gif")))
......
...@@ -673,6 +673,18 @@ uploading your change for review. ...@@ -673,6 +673,18 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram base="true" name="Ads.ResourceUsage.Size.Mime" units="KB"
expires_after="2019-09-10">
<owner>johnidel@chromium.org</owner>
<owner>jkarlin@chromium.org</owner>
<summary>
Size of resources tagged as ads, identified by the response header mime
type. This includes resources that did not complete loading. Recorded when
the resource request is completed. For incomplete requests, recorded when
the page is destroyed/navigated.
</summary>
</histogram>
<histogram name="Ads.ResourceUsage.Size.Subframe.AdResource" units="KB" <histogram name="Ads.ResourceUsage.Size.Subframe.AdResource" units="KB"
expires_after="2019-09-05"> expires_after="2019-09-05">
<owner>jkarlin@chromium.org</owner> <owner>jkarlin@chromium.org</owner>
...@@ -120049,6 +120061,20 @@ uploading your change for review. ...@@ -120049,6 +120061,20 @@ uploading your change for review.
<affected-histogram name="Startup.Android.Cold.TimeToFirstNavigationCommit"/> <affected-histogram name="Startup.Android.Cold.TimeToFirstNavigationCommit"/>
</histogram_suffixes> </histogram_suffixes>
<histogram_suffixes name="AdResourceMimeTypes" separator=".">
<suffix name="CSS" label="Resources identified by text/css."/>
<suffix name="HTML" label="Resources identified by text/html."/>
<suffix name="Image"
label="Resources identified by any supported image mime type."/>
<suffix name="JS"
label="Resources identified by any supported javascript mime type."/>
<suffix name="Other"
label="Resources identified by any mime type that did match any
supported css, html, image, javascript, or video mime types."/>
<suffix name="Video" label="Resources identified by video/*."/>
<affected-histogram name="Ads.ResourceUsage.Size.Mime"/>
</histogram_suffixes>
<histogram_suffixes name="AdsPageLoadMetrics" separator="." ordering="prefix"> <histogram_suffixes name="AdsPageLoadMetrics" separator="." ordering="prefix">
<suffix name="Clients.Ads.All" label="Includes all discovered ads."/> <suffix name="Clients.Ads.All" label="Includes all discovered ads."/>
<suffix name="Clients.Ads.Google" label="Includes only Google ads."/> <suffix name="Clients.Ads.Google" label="Includes only Google ads."/>
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