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

Unified Diff: chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc

Issue 2883433002: [PageLoadMetrics] Handle case where navigation aborts (Closed)
Patch Set: Back to PS3 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
index f6a08a182e620ff14f156528597e3cf507d7550c..cb4ad34eb17a622ce00c2c42f48422321c4145cb 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
@@ -23,25 +23,37 @@ const base::Feature kAdsFeature{"AdsMetrics",
base::FEATURE_DISABLED_BY_DEFAULT};
bool FrameIsAd(content::NavigationHandle* navigation_handle) {
- content::RenderFrameHost* current_frame_host =
- navigation_handle->GetRenderFrameHost();
- DCHECK(current_frame_host);
- const std::string& name = current_frame_host->GetFrameName();
- const GURL& url = navigation_handle->GetURL();
-
// Because sub-resource filtering isn't always enabled, and doesn't work
// well in monitoring mode (no CSS enforcement), it's difficult to identify
// ads. Google ads are prevalent and easy to track, so we'll start by
// tracking those. Note that the frame name can be very large, so be careful
// to avoid full string searches if possible.
// TODO(jkarlin): Track other ad networks that are easy to identify.
- return base::StartsWith(name, "google_ads_iframe",
- base::CompareCase::SENSITIVE) ||
- base::StartsWith(name, "google_ads_frame",
- base::CompareCase::SENSITIVE) ||
- (url.host_piece() == "tpc.googlesyndication.com" &&
- base::StartsWith(url.path_piece(), "/safeframe",
- base::CompareCase::SENSITIVE));
+
+ // In case the navigation aborted, look up the RFH by the Frame Tree Node
+ // ID. It returns the committed frame host or the initial frame host for the
+ // frame if no committed host exists. Using a previous host is fine because
+ // once a frame has an ad we always consider it to have an ad.
+ // We use the unsafe method of FindFrameByFrameTreeNodeId because we're not
+ // concerned with which process the frame lives on (we're just measuring
+ // bytes and not granting security priveleges).
+ content::RenderFrameHost* current_frame_host =
+ navigation_handle->GetWebContents()->UnsafeFindFrameByFrameTreeNodeId(
+ navigation_handle->GetFrameTreeNodeId());
+ if (current_frame_host) {
+ const std::string& frame_name = current_frame_host->GetFrameName();
+ if (base::StartsWith(frame_name, "google_ads_iframe",
+ base::CompareCase::SENSITIVE) ||
+ base::StartsWith(frame_name, "google_ads_frame",
+ base::CompareCase::SENSITIVE)) {
+ return true;
+ }
+ }
+
+ const GURL& url = navigation_handle->GetURL();
+ return url.host_piece() == "tpc.googlesyndication.com" &&
+ base::StartsWith(url.path_piece(), "/safeframe",
+ base::CompareCase::SENSITIVE);
}
} // namespace
@@ -77,22 +89,13 @@ AdsPageLoadMetricsObserver::OnCommit(
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
content::NavigationHandle* navigation_handle) {
+ // Determine if the frame is part of an existing ad, the root of a new ad,
+ // or a non-ad frame. Once a frame is labled as an ad, it is always
+ // considered an ad, even if it navigates to a non-ad page. This function
+ // labels all of a page's frames, even those that fail to commit.
FrameTreeNodeId frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
-
- if (!navigation_handle->HasCommitted() ||
- navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage()) {
- // We're not interested in tracking this navigation. In case we've seen a
- // resource for the navigation before this message, clear it from
- // ongoing_navigation_resources_.
- ongoing_navigation_resources_.erase(frame_tree_node_id);
- return CONTINUE_OBSERVING;
- }
-
content::RenderFrameHost* parent_frame_host =
- navigation_handle->GetRenderFrameHost()->GetParent();
- DCHECK(parent_frame_host);
-
- bool top_level_subframe = !parent_frame_host->GetParent();
+ navigation_handle->GetParentFrame();
const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id);
if (id_and_data != ad_frames_data_.end()) {
@@ -107,7 +110,6 @@ AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
"PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd",
FrameIsAd(navigation_handle));
}
-
return CONTINUE_OBSERVING;
}
// This frame was previously not an ad, process it as usual. If it had
@@ -115,7 +117,7 @@ AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
UMA_HISTOGRAM_BOOLEAN(
"PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd",
FrameIsAd(navigation_handle));
- } else if (top_level_subframe) {
+ } else if (navigation_handle->IsParentMainFrame()) {
top_level_subframe_count_ += 1;
}
@@ -133,7 +135,7 @@ AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
ad_frames_data_[frame_tree_node_id] = ad_data;
- if (top_level_subframe && ad_data)
+ if (navigation_handle->IsParentMainFrame() && ad_data)
top_level_ad_frame_count_ += 1;
ProcessOngoingNavigationResource(frame_tree_node_id);
@@ -176,12 +178,13 @@ void AdsPageLoadMetricsObserver::ProcessLoadedResource(
const auto& id_and_data =
ad_frames_data_.find(extra_request_info.frame_tree_node_id);
if (id_and_data == ad_frames_data_.end()) {
- // This resouce is for a frame that hasn't yet committed. It must be the
- // main document for the frame. Hold onto it and once it commits we'll run
- // it in ProcessOngoingNavigationResource.
- // TODO(jkarlin): Plumb the resource type through and DCHECK that the type
- // is document.
- auto it_and_success = ongoing_navigation_resources_.emplace(
+ // This resource is for a frame that hasn't ever finished a navigation. We
+ // expect it to be the frame's main resource but don't have enough
+ // confidence in that to dcheck it. For example, there might be races
+ // between doc.written resources and navigation failure.
+ // TODO(jkarlin): Add UMA to measure how often we see multiple resources
+ // for a frame before navigation finishes.
+ ongoing_navigation_resources_.emplace(
std::piecewise_construct,
std::forward_as_tuple(extra_request_info.frame_tree_node_id),
std::forward_as_tuple(
@@ -189,7 +192,6 @@ void AdsPageLoadMetricsObserver::ProcessLoadedResource(
extra_request_info.was_cached, extra_request_info.raw_body_bytes,
extra_request_info.original_network_content_length, nullptr,
extra_request_info.resource_type));
- DCHECK(it_and_success.second);
return;
}

Powered by Google App Engine
This is Rietveld 408576698