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

Side by Side Diff: components/page_load_metrics/browser/metrics_web_contents_observer.cc

Issue 1473153002: PageLoadMetricsObservers observe individual page loads (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Randy review: comment + simpler destructor Created 5 years 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/page_load_metrics/browser/metrics_web_contents_observer.h" 5 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/metrics/user_metrics.h" 10 #include "base/metrics/user_metrics.h"
(...skipping 20 matching lines...) Expand all
31 namespace { 31 namespace {
32 32
33 // The url we see from the renderer side is not always the same as what 33 // The url we see from the renderer side is not always the same as what
34 // we see from the browser side (e.g. chrome://newtab). We want to be 34 // we see from the browser side (e.g. chrome://newtab). We want to be
35 // sure here that we aren't logging UMA for internal pages. 35 // sure here that we aren't logging UMA for internal pages.
36 bool IsRelevantNavigation( 36 bool IsRelevantNavigation(
37 content::NavigationHandle* navigation_handle, 37 content::NavigationHandle* navigation_handle,
38 const GURL& browser_url, 38 const GURL& browser_url,
39 const std::string& mime_type) { 39 const std::string& mime_type) {
40 DCHECK(navigation_handle->HasCommitted()); 40 DCHECK(navigation_handle->HasCommitted());
41 return navigation_handle->IsInMainFrame() && 41 return navigation_handle->IsInMainFrame() &&
Bryan McQuade 2015/12/03 22:10:36 I'm wondering if we should be including some or pa
Charlie Harrison 2015/12/03 22:30:25 Let's expose it when we need to, I don't think any
42 !navigation_handle->IsSamePage() && 42 !navigation_handle->IsSamePage() &&
43 !navigation_handle->IsErrorPage() && 43 !navigation_handle->IsErrorPage() &&
44 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() && 44 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() &&
45 browser_url.SchemeIsHTTPOrHTTPS() && 45 browser_url.SchemeIsHTTPOrHTTPS() &&
46 (mime_type == "text/html" || mime_type == "application/xhtml+xml"); 46 (mime_type == "text/html" || mime_type == "application/xhtml+xml");
47 } 47 }
48 48
49 bool IsValidPageLoadTiming(const PageLoadTiming& timing) { 49 bool IsValidPageLoadTiming(const PageLoadTiming& timing) {
50 if (timing.IsEmpty()) 50 if (timing.IsEmpty())
51 return false; 51 return false;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 if (seconds < 32) 102 if (seconds < 32)
103 return 4; 103 return 4;
104 return 5; 104 return 5;
105 } 105 }
106 106
107 } // namespace 107 } // namespace
108 108
109 PageLoadTracker::PageLoadTracker( 109 PageLoadTracker::PageLoadTracker(
110 bool in_foreground, 110 bool in_foreground,
111 PageLoadMetricsEmbedderInterface* embedder_interface, 111 PageLoadMetricsEmbedderInterface* embedder_interface,
112 content::NavigationHandle* navigation_handle, 112 content::NavigationHandle* navigation_handle)
113 base::ObserverList<PageLoadMetricsObserver, true>* observers) 113 : renderer_tracked_(false),
114 : has_commit_(false), 114 has_commit_(false),
115 navigation_start_(navigation_handle->NavigationStart()), 115 navigation_start_(navigation_handle->NavigationStart()),
116 started_in_foreground_(in_foreground), 116 started_in_foreground_(in_foreground),
117 embedder_interface_(embedder_interface), 117 embedder_interface_(embedder_interface) {
118 observers_(observers) {} 118 embedder_interface_->RegisterObservers(this);
119 for (const auto& observer : observers_) {
120 observer->OnStart(navigation_handle);
121 }
122 }
119 123
120 PageLoadTracker::~PageLoadTracker() { 124 PageLoadTracker::~PageLoadTracker() {
121 if (has_commit_) { 125 if (has_commit_) {
122 RecordTimingHistograms(); 126 RecordTimingHistograms();
123 RecordRappor(); 127 RecordRappor();
124 } 128 }
129 PageLoadExtraInfo info = GetPageLoadMetricsInfo();
130 for (const auto& observer : observers_) {
131 observer->OnComplete(timing_, info);
132 }
125 } 133 }
126 134
127 void PageLoadTracker::WebContentsHidden() { 135 void PageLoadTracker::WebContentsHidden() {
128 // Only log the first time we background in a given page load. 136 // Only log the first time we background in a given page load.
129 if (started_in_foreground_ && background_time_.is_null()) 137 if (started_in_foreground_ && background_time_.is_null())
130 background_time_ = base::TimeTicks::Now(); 138 background_time_ = base::TimeTicks::Now();
131 } 139 }
132 140
133 void PageLoadTracker::WebContentsShown() { 141 void PageLoadTracker::WebContentsShown() {
134 // Only log the first time we foreground in a given page load. 142 // Only log the first time we foreground in a given page load.
135 // Don't log foreground time if we started foregrounded. 143 // Don't log foreground time if we started foregrounded.
136 if (!started_in_foreground_ && foreground_time_.is_null()) 144 if (!started_in_foreground_ && foreground_time_.is_null())
137 foreground_time_ = base::TimeTicks::Now(); 145 foreground_time_ = base::TimeTicks::Now();
138 } 146 }
139 147
140 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { 148 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) {
141 has_commit_ = true; 149 has_commit_ = true;
142 url_ = navigation_handle->GetURL(); 150 url_ = navigation_handle->GetURL();
143 // We log the event that this load started. Because we don't know if a load is 151 // We log the event that this load started. Because we don't know if a load is
144 // relevant or if it will commit before now, we have to log this event at 152 // relevant or if it will commit before now, we have to log this event at
145 // commit time. 153 // commit time.
146 RecordCommittedEvent(COMMITTED_LOAD_STARTED, !started_in_foreground_); 154 if (renderer_tracked())
155 RecordCommittedEvent(RELEVANT_LOAD_STARTED, !started_in_foreground_);
147 156
148 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, 157 for (const auto& observer : observers_) {
149 OnCommit(navigation_handle)); 158 observer->OnCommit(navigation_handle);
159 }
150 } 160 }
151 161
152 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { 162 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) {
153 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, 163 for (const auto& observer : observers_) {
154 OnRedirect(navigation_handle)); 164 observer->OnRedirect(navigation_handle);
165 }
155 } 166 }
156 167
157 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing) { 168 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing) {
158 // Throw away IPCs that are not relevant to the current navigation. 169 // Throw away IPCs that are not relevant to the current navigation.
159 // Two timing structures cannot refer to the same navigation if they indicate 170 // Two timing structures cannot refer to the same navigation if they indicate
160 // that a navigation started at different times, so a new timing struct with a 171 // that a navigation started at different times, so a new timing struct with a
161 // different start time from an earlier struct is considered invalid. 172 // different start time from an earlier struct is considered invalid.
162 bool valid_timing_descendent = 173 bool valid_timing_descendent =
163 timing_.navigation_start.is_null() || 174 timing_.navigation_start.is_null() ||
164 timing_.navigation_start == new_timing.navigation_start; 175 timing_.navigation_start == new_timing.navigation_start;
165 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent) { 176 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent) {
166 timing_ = new_timing; 177 timing_ = new_timing;
167 return true; 178 return true;
168 } 179 }
169 return false; 180 return false;
170 } 181 }
171 182
172 bool PageLoadTracker::HasBackgrounded() { 183 bool PageLoadTracker::HasBackgrounded() {
173 return !started_in_foreground_ || !background_time_.is_null(); 184 return !started_in_foreground_ || !background_time_.is_null();
174 } 185 }
175 186
187 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) {
188 renderer_tracked_ = renderer_tracked;
189 }
190
191 void PageLoadTracker::AddObserver(
192 scoped_ptr<PageLoadMetricsObserver> observer) {
193 observers_.push_back(std::move(observer));
194 }
195
176 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { 196 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() {
177 base::TimeDelta first_background_time; 197 base::TimeDelta first_background_time;
178 base::TimeDelta first_foreground_time; 198 base::TimeDelta first_foreground_time;
179 if (!background_time_.is_null() && started_in_foreground_) 199 if (!background_time_.is_null() && started_in_foreground_)
180 first_background_time = background_time_ - navigation_start_; 200 first_background_time = background_time_ - navigation_start_;
181 if (!foreground_time_.is_null() && !started_in_foreground_) 201 if (!foreground_time_.is_null() && !started_in_foreground_)
182 first_foreground_time = foreground_time_ - navigation_start_; 202 first_foreground_time = foreground_time_ - navigation_start_;
183 return PageLoadExtraInfo(first_background_time, first_foreground_time, 203 return PageLoadExtraInfo(first_background_time, first_foreground_time,
184 started_in_foreground_); 204 started_in_foreground_, has_commit_);
185 } 205 }
186 206
187 const GURL& PageLoadTracker::GetCommittedURL() { 207 const GURL& PageLoadTracker::committed_url() {
188 DCHECK(has_commit_); 208 DCHECK(has_commit_);
189 return url_; 209 return url_;
190 } 210 }
191 211
192 // Blink calculates navigation start using TimeTicks, but converts to epoch time 212 // Blink calculates navigation start using TimeTicks, but converts to epoch time
193 // in its public API. Thus, to compare time values to navigation start, we 213 // in its public API. Thus, to compare time values to navigation start, we
194 // calculate the current time since the epoch using TimeTicks, and convert to 214 // calculate the current time since the epoch using TimeTicks, and convert to
195 // Time. This method is similar to how blink converts TimeTicks to epoch time. 215 // Time. This method is similar to how blink converts TimeTicks to epoch time.
196 // There may be slight inaccuracies due to inter-process timestamps, but 216 // There may be slight inaccuracies due to inter-process timestamps, but
197 // this solution is the best we have right now. 217 // this solution is the best we have right now.
198 // 218 //
199 // returns a TimeDelta which is 219 // returns a TimeDelta which is
200 // - Infinity if we were never backgrounded 220 // - Infinity if we were never backgrounded
201 // - null (TimeDelta()) if we started backgrounded 221 // - null (TimeDelta()) if we started backgrounded
202 // - elapsed time to first background if we started in the foreground and 222 // - elapsed time to first background if we started in the foreground and
203 // backgrounded. 223 // backgrounded.
204 base::TimeDelta PageLoadTracker::GetBackgroundDelta() { 224 base::TimeDelta PageLoadTracker::GetBackgroundDelta() {
205 if (started_in_foreground_) { 225 if (started_in_foreground_) {
206 return background_time_.is_null() ? base::TimeDelta::Max() 226 return background_time_.is_null() ? base::TimeDelta::Max()
207 : background_time_ - navigation_start_; 227 : background_time_ - navigation_start_;
208 } 228 }
209 return base::TimeDelta(); 229 return base::TimeDelta();
210 } 230 }
211 231
212 void PageLoadTracker::RecordTimingHistograms() { 232 void PageLoadTracker::RecordTimingHistograms() {
213 DCHECK(has_commit_); 233 DCHECK(has_commit_);
234 if (!renderer_tracked())
235 return;
236
214 if (timing_.IsEmpty()) { 237 if (timing_.IsEmpty()) {
215 RecordInternalError(ERR_NO_IPCS_RECEIVED); 238 RecordInternalError(ERR_NO_IPCS_RECEIVED);
216 return; 239 return;
217 } 240 }
218 241
219 PageLoadExtraInfo info = GetPageLoadMetricsInfo();
220 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_,
221 OnComplete(timing_, info));
222
223 base::TimeDelta background_delta = GetBackgroundDelta(); 242 base::TimeDelta background_delta = GetBackgroundDelta();
224 243
225 if (!timing_.dom_content_loaded_event_start.is_zero()) { 244 if (!timing_.dom_content_loaded_event_start.is_zero()) {
226 if (timing_.dom_content_loaded_event_start < background_delta) { 245 if (timing_.dom_content_loaded_event_start < background_delta) {
227 PAGE_LOAD_HISTOGRAM(kHistogramDomContentLoaded, 246 PAGE_LOAD_HISTOGRAM(kHistogramDomContentLoaded,
228 timing_.dom_content_loaded_event_start); 247 timing_.dom_content_loaded_event_start);
229 } else { 248 } else {
230 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramDomContentLoaded, 249 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramDomContentLoaded,
231 timing_.dom_content_loaded_event_start); 250 timing_.dom_content_loaded_event_start);
232 } 251 }
233 } 252 }
234 if (!timing_.load_event_start.is_zero()) { 253 if (!timing_.load_event_start.is_zero()) {
235 if (timing_.load_event_start < background_delta) { 254 if (timing_.load_event_start < background_delta) {
236 PAGE_LOAD_HISTOGRAM(kHistogramLoad, timing_.load_event_start); 255 PAGE_LOAD_HISTOGRAM(kHistogramLoad, timing_.load_event_start);
237 } else { 256 } else {
238 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramLoad, timing_.load_event_start); 257 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramLoad, timing_.load_event_start);
239 } 258 }
240 } 259 }
241 if (timing_.first_layout.is_zero()) { 260 if (timing_.first_layout.is_zero()) {
242 RecordCommittedEvent(COMMITTED_LOAD_FAILED_BEFORE_FIRST_LAYOUT, 261 RecordCommittedEvent(RELEVANT_LOAD_FAILED_BEFORE_FIRST_LAYOUT,
243 HasBackgrounded()); 262 HasBackgrounded());
244 } else { 263 } else {
245 if (timing_.first_layout < background_delta) { 264 if (timing_.first_layout < background_delta) {
246 PAGE_LOAD_HISTOGRAM(kHistogramFirstLayout, timing_.first_layout); 265 PAGE_LOAD_HISTOGRAM(kHistogramFirstLayout, timing_.first_layout);
247 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, false); 266 RecordCommittedEvent(RELEVANT_LOAD_SUCCESSFUL_FIRST_LAYOUT, false);
248 } else { 267 } else {
249 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstLayout, 268 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstLayout,
250 timing_.first_layout); 269 timing_.first_layout);
251 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, true); 270 RecordCommittedEvent(RELEVANT_LOAD_SUCCESSFUL_FIRST_LAYOUT, true);
252 } 271 }
253 } 272 }
254 if (!timing_.first_paint.is_zero()) { 273 if (!timing_.first_paint.is_zero()) {
255 if (timing_.first_paint < background_delta) { 274 if (timing_.first_paint < background_delta) {
256 PAGE_LOAD_HISTOGRAM(kHistogramFirstPaint, timing_.first_paint); 275 PAGE_LOAD_HISTOGRAM(kHistogramFirstPaint, timing_.first_paint);
257 } else { 276 } else {
258 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstPaint, timing_.first_paint); 277 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstPaint, timing_.first_paint);
259 } 278 }
260 } 279 }
261 if (!timing_.first_text_paint.is_zero()) { 280 if (!timing_.first_text_paint.is_zero()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 PROVISIONAL_LOAD_LAST_ENTRY); 329 PROVISIONAL_LOAD_LAST_ENTRY);
311 } else { 330 } else {
312 UMA_HISTOGRAM_ENUMERATION(kProvisionalEvents, event, 331 UMA_HISTOGRAM_ENUMERATION(kProvisionalEvents, event,
313 PROVISIONAL_LOAD_LAST_ENTRY); 332 PROVISIONAL_LOAD_LAST_ENTRY);
314 } 333 }
315 } 334 }
316 335
317 // RecordCommittedEvent needs a backgrounded input because we need to special 336 // RecordCommittedEvent needs a backgrounded input because we need to special
318 // case a few events that need either precise timing measurements, or different 337 // case a few events that need either precise timing measurements, or different
319 // logic than simply "Did I background before logging this event?" 338 // logic than simply "Did I background before logging this event?"
320 void PageLoadTracker::RecordCommittedEvent(CommittedLoadEvent event, 339 void PageLoadTracker::RecordCommittedEvent(CommittedRelevantLoadEvent event,
321 bool backgrounded) { 340 bool backgrounded) {
322 if (backgrounded) { 341 if (backgrounded) {
323 UMA_HISTOGRAM_ENUMERATION(kBackgroundCommittedEvents, event, 342 UMA_HISTOGRAM_ENUMERATION(kBackgroundCommittedEvents, event,
324 COMMITTED_LOAD_LAST_ENTRY); 343 RELEVANT_LOAD_LAST_ENTRY);
325 } else { 344 } else {
326 UMA_HISTOGRAM_ENUMERATION(kCommittedEvents, event, 345 UMA_HISTOGRAM_ENUMERATION(kCommittedEvents, event,
327 COMMITTED_LOAD_LAST_ENTRY); 346 RELEVANT_LOAD_LAST_ENTRY);
328 } 347 }
329 } 348 }
330 349
331 void PageLoadTracker::RecordRappor() { 350 void PageLoadTracker::RecordRappor() {
332 DCHECK(!GetCommittedURL().is_empty()); 351 DCHECK(!committed_url().is_empty());
333 rappor::RapporService* rappor_service = 352 rappor::RapporService* rappor_service =
334 embedder_interface_->GetRapporService(); 353 embedder_interface_->GetRapporService();
335 if (!rappor_service) 354 if (!rappor_service)
336 return; 355 return;
337 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); 356 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_);
338 // Log the eTLD+1 of sites that show poor loading performance. 357 // Log the eTLD+1 of sites that show poor loading performance.
339 if (!first_contentful_paint.is_zero() && 358 if (!first_contentful_paint.is_zero() &&
340 first_contentful_paint < GetBackgroundDelta()) { 359 first_contentful_paint < GetBackgroundDelta()) {
341 scoped_ptr<rappor::Sample> sample = 360 scoped_ptr<rappor::Sample> sample =
342 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); 361 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE);
343 sample->SetStringField("Domain", rappor::GetDomainAndRegistrySampleFromGURL( 362 sample->SetStringField(
344 GetCommittedURL())); 363 "Domain", rappor::GetDomainAndRegistrySampleFromGURL(committed_url()));
345 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint); 364 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint);
346 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index, 365 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index,
347 kNumRapporHistogramBuckets); 366 kNumRapporHistogramBuckets);
348 // The IsSlow flag is just a one bit boolean if the first layout was > 10s. 367 // The IsSlow flag is just a one bit boolean if the first layout was > 10s.
349 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10, 368 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10,
350 1); 369 1);
351 rappor_service->RecordSampleObj(kRapporMetricsNameCoarseTiming, 370 rappor_service->RecordSampleObj(kRapporMetricsNameCoarseTiming,
352 sample.Pass()); 371 sample.Pass());
353 } 372 }
354 } 373 }
(...skipping 13 matching lines...) Expand all
368 387
369 MetricsWebContentsObserver* metrics = FromWebContents(web_contents); 388 MetricsWebContentsObserver* metrics = FromWebContents(web_contents);
370 if (!metrics) { 389 if (!metrics) {
371 metrics = 390 metrics =
372 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass()); 391 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass());
373 web_contents->SetUserData(UserDataKey(), metrics); 392 web_contents->SetUserData(UserDataKey(), metrics);
374 } 393 }
375 return metrics; 394 return metrics;
376 } 395 }
377 396
378 MetricsWebContentsObserver::~MetricsWebContentsObserver() { 397 MetricsWebContentsObserver::~MetricsWebContentsObserver() {}
379 // Reset PageLoadTrackers so observers get final notifications.
380 committed_load_.reset();
381 provisional_loads_.clear();
382 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_,
383 OnPageLoadMetricsGoingAway());
384 }
385
386 void MetricsWebContentsObserver::AddObserver(
387 PageLoadMetricsObserver* observer) {
388 observers_.AddObserver(observer);
389 }
390
391 void MetricsWebContentsObserver::RemoveObserver(
392 PageLoadMetricsObserver* observer) {
393 observers_.RemoveObserver(observer);
394 }
395 398
396 bool MetricsWebContentsObserver::OnMessageReceived( 399 bool MetricsWebContentsObserver::OnMessageReceived(
397 const IPC::Message& message, 400 const IPC::Message& message,
398 content::RenderFrameHost* render_frame_host) { 401 content::RenderFrameHost* render_frame_host) {
399 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 402 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
400 bool handled = true; 403 bool handled = true;
401 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, 404 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message,
402 render_frame_host) 405 render_frame_host)
403 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) 406 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated)
404 IPC_MESSAGE_UNHANDLED(handled = false) 407 IPC_MESSAGE_UNHANDLED(handled = false)
405 IPC_END_MESSAGE_MAP() 408 IPC_END_MESSAGE_MAP()
406 return handled; 409 return handled;
407 } 410 }
408 411
409 void MetricsWebContentsObserver::DidStartNavigation( 412 void MetricsWebContentsObserver::DidStartNavigation(
410 content::NavigationHandle* navigation_handle) { 413 content::NavigationHandle* navigation_handle) {
411 if (!navigation_handle->IsInMainFrame()) 414 if (!navigation_handle->IsInMainFrame())
412 return; 415 return;
413 if (embedder_interface_->IsPrerendering(web_contents())) 416 if (embedder_interface_->IsPrerendering(web_contents()))
414 return; 417 return;
415 // We can have two provisional loads in some cases. E.g. a same-site 418 // We can have two provisional loads in some cases. E.g. a same-site
416 // navigation can have a concurrent cross-process navigation started 419 // navigation can have a concurrent cross-process navigation started
417 // from the omnibox. 420 // from the omnibox.
418 DCHECK_GT(2ul, provisional_loads_.size()); 421 DCHECK_GT(2ul, provisional_loads_.size());
419 // Passing raw pointers to observers_ and embedder_interface_ is safe because 422 // Passing raw pointers to observers_ and embedder_interface_ is safe because
420 // the MetricsWebContentsObserver owns them both list and they are torn down 423 // the MetricsWebContentsObserver owns them both list and they are torn down
421 // after the PageLoadTracker. 424 // after the PageLoadTracker.
422 provisional_loads_.insert(std::make_pair( 425 provisional_loads_.insert(std::make_pair(
423 navigation_handle, make_scoped_ptr(new PageLoadTracker( 426 navigation_handle,
424 in_foreground_, embedder_interface_.get(), 427 make_scoped_ptr(new PageLoadTracker(
425 navigation_handle, &observers_)))); 428 in_foreground_, embedder_interface_.get(), navigation_handle))));
426 } 429 }
427 430
428 void MetricsWebContentsObserver::DidFinishNavigation( 431 void MetricsWebContentsObserver::DidFinishNavigation(
429 content::NavigationHandle* navigation_handle) { 432 content::NavigationHandle* navigation_handle) {
430 if (!navigation_handle->IsInMainFrame()) 433 if (!navigation_handle->IsInMainFrame())
431 return; 434 return;
432 435
433 scoped_ptr<PageLoadTracker> finished_nav( 436 scoped_ptr<PageLoadTracker> finished_nav(
434 std::move(provisional_loads_[navigation_handle])); 437 std::move(provisional_loads_[navigation_handle]));
435 provisional_loads_.erase(navigation_handle); 438 provisional_loads_.erase(navigation_handle);
(...skipping 13 matching lines...) Expand all
449 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED 452 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED
450 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT); 453 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT);
451 return; 454 return;
452 } 455 }
453 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED); 456 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED);
454 457
455 // Don't treat a same-page nav as a new page load. 458 // Don't treat a same-page nav as a new page load.
456 if (navigation_handle->IsSamePage()) 459 if (navigation_handle->IsSamePage())
457 return; 460 return;
458 461
459 // Eagerly log the previous UMA even if we don't care about the current 462 committed_load_ = finished_nav.Pass();
460 // navigation.
461 committed_load_.reset();
462 463
463 const GURL& browser_url = web_contents()->GetLastCommittedURL(); 464 const GURL& browser_url = web_contents()->GetLastCommittedURL();
464 const std::string& mime_type = web_contents()->GetContentsMimeType(); 465 const std::string& mime_type = web_contents()->GetContentsMimeType();
465 DCHECK(!browser_url.is_empty()); 466 DCHECK(!browser_url.is_empty());
466 DCHECK(!mime_type.empty()); 467 DCHECK(!mime_type.empty());
467 if (!IsRelevantNavigation(navigation_handle, browser_url, mime_type)) 468 committed_load_->set_renderer_tracked(
468 return; 469 IsRelevantNavigation(navigation_handle, browser_url, mime_type));
469 470
470 committed_load_ = finished_nav.Pass();
471 committed_load_->Commit(navigation_handle); 471 committed_load_->Commit(navigation_handle);
472 } 472 }
473 473
474 void MetricsWebContentsObserver::DidRedirectNavigation( 474 void MetricsWebContentsObserver::DidRedirectNavigation(
475 content::NavigationHandle* navigation_handle) { 475 content::NavigationHandle* navigation_handle) {
476 if (!navigation_handle->IsInMainFrame()) 476 if (!navigation_handle->IsInMainFrame())
477 return; 477 return;
478 auto it = provisional_loads_.find(navigation_handle); 478 auto it = provisional_loads_.find(navigation_handle);
479 if (it == provisional_loads_.end()) 479 if (it == provisional_loads_.end())
480 return; 480 return;
(...skipping 23 matching lines...) Expand all
504 // we have one. 504 // we have one.
505 void MetricsWebContentsObserver::RenderProcessGone( 505 void MetricsWebContentsObserver::RenderProcessGone(
506 base::TerminationStatus status) { 506 base::TerminationStatus status) {
507 committed_load_.reset(); 507 committed_load_.reset();
508 } 508 }
509 509
510 void MetricsWebContentsObserver::OnTimingUpdated( 510 void MetricsWebContentsObserver::OnTimingUpdated(
511 content::RenderFrameHost* render_frame_host, 511 content::RenderFrameHost* render_frame_host,
512 const PageLoadTiming& timing) { 512 const PageLoadTiming& timing) {
513 bool error = false; 513 bool error = false;
514 if (!committed_load_) { 514 if (!committed_load_ || !committed_load_->renderer_tracked()) {
515 RecordInternalError(ERR_IPC_WITH_NO_COMMITTED_LOAD); 515 RecordInternalError(ERR_IPC_WITH_NO_RELEVANT_LOAD);
516 error = true; 516 error = true;
517 } 517 }
518 518
519 // We may receive notifications from frames that have been navigated away 519 // We may receive notifications from frames that have been navigated away
520 // from. We simply ignore them. 520 // from. We simply ignore them.
521 if (render_frame_host != web_contents()->GetMainFrame()) { 521 if (render_frame_host != web_contents()->GetMainFrame()) {
522 RecordInternalError(ERR_IPC_FROM_WRONG_FRAME); 522 RecordInternalError(ERR_IPC_FROM_WRONG_FRAME);
523 error = true; 523 error = true;
524 } 524 }
525 525
(...skipping 10 matching lines...) Expand all
536 536
537 if (!committed_load_->UpdateTiming(timing)) { 537 if (!committed_load_->UpdateTiming(timing)) {
538 // If the page load tracker cannot update its timing, something is wrong 538 // If the page load tracker cannot update its timing, something is wrong
539 // with the IPC (it's from another load, or it's invalid in some other way). 539 // with the IPC (it's from another load, or it's invalid in some other way).
540 // We expect this to be a rare occurrence. 540 // We expect this to be a rare occurrence.
541 RecordInternalError(ERR_BAD_TIMING_IPC); 541 RecordInternalError(ERR_BAD_TIMING_IPC);
542 } 542 }
543 } 543 }
544 544
545 } // namespace page_load_metrics 545 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698