Chromium Code Reviews| Index: chrome/browser/page_load_metrics/metrics_web_contents_observer.cc |
| diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc |
| index 926978a722908430d4ab523137ffa0f6886562dd..65a0264a6ccd3430746ccab0b609178b3fa42ad0 100644 |
| --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc |
| +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc |
| @@ -20,6 +20,7 @@ |
| #include "chrome/common/page_load_metrics/page_load_metrics_messages.h" |
| #include "chrome/common/page_load_metrics/page_load_timing.h" |
| #include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/global_request_id.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/render_frame_host.h" |
| @@ -175,29 +176,67 @@ void MetricsWebContentsObserver::WillStartNavigationRequest( |
| chain_size_same_url))); |
| } |
| +PageLoadTracker* MetricsWebContentsObserver::GetTrackerOrNullForRequest( |
| + const content::GlobalRequestID& request_id, |
| + content::ResourceType resource_type, |
| + base::TimeTicks creation_time) { |
| + if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) { |
| + // The main frame request can complete either before or after commit, so we |
| + // look at both provisional loads and the committed load to find a |
| + // PageLoadTracker with a matching request id. See |
| + // https://docs.google.com/document/d/1dZP0si0IKEMeVKGsohJ3fFWiKqh3nZBtuTFVkAPSXYM/edit |
|
Charlie Harrison
2017/01/13 15:56:23
optional: Can you shorten this with a https://goo.
Bryan McQuade
2017/01/17 15:06:26
done
|
| + // for more details. |
| + for (const auto& kv : provisional_loads_) { |
|
RyanSturm
2017/01/13 15:39:50
I'd actually suggest going a step further for the
Bryan McQuade
2017/01/13 15:47:14
Ah, interesting, what problem would we solve by st
Bryan McQuade
2017/01/13 15:53:17
Ah, maybe you are concerned that we won't have the
RyanSturm
2017/01/13 16:15:46
Like you said, clamy@ is the expert here, but I be
|
| + PageLoadTracker* candidate = kv.second.get(); |
| + if (candidate->HasMatchingNavigationRequestID(request_id)) { |
| + return candidate; |
| + } |
| + } |
| + if (committed_load_ && |
| + committed_load_->HasMatchingNavigationRequestID(request_id)) { |
| + return committed_load_.get(); |
| + } |
| + } else { |
| + // Non main frame resources are always associated with the currently |
| + // committed load. If the resource request was started before this |
| + // navigation then it should be ignored. |
| + |
| + // TODO(jkarlin): There is a race here. Consider the following sequence: |
| + // 1. renderer has a committed page A |
| + // 2. navigation is initiated to page B |
| + // 3. page A initiates URLRequests (e.g. in the unload handler) |
| + // 4. page B commits |
| + // 5. the URLRequests initiated by A complete |
|
Charlie Harrison
2017/01/13 15:56:23
Shouldn't the request be cancelled? I guess it cou
Bryan McQuade
2017/01/17 15:06:26
Unfortunately that doesn't seem to be the case. I
|
| + // In the above example, the URLRequests initiated by A will be attributed |
| + // to page load B. This should be relatively rare but we may want to fix |
| + // this at some point. We could fix this by comparing the URLRequest |
| + // creation time against the committed load's commit time, however more |
| + // investigation is needed to confirm that all cases would be handled |
| + // correctly (for example Link: preloads). |
| + if (committed_load_ && |
| + creation_time >= committed_load_->navigation_start()) { |
| + return committed_load_.get(); |
| + } |
| + } |
| + return nullptr; |
| +} |
| + |
| void MetricsWebContentsObserver::OnRequestComplete( |
| + const content::GlobalRequestID& request_id, |
| content::ResourceType resource_type, |
| bool was_cached, |
| bool used_data_reduction_proxy, |
| int64_t raw_body_bytes, |
| int64_t original_content_length, |
| base::TimeTicks creation_time) { |
| - // If the navigation hasn't committed yet then we'll miss the resource (this |
| - // happens on the new tab page). Also, if the resource request was started |
| - // before this navigation then it should be ignored. |
| - // TODO(jkarlin): There is a race here. If a renderer starts URLRequests for |
| - // page A after navigating (but before comitting) to page B, then page A's |
| - // requests might wind up counting toward page B's size. This should be |
| - // relatively rare but we may want to fix this at some point. |
| - if (!committed_load_ || creation_time < committed_load_->navigation_start()) { |
| - return; |
| + PageLoadTracker* tracker = |
| + GetTrackerOrNullForRequest(request_id, resource_type, creation_time); |
| + if (tracker) { |
| + ExtraRequestInfo extra_request_info( |
| + was_cached, raw_body_bytes, used_data_reduction_proxy, |
| + was_cached ? 0 : original_content_length); |
| + tracker->OnLoadedResource(extra_request_info); |
| } |
| - |
| - ExtraRequestInfo extra_request_info(was_cached, raw_body_bytes, |
| - used_data_reduction_proxy, |
| - was_cached ? 0 : original_content_length); |
| - |
| - committed_load_->OnLoadedResource(extra_request_info); |
| } |
| const PageLoadExtraInfo |
| @@ -206,6 +245,14 @@ MetricsWebContentsObserver::GetPageLoadExtraInfoForCommittedLoad() { |
| return committed_load_->ComputePageLoadExtraInfo(); |
| } |
| +void MetricsWebContentsObserver::ReadyToCommitNavigation( |
| + content::NavigationHandle* navigation_handle) { |
| + auto it = provisional_loads_.find(navigation_handle); |
| + if (it == provisional_loads_.end()) |
| + return; |
| + it->second->ReadyToCommit(navigation_handle); |
| +} |
| + |
| void MetricsWebContentsObserver::DidFinishNavigation( |
| content::NavigationHandle* navigation_handle) { |
| if (!navigation_handle->IsInMainFrame()) |