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

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

Issue 2861433005: [PageLoadMetrics] Reenable AdsMetrics and handle case where navigation aborts (Closed)
Patch Set: Fix Created 3 years, 7 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
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_obser ver.h" 5 #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_obser ver.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/feature_list.h" 10 #include "base/feature_list.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" 14 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
15 #include "content/public/browser/navigation_handle.h" 15 #include "content/public/browser/navigation_handle.h"
16 #include "content/public/browser/render_frame_host.h" 16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
18 #include "url/gurl.h" 18 #include "url/gurl.h"
19 19
20 namespace { 20 namespace {
21 21
22 const base::Feature kAdsFeature{"AdsMetrics", 22 const base::Feature kAdsFeature{"AdsMetrics", base::FEATURE_ENABLED_BY_DEFAULT};
Charlie Harrison 2017/05/04 20:21:14 Please mention in the description that this CL re-
jkarlin 2017/05/05 19:56:28 Done.
23 base::FEATURE_DISABLED_BY_DEFAULT};
24 23
25 bool FrameIsAd(content::NavigationHandle* navigation_handle) { 24 bool FrameIsAd(const GURL& url, const std::string& frame_name) {
26 content::RenderFrameHost* current_frame_host =
27 navigation_handle->GetRenderFrameHost();
28 DCHECK(current_frame_host);
29 const std::string& name = current_frame_host->GetFrameName();
30 const GURL& url = navigation_handle->GetURL();
31
32 // Because sub-resource filtering isn't always enabled, and doesn't work 25 // Because sub-resource filtering isn't always enabled, and doesn't work
33 // well in monitoring mode (no CSS enforcement), it's difficult to identify 26 // well in monitoring mode (no CSS enforcement), it's difficult to identify
34 // ads. Google ads are prevalent and easy to track, so we'll start by 27 // ads. Google ads are prevalent and easy to track, so we'll start by
35 // tracking those. Note that the frame name can be very large, so be careful 28 // tracking those. Note that the frame name can be very large, so be careful
36 // to avoid full string searches if possible. 29 // to avoid full string searches if possible.
37 // TODO(jkarlin): Track other ad networks that are easy to identify. 30 // TODO(jkarlin): Track other ad networks that are easy to identify.
38 return base::StartsWith(name, "google_ads_iframe", 31 return base::StartsWith(frame_name, "google_ads_iframe",
39 base::CompareCase::SENSITIVE) || 32 base::CompareCase::SENSITIVE) ||
40 base::StartsWith(name, "google_ads_frame", 33 base::StartsWith(frame_name, "google_ads_frame",
41 base::CompareCase::SENSITIVE) || 34 base::CompareCase::SENSITIVE) ||
42 (url.host_piece() == "tpc.googlesyndication.com" && 35 (url.host_piece() == "tpc.googlesyndication.com" &&
43 base::StartsWith(url.path_piece(), "/safeframe", 36 base::StartsWith(url.path_piece(), "/safeframe",
44 base::CompareCase::SENSITIVE)); 37 base::CompareCase::SENSITIVE));
45 } 38 }
46 39
47 } // namespace 40 } // namespace
48 41
49 AdsPageLoadMetricsObserver::AdFrameData::AdFrameData( 42 AdsPageLoadMetricsObserver::AdFrameData::AdFrameData(
50 FrameTreeNodeId frame_tree_node_id) 43 FrameTreeNodeId frame_tree_node_id)
(...skipping 21 matching lines...) Expand all
72 ad_frames_data_[navigation_handle->GetFrameTreeNodeId()] = nullptr; 65 ad_frames_data_[navigation_handle->GetFrameTreeNodeId()] = nullptr;
73 ProcessOngoingNavigationResource(navigation_handle->GetFrameTreeNodeId()); 66 ProcessOngoingNavigationResource(navigation_handle->GetFrameTreeNodeId());
74 return CONTINUE_OBSERVING; 67 return CONTINUE_OBSERVING;
75 } 68 }
76 69
77 page_load_metrics::PageLoadMetricsObserver::ObservePolicy 70 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
78 AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation( 71 AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
79 content::NavigationHandle* navigation_handle) { 72 content::NavigationHandle* navigation_handle) {
80 FrameTreeNodeId frame_tree_node_id = navigation_handle->GetFrameTreeNodeId(); 73 FrameTreeNodeId frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
81 74
82 if (!navigation_handle->HasCommitted() || 75 if ((!navigation_handle->HasCommitted() ||
83 navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage()) { 76 navigation_handle->IsSameDocument() ||
77 navigation_handle->IsErrorPage()) &&
78 navigation_handle->GetNetErrorCode() != net::ERR_ABORTED) {
Charlie Harrison 2017/05/04 20:21:14 #include net errors
jkarlin 2017/05/05 19:56:28 Done.
84 // We're not interested in tracking this navigation. In case we've seen a 79 // We're not interested in tracking this navigation. In case we've seen a
Charlie Harrison 2017/05/04 20:21:14 IMO pulling this whole comment above the if statem
jkarlin 2017/05/05 19:56:28 Done.
85 // resource for the navigation before this message, clear it from 80 // resource for the navigation before this message, clear it from
86 // ongoing_navigation_resources_. 81 // ongoing_navigation_resources_.
82 //
83 // Note that we *do* keep track of net::ERR_ABORTED navigations because
84 // the frame can continue to load resources (either from the previous
85 // navigation or from a document written by doc.write which aborted the
86 // navigation).
Charlie Harrison 2017/05/04 20:21:14 I imagine this is not the only way the navigation
jkarlin 2017/05/05 19:56:28 Done.
87 ongoing_navigation_resources_.erase(frame_tree_node_id); 87 ongoing_navigation_resources_.erase(frame_tree_node_id);
88 return CONTINUE_OBSERVING; 88 return CONTINUE_OBSERVING;
89 } 89 }
90 90
91 content::RenderFrameHost* parent_frame_host = 91 // Get the RFH from the frame tree node id because
92 navigation_handle->GetRenderFrameHost()->GetParent(); 92 // NavigationHandle->GetRenderFrameHost doesn't like being called for
Charlie Harrison 2017/05/04 20:21:14 Slightly awkward wording. It's helpful to differen
jkarlin 2017/05/05 19:56:28 Done.
93 // uncomitted navigations (e.g., due to an abort).
94 content::RenderFrameHost* current_frame_host =
95 navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId(
96 frame_tree_node_id);
97 content::RenderFrameHost* parent_frame_host = current_frame_host->GetParent();
93 DCHECK(parent_frame_host); 98 DCHECK(parent_frame_host);
94 99
95 bool top_level_subframe = !parent_frame_host->GetParent(); 100 bool top_level_subframe = !parent_frame_host->GetParent();
96 101
97 const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id); 102 const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id);
98 if (id_and_data != ad_frames_data_.end()) { 103 if (id_and_data != ad_frames_data_.end()) {
99 // An existing subframe is navigating again. 104 // An existing subframe is navigating again.
100 if (id_and_data->second) { 105 if (id_and_data->second) {
101 // The subframe was an ad to begin with, keep tracking it as an ad. 106 // The subframe was an ad to begin with, keep tracking it as an ad.
102 ProcessOngoingNavigationResource(frame_tree_node_id); 107 ProcessOngoingNavigationResource(frame_tree_node_id);
103 108
104 if (frame_tree_node_id == id_and_data->second->frame_tree_node_id) { 109 if (frame_tree_node_id == id_and_data->second->frame_tree_node_id) {
105 // This is the top-most frame in the ad. 110 // This is the top-most frame in the ad.
106 UMA_HISTOGRAM_BOOLEAN( 111 UMA_HISTOGRAM_BOOLEAN(
107 "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd", 112 "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd",
108 FrameIsAd(navigation_handle)); 113 FrameIsAd(navigation_handle->GetURL(),
114 current_frame_host->GetFrameName()));
109 } 115 }
110 116
111 return CONTINUE_OBSERVING; 117 return CONTINUE_OBSERVING;
112 } 118 }
113 // This frame was previously not an ad, process it as usual. If it had 119 // This frame was previously not an ad, process it as usual. If it had
114 // any child frames that were ads, those will still be recorded. 120 // any child frames that were ads, those will still be recorded.
115 UMA_HISTOGRAM_BOOLEAN( 121 UMA_HISTOGRAM_BOOLEAN(
116 "PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd", 122 "PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd",
117 FrameIsAd(navigation_handle)); 123 FrameIsAd(navigation_handle->GetURL(),
124 current_frame_host->GetFrameName()));
118 } else if (top_level_subframe) { 125 } else if (top_level_subframe) {
119 top_level_subframe_count_ += 1; 126 top_level_subframe_count_ += 1;
120 } 127 }
121 128
122 // Determine who the parent frame's ad ancestor is. 129 // Determine who the parent frame's ad ancestor is.
123 const auto& parent_id_and_data = 130 const auto& parent_id_and_data =
124 ad_frames_data_.find(parent_frame_host->GetFrameTreeNodeId()); 131 ad_frames_data_.find(parent_frame_host->GetFrameTreeNodeId());
125 DCHECK(parent_id_and_data != ad_frames_data_.end()); 132 DCHECK(parent_id_and_data != ad_frames_data_.end());
126 AdFrameData* ad_data = parent_id_and_data->second; 133 AdFrameData* ad_data = parent_id_and_data->second;
127 134
128 if (!ad_data && FrameIsAd(navigation_handle)) { 135 if (!ad_data && FrameIsAd(navigation_handle->GetURL(),
136 current_frame_host->GetFrameName())) {
129 // This frame is not nested within an ad frame but is itself an ad. 137 // This frame is not nested within an ad frame but is itself an ad.
130 ad_frames_data_storage_.emplace_back(frame_tree_node_id); 138 ad_frames_data_storage_.emplace_back(frame_tree_node_id);
131 ad_data = &ad_frames_data_storage_.back(); 139 ad_data = &ad_frames_data_storage_.back();
132 } 140 }
133 141
134 ad_frames_data_[frame_tree_node_id] = ad_data; 142 ad_frames_data_[frame_tree_node_id] = ad_data;
135 143
136 if (top_level_subframe && ad_data) 144 if (top_level_subframe && ad_data)
137 top_level_ad_frame_count_ += 1; 145 top_level_ad_frame_count_ += 1;
138 146
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 void AdsPageLoadMetricsObserver::ProcessOngoingNavigationResource( 297 void AdsPageLoadMetricsObserver::ProcessOngoingNavigationResource(
290 FrameTreeNodeId frame_tree_node_id) { 298 FrameTreeNodeId frame_tree_node_id) {
291 const auto& frame_id_and_request = 299 const auto& frame_id_and_request =
292 ongoing_navigation_resources_.find(frame_tree_node_id); 300 ongoing_navigation_resources_.find(frame_tree_node_id);
293 if (frame_id_and_request == ongoing_navigation_resources_.end()) 301 if (frame_id_and_request == ongoing_navigation_resources_.end())
294 return; 302 return;
295 303
296 ProcessLoadedResource(frame_id_and_request->second); 304 ProcessLoadedResource(frame_id_and_request->second);
297 ongoing_navigation_resources_.erase(frame_id_and_request); 305 ongoing_navigation_resources_.erase(frame_id_and_request);
298 } 306 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698