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

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

Issue 1449253002: [do not review][page_load_metrics] User Initiated Abort Tracking (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@plm_navigation_start
Patch Set: Created 5 years, 1 month 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 "components/page_load_metrics/browser/page_load_metrics_macros.h" 10 #include "components/page_load_metrics/browser/page_load_metrics_macros.h"
11 #include "components/page_load_metrics/common/page_load_metrics_messages.h" 11 #include "components/page_load_metrics/common/page_load_metrics_messages.h"
12 #include "components/page_load_metrics/common/page_load_timing.h" 12 #include "components/page_load_metrics/common/page_load_timing.h"
13 #include "components/rappor/rappor_service.h" 13 #include "components/rappor/rappor_service.h"
14 #include "components/rappor/rappor_utils.h" 14 #include "components/rappor/rappor_utils.h"
15 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/navigation_details.h" 16 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/navigation_handle.h" 17 #include "content/public/browser/navigation_handle.h"
18 #include "content/public/browser/render_frame_host.h" 18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_observer.h" 20 #include "content/public/browser/web_contents_observer.h"
21 #include "content/public/browser/web_contents_user_data.h" 21 #include "content/public/browser/web_contents_user_data.h"
22 #include "ipc/ipc_message.h" 22 #include "ipc/ipc_message.h"
23 #include "ipc/ipc_message_macros.h" 23 #include "ipc/ipc_message_macros.h"
24 #include "ui/base/page_transition_types.h"
24 25
25 DEFINE_WEB_CONTENTS_USER_DATA_KEY( 26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
26 page_load_metrics::MetricsWebContentsObserver); 27 page_load_metrics::MetricsWebContentsObserver);
27 28
28 namespace page_load_metrics { 29 namespace page_load_metrics {
29 30
30 namespace { 31 namespace {
31 32
32 // 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
33 // 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
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 return false; 74 return false;
74 } 75 }
75 76
76 return true; 77 return true;
77 } 78 }
78 79
79 void RecordInternalError(InternalErrorLoadEvent event) { 80 void RecordInternalError(InternalErrorLoadEvent event) {
80 UMA_HISTOGRAM_ENUMERATION(kErrorEvents, event, ERR_LAST_ENTRY); 81 UMA_HISTOGRAM_ENUMERATION(kErrorEvents, event, ERR_LAST_ENTRY);
81 } 82 }
82 83
84 UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) {
85 if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD))
86 return ABORT_RELOAD;
87 else if (transition & ui::PAGE_TRANSITION_FORWARD_BACK)
88 return ABORT_FORWARD_BACK;
89 else
90 return ABORT_NEW_NAVIGATION;
91 }
92
83 base::TimeDelta GetFirstContentfulPaint(const PageLoadTiming& timing) { 93 base::TimeDelta GetFirstContentfulPaint(const PageLoadTiming& timing) {
84 if (timing.first_text_paint.is_zero()) 94 if (timing.first_text_paint.is_zero())
85 return timing.first_image_paint; 95 return timing.first_image_paint;
86 if (timing.first_image_paint.is_zero()) 96 if (timing.first_image_paint.is_zero())
87 return timing.first_text_paint; 97 return timing.first_text_paint;
88 return std::min(timing.first_text_paint, timing.first_image_paint); 98 return std::min(timing.first_text_paint, timing.first_image_paint);
89 } 99 }
90 100
91 // The number of buckets in the bitfield histogram. These buckets are described 101 // The number of buckets in the bitfield histogram. These buckets are described
92 // in rappor.xml in PageLoad.CoarseTiming.NavigationToFirstContentfulPaint. 102 // in rappor.xml in PageLoad.CoarseTiming.NavigationToFirstContentfulPaint.
(...skipping 20 matching lines...) Expand all
113 123
114 } // namespace 124 } // namespace
115 125
116 PageLoadTracker::PageLoadTracker( 126 PageLoadTracker::PageLoadTracker(
117 bool in_foreground, 127 bool in_foreground,
118 PageLoadMetricsEmbedderInterface* embedder_interface, 128 PageLoadMetricsEmbedderInterface* embedder_interface,
119 content::NavigationHandle* navigation_handle, 129 content::NavigationHandle* navigation_handle,
120 base::ObserverList<PageLoadMetricsObserver, true>* observers) 130 base::ObserverList<PageLoadMetricsObserver, true>* observers)
121 : has_commit_(false), 131 : has_commit_(false),
122 navigation_start_(navigation_handle->navigation_start()), 132 navigation_start_(navigation_handle->navigation_start()),
133 abort_type_(ABORT_NULL),
123 started_in_foreground_(in_foreground), 134 started_in_foreground_(in_foreground),
124 embedder_interface_(embedder_interface), 135 embedder_interface_(embedder_interface),
125 observers_(observers) {} 136 observers_(observers) {}
126 137
127 PageLoadTracker::~PageLoadTracker() { 138 PageLoadTracker::~PageLoadTracker() {
128 if (has_commit_) { 139 if (has_commit_) {
129 RecordTimingHistograms(); 140 RecordTimingHistograms();
130 RecordRappor(); 141 RecordRappor();
131 } 142 }
143 RecordAbortTimingHistograms();
132 } 144 }
133 145
134 void PageLoadTracker::WebContentsHidden() { 146 void PageLoadTracker::WebContentsHidden() {
135 // Only log the first time we background in a given page load. 147 // Only log the first time we background in a given page load.
136 if (started_in_foreground_ && background_time_.is_null()) 148 if (started_in_foreground_ && background_time_.is_null())
137 background_time_ = base::TimeTicks::Now(); 149 background_time_ = base::TimeTicks::Now();
138 } 150 }
139 151
140 void PageLoadTracker::WebContentsShown() { 152 void PageLoadTracker::WebContentsShown() {
141 // Only log the first time we foreground in a given page load. 153 // Only log the first time we foreground in a given page load.
(...skipping 29 matching lines...) Expand all
171 return false; 183 return false;
172 } 184 }
173 185
174 bool PageLoadTracker::HasBackgrounded() { 186 bool PageLoadTracker::HasBackgrounded() {
175 return !started_in_foreground_ || !background_time_.is_null(); 187 return !started_in_foreground_ || !background_time_.is_null();
176 } 188 }
177 189
178 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { 190 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() {
179 base::TimeDelta first_background_time; 191 base::TimeDelta first_background_time;
180 base::TimeDelta first_foreground_time; 192 base::TimeDelta first_foreground_time;
181 if (!background_time_.is_null() && started_in_foreground_) 193 if (!background_time_.is_null())
182 first_background_time = background_time_ - navigation_start_; 194 first_background_time = background_time_ - navigation_start_;
183 if (!foreground_time_.is_null() && !started_in_foreground_) 195 if (!foreground_time_.is_null())
184 first_foreground_time = foreground_time_ - navigation_start_; 196 first_foreground_time = foreground_time_ - navigation_start_;
185 return PageLoadExtraInfo(first_background_time, first_foreground_time, 197 return PageLoadExtraInfo(first_background_time, first_foreground_time,
186 started_in_foreground_); 198 started_in_foreground_);
187 } 199 }
188 200
201 // We consider the first abort passed here as the true abort, unless it is
202 // ABORT_OTHER, so call this with decreasing specificity.
203 void PageLoadTracker::NotifyAbort(UserAbortType abort_type,
204 const base::TimeTicks& timestamp) {
205 DCHECK(abort_type != ABORT_NULL);
206 if (abort_type_ == ABORT_NULL) {
207 abort_type_ = abort_type;
208 abort_time_ = timestamp;
209 }
210
211 // If we got a better signal than ABORT_OTHER since the last navigation, treat
212 // it as the cause of the abort (Some ABORT_OTHER signals occur before the
213 // true signal). Note that this only occurs for provisional loads. While this
214 // heuristic is coarse, it works better and is simpler than other feasible
215 // methods.
216 if (abort_type_ == ABORT_OTHER && abort_type != ABORT_OTHER) {
217 abort_type_ = abort_type;
218 abort_time_ = std::min(abort_time_, timestamp);
219 }
220 }
221
222 void PageLoadTracker::RecordAbortTimingHistograms() {
223 // Log the background "abort" if we backgrounded a foregrounded page before
224 // its first paint. This is a slightly different notion of abort (we can still
225 // get to the first paint later), but it is still worthwhile measure.
226 if (!background_time_.is_null() &&
227 (timing_.first_paint.is_zero() ||
228 GetBackgroundDelta() < timing_.first_paint)) {
229 if (has_commit_) {
230 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortBackground,
Bryan McQuade 2015/11/17 13:33:08 this does feel like a user-initiated abort, but i
Charlie Harrison 2015/11/17 16:11:54 I could go either way. I only put it here because
231 background_time_ - navigation_start_);
232 } else {
233 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortBackground,
234 background_time_ - navigation_start_);
235 }
236 }
237 if (abort_type_ == ABORT_NULL)
238 return;
239 DCHECK(!abort_time_.is_null());
240
241 // Loads are not considered aborts if they painted before the abort event.
Bryan McQuade 2015/11/17 13:33:08 i'm inclined to either ignore aborts when a tab is
Charlie Harrison 2015/11/17 16:11:54 I'm inclined to ignore them for now and add later
242 base::TimeDelta time_to_abort = abort_time_ - navigation_start_;
243 if (!timing_.first_paint.is_zero() && timing_.first_paint < time_to_abort)
244 return;
245 if (has_commit_) {
246 if (abort_type_ == ABORT_RELOAD) {
247 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortReload, time_to_abort);
248 } else if (abort_type_ == ABORT_FORWARD_BACK) {
249 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortForwardBack, time_to_abort);
250 } else if (abort_type_ == ABORT_NEW_NAVIGATION) {
251 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortNewNavigation, time_to_abort);
252 } else if (abort_type_ == ABORT_STOP) {
253 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortStop, time_to_abort);
254 } else if (abort_type_ == ABORT_CLOSE) {
255 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortClose, time_to_abort);
256 } else if (abort_type_ == ABORT_OTHER) {
257 PAGE_LOAD_HISTOGRAM(kHistogramCommittedAbortOther, time_to_abort);
258 }
259 } else {
260 if (abort_type_ == ABORT_RELOAD) {
261 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortReload, time_to_abort);
262 } else if (abort_type_ == ABORT_FORWARD_BACK) {
263 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortForwardBack, time_to_abort);
264 } else if (abort_type_ == ABORT_NEW_NAVIGATION) {
265 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortNewNavigation,
266 time_to_abort);
267 } else if (abort_type_ == ABORT_STOP) {
268 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortStop, time_to_abort);
269 } else if (abort_type_ == ABORT_CLOSE) {
270 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortClose, time_to_abort);
271 } else if (abort_type_ == ABORT_OTHER) {
272 PAGE_LOAD_HISTOGRAM(kHistogramProvisionalAbortOther, time_to_abort);
273 }
274 }
275 }
276
189 const GURL& PageLoadTracker::GetCommittedURL() { 277 const GURL& PageLoadTracker::GetCommittedURL() {
190 DCHECK(has_commit_); 278 DCHECK(has_commit_);
191 return url_; 279 return url_;
192 } 280 }
193 281
194 // Blink calculates navigation start using TimeTicks, but converts to epoch time 282 // Blink calculates navigation start using TimeTicks, but converts to epoch time
195 // in its public API. Thus, to compare time values to navigation start, we 283 // in its public API. Thus, to compare time values to navigation start, we
196 // calculate the current time since the epoch using TimeTicks, and convert to 284 // calculate the current time since the epoch using TimeTicks, and convert to
197 // Time. This method is similar to how blink converts TimeTicks to epoch time. 285 // Time. This method is similar to how blink converts TimeTicks to epoch time.
198 // There may be slight inaccuracies due to inter-process timestamps, but 286 // There may be slight inaccuracies due to inter-process timestamps, but
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 if (!metrics) { 451 if (!metrics) {
364 metrics = 452 metrics =
365 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass()); 453 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass());
366 web_contents->SetUserData(UserDataKey(), metrics); 454 web_contents->SetUserData(UserDataKey(), metrics);
367 } 455 }
368 return metrics; 456 return metrics;
369 } 457 }
370 458
371 MetricsWebContentsObserver::~MetricsWebContentsObserver() { 459 MetricsWebContentsObserver::~MetricsWebContentsObserver() {
372 // Reset PageLoadTrackers so observers get final notifications. 460 // Reset PageLoadTrackers so observers get final notifications.
461 NotifyAbortAllLoads(ABORT_CLOSE);
373 committed_load_.reset(); 462 committed_load_.reset();
374 provisional_loads_.clear(); 463 provisional_loads_.clear();
464 aborted_provisional_loads_.clear();
375 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_, 465 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_,
376 OnPageLoadMetricsGoingAway()); 466 OnPageLoadMetricsGoingAway());
377 } 467 }
378 468
379 void MetricsWebContentsObserver::AddObserver( 469 void MetricsWebContentsObserver::AddObserver(
380 PageLoadMetricsObserver* observer) { 470 PageLoadMetricsObserver* observer) {
381 observers_.AddObserver(observer); 471 observers_.AddObserver(observer);
382 } 472 }
383 473
384 void MetricsWebContentsObserver::RemoveObserver( 474 void MetricsWebContentsObserver::RemoveObserver(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 scoped_ptr<PageLoadTracker> finished_nav( 516 scoped_ptr<PageLoadTracker> finished_nav(
427 provisional_loads_.take_and_erase(navigation_handle)); 517 provisional_loads_.take_and_erase(navigation_handle));
428 // There's a chance a navigation could have started before we were added to a 518 // There's a chance a navigation could have started before we were added to a
429 // tab. Bail out early if this is the case. 519 // tab. Bail out early if this is the case.
430 if (!finished_nav) 520 if (!finished_nav)
431 return; 521 return;
432 522
433 // Handle a pre-commit error here. Navigations that result in an error page 523 // Handle a pre-commit error here. Navigations that result in an error page
434 // will be ignored. Note that downloads/204s will result in HasCommitted() 524 // will be ignored. Note that downloads/204s will result in HasCommitted()
435 // returning false. 525 // returning false.
526 // TODO(csharrison): Track changes to NavigationHandle for signals when this
527 // is the case (HTTP response headers).
436 if (!navigation_handle->HasCommitted()) { 528 if (!navigation_handle->HasCommitted()) {
437 net::Error error = navigation_handle->GetNetErrorCode(); 529 net::Error error = navigation_handle->GetNetErrorCode();
438 finished_nav->RecordProvisionalEvent( 530 ProvisionalLoadEvent event = error == net::OK ? PROVISIONAL_LOAD_STOPPED
439 error == net::OK ? PROVISIONAL_LOAD_STOPPED
440 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED 531 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED
Bryan McQuade 2015/11/17 13:33:08 IIRC downloads/204s report ERR_ABORTED, so we'll e
Charlie Harrison 2015/11/17 16:11:54 Let's see. It's possible clamy@ will land her chan
441 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT); 532 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT;
533 finished_nav->RecordProvisionalEvent(event);
534 if (event != PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT) {
535 finished_nav->NotifyAbort(ABORT_OTHER, base::TimeTicks::Now());
536 aborted_provisional_loads_.push_back(finished_nav.Pass());
Bryan McQuade 2015/11/17 13:33:08 the aborted_provisional_loads_ member makes me a b
537 }
442 return; 538 return;
443 } 539 }
444 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED); 540 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED);
Bryan McQuade 2015/11/17 13:33:08 just noticing now - unrelated to this change - sho
Charlie Harrison 2015/11/17 16:11:54 This was intentional. If we want we can break up t
445 541
446 // Don't treat a same-page nav as a new page load. 542 // Don't treat a same-page nav as a new page load.
447 if (navigation_handle->IsSamePage()) 543 if (navigation_handle->IsSamePage())
448 return; 544 return;
449 545
546 // Notify other loads that they may have been aborted by this committed load
547 NotifyAbortAllLoadsWithTimestamp(
548 AbortTypeForPageTransition(navigation_handle->GetPageTransition()),
549 navigation_handle->navigation_start());
550
450 // Eagerly log the previous UMA even if we don't care about the current 551 // Eagerly log the previous UMA even if we don't care about the current
451 // navigation. 552 // navigation.
452 committed_load_.reset(); 553 committed_load_.reset();
453 554
454 const GURL& browser_url = web_contents()->GetLastCommittedURL(); 555 const GURL& browser_url = web_contents()->GetLastCommittedURL();
455 const std::string& mime_type = web_contents()->GetContentsMimeType(); 556 const std::string& mime_type = web_contents()->GetContentsMimeType();
456 DCHECK(!browser_url.is_empty()); 557 DCHECK(!browser_url.is_empty());
457 DCHECK(!mime_type.empty()); 558 DCHECK(!mime_type.empty());
458 if (!IsRelevantNavigation(navigation_handle, browser_url, mime_type)) 559 if (!IsRelevantNavigation(navigation_handle, browser_url, mime_type))
459 return; 560 return;
460 561
461 committed_load_ = finished_nav.Pass(); 562 committed_load_ = finished_nav.Pass();
462 committed_load_->Commit(navigation_handle); 563 committed_load_->Commit(navigation_handle);
564 aborted_provisional_loads_.clear();
Bryan McQuade 2015/11/17 13:33:08 should we clear aborted_provisional_loads_ even if
Charlie Harrison 2015/11/17 16:11:54 Yupp good idea. Done.
565 }
566
567 void MetricsWebContentsObserver::NavigationStopped() {
568 NotifyAbortAllLoads(ABORT_STOP);
463 } 569 }
464 570
465 void MetricsWebContentsObserver::WasShown() { 571 void MetricsWebContentsObserver::WasShown() {
466 in_foreground_ = true; 572 in_foreground_ = true;
467 if (committed_load_) 573 if (committed_load_)
468 committed_load_->WebContentsShown(); 574 committed_load_->WebContentsShown();
469 for (const auto& kv : provisional_loads_) { 575 for (const auto& kv : provisional_loads_) {
470 kv.second->WebContentsShown(); 576 kv.second->WebContentsShown();
471 } 577 }
472 } 578 }
473 579
474 void MetricsWebContentsObserver::WasHidden() { 580 void MetricsWebContentsObserver::WasHidden() {
475 in_foreground_ = false; 581 in_foreground_ = false;
476 if (committed_load_) 582 if (committed_load_)
477 committed_load_->WebContentsHidden(); 583 committed_load_->WebContentsHidden();
478 for (const auto& kv : provisional_loads_) { 584 for (const auto& kv : provisional_loads_) {
479 kv.second->WebContentsHidden(); 585 kv.second->WebContentsHidden();
480 } 586 }
481 } 587 }
482 588
483 // This will occur when the process for the main RenderFrameHost exits, either 589 // This will occur when the process for the main RenderFrameHost exits, either
484 // normally or from a crash. We eagerly log data from the last committed load if 590 // normally or from a crash. We eagerly log data from the last committed load if
485 // we have one. 591 // we have one.
486 void MetricsWebContentsObserver::RenderProcessGone( 592 void MetricsWebContentsObserver::RenderProcessGone(
487 base::TerminationStatus status) { 593 base::TerminationStatus status) {
594 NotifyAbortAllLoads(ABORT_CLOSE);
488 committed_load_.reset(); 595 committed_load_.reset();
596 provisional_loads_.clear();
597 aborted_provisional_loads_.clear();
598 }
599
600 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) {
601 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now());
602 }
603
604 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp(
605 UserAbortType abort_type, const base::TimeTicks& timestamp) {
606 if (committed_load_)
607 committed_load_->NotifyAbort(abort_type, timestamp);
608 for (const auto& kv : provisional_loads_) {
609 kv.second->NotifyAbort(abort_type, timestamp);
610 }
611 for (const auto& plt : aborted_provisional_loads_) {
612 plt->NotifyAbort(abort_type, timestamp);
613 }
489 } 614 }
490 615
491 void MetricsWebContentsObserver::OnTimingUpdated( 616 void MetricsWebContentsObserver::OnTimingUpdated(
492 content::RenderFrameHost* render_frame_host, 617 content::RenderFrameHost* render_frame_host,
493 const PageLoadTiming& timing) { 618 const PageLoadTiming& timing) {
494 bool error = false; 619 bool error = false;
495 if (!committed_load_) { 620 if (!committed_load_) {
496 RecordInternalError(ERR_IPC_WITH_NO_COMMITTED_LOAD); 621 RecordInternalError(ERR_IPC_WITH_NO_COMMITTED_LOAD);
497 error = true; 622 error = true;
498 } 623 }
(...skipping 18 matching lines...) Expand all
517 642
518 if (!committed_load_->UpdateTiming(timing)) { 643 if (!committed_load_->UpdateTiming(timing)) {
519 // If the page load tracker cannot update its timing, something is wrong 644 // If the page load tracker cannot update its timing, something is wrong
520 // with the IPC (it's from another load, or it's invalid in some other way). 645 // with the IPC (it's from another load, or it's invalid in some other way).
521 // We expect this to be a rare occurrence. 646 // We expect this to be a rare occurrence.
522 RecordInternalError(ERR_BAD_TIMING_IPC); 647 RecordInternalError(ERR_BAD_TIMING_IPC);
523 } 648 }
524 } 649 }
525 650
526 } // namespace page_load_metrics 651 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698