Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc

Issue 2798953002: [PageLoadMetrics] Keep track of Ad Sizes on Pages (Closed)
Patch Set: Add tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_obser ver.h"
6
7 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
8 #include "content/public/browser/render_frame_host.h"
9 #include "content/public/browser/web_contents.h"
10
11 namespace {
12
13 bool FrameIsAd(content::NavigationHandle* navigation_handle) {
14 int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
15 content::RenderFrameHost* current_frame_host =
16 navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId(
17 frame_tree_node_id);
18 const std::string& name = current_frame_host->GetFrameName();
19 const std::string& url_spec = navigation_handle->GetURL().spec();
20
21 return base::StartsWith(name, "google_ads_iframe",
ojan 2017/04/07 19:40:06 People will stumble across this in public. Anywher
jkarlin 2017/04/10 17:52:23 Done.
22 base::CompareCase::SENSITIVE) ||
23 base::StartsWith(name, "google_ads_frame",
24 base::CompareCase::SENSITIVE) ||
25 base::StartsWith(url_spec,
26 "http://tpc.googlesyndication.com/safeframe/",
27 base::CompareCase::SENSITIVE) ||
28 base::StartsWith(url_spec,
29 "https://tpc.googlesyndication.com/safeframe/",
30 base::CompareCase::SENSITIVE);
31 }
32
33 } // namespace
34
35 AdsPageLoadMetricsObserver::AdsPageLoadMetricsObserver() = default;
36 AdsPageLoadMetricsObserver::~AdsPageLoadMetricsObserver() = default;
37
38 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
39 AdsPageLoadMetricsObserver::OnCommit(
40 content::NavigationHandle* navigation_handle) {
41 DCHECK(ad_frames_.empty());
42 DCHECK(ad_ancestors_.empty());
43
44 // The main frame is never considered an ad.
45 ad_ancestors_[navigation_handle->GetFrameTreeNodeId()] =
46 kInvalidFrameTreeNodeId;
47 ProcessDelayedResources(navigation_handle->GetFrameTreeNodeId());
48 return CONTINUE_OBSERVING;
49 }
50
51 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
52 AdsPageLoadMetricsObserver::OnCommitSubFrame(
53 content::NavigationHandle* navigation_handle) {
54 DCHECK(
55 !base::ContainsKey(ad_frames_, navigation_handle->GetFrameTreeNodeId()));
56
57 FrameTreeNodeId frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
58 FrameTreeNodeId ancestor_id = FindAdAncestor(navigation_handle);
59
60 if (ancestor_id != kInvalidFrameTreeNodeId) {
61 ad_ancestors_[frame_tree_node_id] = ancestor_id;
62 ProcessDelayedResources(frame_tree_node_id);
63 return CONTINUE_OBSERVING;
64 }
65
66 if (FrameIsAd(navigation_handle)) {
67 ad_frames_[frame_tree_node_id] = AdFrameData();
68 ad_ancestors_[frame_tree_node_id] = frame_tree_node_id;
69 ProcessDelayedResources(frame_tree_node_id);
70 return CONTINUE_OBSERVING;
71 }
72
73 ad_ancestors_[frame_tree_node_id] = kInvalidFrameTreeNodeId;
74 ProcessDelayedResources(frame_tree_node_id);
75 return CONTINUE_OBSERVING;
76 }
77
78 void AdsPageLoadMetricsObserver::OnLoadedResource(
79 const page_load_metrics::ExtraRequestInfo& extra_request_info) {
80 if (!base::ContainsKey(ad_ancestors_,
81 extra_request_info.frame_tree_node_id)) {
82 // This resouce is for a frame that hasn't yet committed. It must be the
83 // main document for the frame. Hold onto it and once it commits we'll run
84 // it in ProcessDelayedResources.
85 auto it_and_success = delayed_resources_.insert(std::make_pair(
86 extra_request_info.frame_tree_node_id, extra_request_info));
87 DCHECK(it_and_success.second);
88 return;
89 }
90
91 page_bytes_ += extra_request_info.raw_body_bytes;
92 if (!extra_request_info.was_cached)
93 uncached_page_bytes_ += extra_request_info.raw_body_bytes;
94
95 // Determine if the frame (or its ancestor) is an ad, if so attribute the
96 // bytes to the highest ad ancestor.
97 FrameTreeNodeId ad_ancestor_id =
98 ad_ancestors_[extra_request_info.frame_tree_node_id];
99 if (ad_ancestor_id != kInvalidFrameTreeNodeId) {
100 ad_frames_[ad_ancestor_id].frame_bytes += extra_request_info.raw_body_bytes;
101 if (!extra_request_info.was_cached)
102 ad_frames_[ad_ancestor_id].frame_bytes_uncached +=
103 extra_request_info.raw_body_bytes;
104 }
105 }
106
107 void AdsPageLoadMetricsObserver::OnComplete(
ojan 2017/04/07 19:40:06 Do you also need to hook FlushMetricsOnAppEnterBac
jkarlin 2017/04/10 17:52:23 Good idea. Done.
108 const page_load_metrics::PageLoadTiming& timing,
109 const page_load_metrics::PageLoadExtraInfo& info) {
110 if (page_bytes_ == 0)
111 return;
112
113 size_t total_ad_frame_bytes = 0;
114 size_t uncached_ad_frame_bytes = 0;
115 int ad_frames = 0;
116
117 for (const auto& frame_id_and_size : ad_frames_) {
118 total_ad_frame_bytes += frame_id_and_size.second.frame_bytes;
119 uncached_ad_frame_bytes += frame_id_and_size.second.frame_bytes_uncached;
120
121 const AdFrameData& data = frame_id_and_size.second;
122 if (data.frame_bytes > 0) {
123 ad_frames += 1;
124 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.AdFrame",
125 data.frame_bytes);
126 PAGE_BYTES_HISTOGRAM(
127 "PageLoad.Clients.Ads.Google.Bytes.AdFrameFromNetwork",
128 data.frame_bytes_uncached);
129 UMA_HISTOGRAM_PERCENTAGE(
130 "PageLoad.Experimental.Ads.Google.BytesPercent.AdFrameFromNetwork",
131 data.frame_bytes_uncached * 100 / data.frame_bytes);
132 }
133 }
134
135 // Don't post UMA for pages that don't have ads or content.
136 if (total_ad_frame_bytes == 0) {
137 UMA_HISTOGRAM_COUNTS("PageLoad.Clients.Ads.Google.PageHasNoAds", 1);
138 return;
139 }
140
141 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.AdFrames",
142 total_ad_frame_bytes);
143
144 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.PageSansAdFrames",
145 page_bytes_ - total_ad_frame_bytes);
146
147 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.Page", page_bytes_);
148 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.PageFromNetwork",
149 uncached_page_bytes_);
150
151 UMA_HISTOGRAM_PERCENTAGE(
152 "PageLoad.Experimental.Ads.Google.BytesPercent.AdFrames",
153 total_ad_frame_bytes * 100 / page_bytes_);
154
155 UMA_HISTOGRAM_COUNTS_1000("PageLoad.Clients.Ads.Google.AdFrameCount",
156 ad_frames);
157
158 PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.AdFramesFromNetwork",
159 uncached_ad_frame_bytes);
160
161 UMA_HISTOGRAM_PERCENTAGE(
162 "PageLoad.Experimental.Ads.Google.BytesPercent."
163 "AdFramesFromNetworkOfAdFramesTotal",
164 uncached_ad_frame_bytes * 100 / total_ad_frame_bytes);
165
166 int percent_bytes_from_uncached_ads =
167 uncached_page_bytes_ == 0
168 ? 0
169 : uncached_ad_frame_bytes * 100 / uncached_page_bytes_;
170 UMA_HISTOGRAM_PERCENTAGE(
171 "PageLoad.Clients.Ads.Google.Bytes.Percent."
172 "AdFramesFromNetworkOfPageFromNetwork",
173 percent_bytes_from_uncached_ads);
174 }
175
176 int AdsPageLoadMetricsObserver::FindAdAncestor(
177 content::NavigationHandle* navigation_handle) {
178 // We haven't seen a load from this frame before. We should have seen its
179 // parent though. Use the ad ancestor of its parent.
180 content::RenderFrameHost* parent_frame_host =
181 navigation_handle->GetRenderFrameHost()->GetParent();
182 DCHECK(parent_frame_host); // Since this isn't a main frame.
183 DCHECK(base::ContainsKey(ad_ancestors_,
184 parent_frame_host->GetFrameTreeNodeId()));
185 return ad_ancestors_[parent_frame_host->GetFrameTreeNodeId()];
186 }
187
188 void AdsPageLoadMetricsObserver::ProcessDelayedResources(
189 FrameTreeNodeId frame_tree_node_id) {
190 const auto& frame_id_and_request =
191 delayed_resources_.find(frame_tree_node_id);
192 if (frame_id_and_request == delayed_resources_.end())
193 return;
194 OnLoadedResource(frame_id_and_request->second);
195 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698