OLD | NEW |
---|---|
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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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_EACH_OBSERVER(PageLoadMetricsObserver, observers_, | |
120 OnStart(navigation_handle)); | |
121 } | |
119 | 122 |
120 PageLoadTracker::~PageLoadTracker() { | 123 PageLoadTracker::~PageLoadTracker() { |
121 if (has_commit_) { | 124 if (has_commit_) { |
122 RecordTimingHistograms(); | 125 RecordTimingHistograms(); |
123 RecordRappor(); | 126 RecordRappor(); |
124 } | 127 } |
128 PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | |
129 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_, | |
130 OnComplete(timing_, info)); | |
131 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_, | |
132 OnPageLoadMetricsGoingAway()); | |
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_EACH_OBSERVER(PageLoadMetricsObserver, observers_, |
149 OnCommit(navigation_handle)); | 158 OnCommit(navigation_handle)); |
150 } | 159 } |
151 | 160 |
152 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { | 161 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { |
153 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, | 162 FOR_EACH_OBSERVER(PageLoadMetricsObserver, observers_, |
154 OnRedirect(navigation_handle)); | 163 OnRedirect(navigation_handle)); |
155 } | 164 } |
156 | 165 |
157 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing) { | 166 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing) { |
158 // Throw away IPCs that are not relevant to the current navigation. | 167 // Throw away IPCs that are not relevant to the current navigation. |
159 // Two timing structures cannot refer to the same navigation if they indicate | 168 // 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 | 169 // 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. | 170 // different start time from an earlier struct is considered invalid. |
162 bool valid_timing_descendent = | 171 bool valid_timing_descendent = |
163 timing_.navigation_start.is_null() || | 172 timing_.navigation_start.is_null() || |
164 timing_.navigation_start == new_timing.navigation_start; | 173 timing_.navigation_start == new_timing.navigation_start; |
165 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent) { | 174 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent) { |
166 timing_ = new_timing; | 175 timing_ = new_timing; |
167 return true; | 176 return true; |
168 } | 177 } |
169 return false; | 178 return false; |
170 } | 179 } |
171 | 180 |
172 bool PageLoadTracker::HasBackgrounded() { | 181 bool PageLoadTracker::HasBackgrounded() { |
173 return !started_in_foreground_ || !background_time_.is_null(); | 182 return !started_in_foreground_ || !background_time_.is_null(); |
174 } | 183 } |
175 | 184 |
185 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { | |
186 renderer_tracked_ = renderer_tracked; | |
187 } | |
188 | |
189 void PageLoadTracker::AddObserver(PageLoadMetricsObserver* observer) { | |
190 observers_.AddObserver(observer); | |
191 } | |
192 | |
193 void PageLoadTracker::RemoveObserver(PageLoadMetricsObserver* observer) { | |
194 observers_.RemoveObserver(observer); | |
195 } | |
196 | |
176 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { | 197 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { |
177 base::TimeDelta first_background_time; | 198 base::TimeDelta first_background_time; |
178 base::TimeDelta first_foreground_time; | 199 base::TimeDelta first_foreground_time; |
179 if (!background_time_.is_null() && started_in_foreground_) | 200 if (!background_time_.is_null() && started_in_foreground_) |
180 first_background_time = background_time_ - navigation_start_; | 201 first_background_time = background_time_ - navigation_start_; |
181 if (!foreground_time_.is_null() && !started_in_foreground_) | 202 if (!foreground_time_.is_null() && !started_in_foreground_) |
182 first_foreground_time = foreground_time_ - navigation_start_; | 203 first_foreground_time = foreground_time_ - navigation_start_; |
183 return PageLoadExtraInfo(first_background_time, first_foreground_time, | 204 return PageLoadExtraInfo(first_background_time, first_foreground_time, |
184 started_in_foreground_); | 205 started_in_foreground_, has_commit_); |
185 } | 206 } |
186 | 207 |
187 const GURL& PageLoadTracker::GetCommittedURL() { | 208 const GURL& PageLoadTracker::committed_url() { |
188 DCHECK(has_commit_); | 209 DCHECK(has_commit_); |
189 return url_; | 210 return url_; |
190 } | 211 } |
191 | 212 |
192 // Blink calculates navigation start using TimeTicks, but converts to epoch time | 213 // 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 | 214 // 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 | 215 // 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. | 216 // 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 | 217 // There may be slight inaccuracies due to inter-process timestamps, but |
197 // this solution is the best we have right now. | 218 // this solution is the best we have right now. |
198 // | 219 // |
199 // returns a TimeDelta which is | 220 // returns a TimeDelta which is |
200 // - Infinity if we were never backgrounded | 221 // - Infinity if we were never backgrounded |
201 // - null (TimeDelta()) if we started backgrounded | 222 // - null (TimeDelta()) if we started backgrounded |
202 // - elapsed time to first background if we started in the foreground and | 223 // - elapsed time to first background if we started in the foreground and |
203 // backgrounded. | 224 // backgrounded. |
204 base::TimeDelta PageLoadTracker::GetBackgroundDelta() { | 225 base::TimeDelta PageLoadTracker::GetBackgroundDelta() { |
205 if (started_in_foreground_) { | 226 if (started_in_foreground_) { |
206 return background_time_.is_null() ? base::TimeDelta::Max() | 227 return background_time_.is_null() ? base::TimeDelta::Max() |
207 : background_time_ - navigation_start_; | 228 : background_time_ - navigation_start_; |
208 } | 229 } |
209 return base::TimeDelta(); | 230 return base::TimeDelta(); |
210 } | 231 } |
211 | 232 |
212 void PageLoadTracker::RecordTimingHistograms() { | 233 void PageLoadTracker::RecordTimingHistograms() { |
213 DCHECK(has_commit_); | 234 DCHECK(has_commit_); |
214 if (timing_.IsEmpty()) { | 235 if (timing_.IsEmpty() && renderer_tracked()) { |
215 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 236 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
216 return; | 237 return; |
217 } | 238 } |
218 | 239 |
219 PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 240 if (!renderer_tracked()) |
220 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, | 241 return; |
Randy Smith (Not in Mondays)
2015/12/01 22:34:03
nit: Why not push this before the previous clause
Charlie Harrison
2015/12/01 22:54:24
Done.
| |
221 OnComplete(timing_, info)); | |
222 | 242 |
223 base::TimeDelta background_delta = GetBackgroundDelta(); | 243 base::TimeDelta background_delta = GetBackgroundDelta(); |
224 | 244 |
225 if (!timing_.dom_content_loaded_event_start.is_zero()) { | 245 if (!timing_.dom_content_loaded_event_start.is_zero()) { |
226 if (timing_.dom_content_loaded_event_start < background_delta) { | 246 if (timing_.dom_content_loaded_event_start < background_delta) { |
227 PAGE_LOAD_HISTOGRAM(kHistogramDomContentLoaded, | 247 PAGE_LOAD_HISTOGRAM(kHistogramDomContentLoaded, |
228 timing_.dom_content_loaded_event_start); | 248 timing_.dom_content_loaded_event_start); |
229 } else { | 249 } else { |
230 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramDomContentLoaded, | 250 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramDomContentLoaded, |
231 timing_.dom_content_loaded_event_start); | 251 timing_.dom_content_loaded_event_start); |
232 } | 252 } |
233 } | 253 } |
234 if (!timing_.load_event_start.is_zero()) { | 254 if (!timing_.load_event_start.is_zero()) { |
235 if (timing_.load_event_start < background_delta) { | 255 if (timing_.load_event_start < background_delta) { |
236 PAGE_LOAD_HISTOGRAM(kHistogramLoad, timing_.load_event_start); | 256 PAGE_LOAD_HISTOGRAM(kHistogramLoad, timing_.load_event_start); |
237 } else { | 257 } else { |
238 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramLoad, timing_.load_event_start); | 258 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramLoad, timing_.load_event_start); |
239 } | 259 } |
240 } | 260 } |
241 if (timing_.first_layout.is_zero()) { | 261 if (timing_.first_layout.is_zero()) { |
242 RecordCommittedEvent(COMMITTED_LOAD_FAILED_BEFORE_FIRST_LAYOUT, | 262 RecordCommittedEvent(RELEVANT_LOAD_FAILED_BEFORE_FIRST_LAYOUT, |
243 HasBackgrounded()); | 263 HasBackgrounded()); |
244 } else { | 264 } else { |
245 if (timing_.first_layout < background_delta) { | 265 if (timing_.first_layout < background_delta) { |
246 PAGE_LOAD_HISTOGRAM(kHistogramFirstLayout, timing_.first_layout); | 266 PAGE_LOAD_HISTOGRAM(kHistogramFirstLayout, timing_.first_layout); |
247 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, false); | 267 RecordCommittedEvent(RELEVANT_LOAD_SUCCESSFUL_FIRST_LAYOUT, false); |
248 } else { | 268 } else { |
249 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstLayout, | 269 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstLayout, |
250 timing_.first_layout); | 270 timing_.first_layout); |
251 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, true); | 271 RecordCommittedEvent(RELEVANT_LOAD_SUCCESSFUL_FIRST_LAYOUT, true); |
252 } | 272 } |
253 } | 273 } |
254 if (!timing_.first_paint.is_zero()) { | 274 if (!timing_.first_paint.is_zero()) { |
255 if (timing_.first_paint < background_delta) { | 275 if (timing_.first_paint < background_delta) { |
256 PAGE_LOAD_HISTOGRAM(kHistogramFirstPaint, timing_.first_paint); | 276 PAGE_LOAD_HISTOGRAM(kHistogramFirstPaint, timing_.first_paint); |
257 } else { | 277 } else { |
258 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstPaint, timing_.first_paint); | 278 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstPaint, timing_.first_paint); |
259 } | 279 } |
260 } | 280 } |
261 if (!timing_.first_text_paint.is_zero()) { | 281 if (!timing_.first_text_paint.is_zero()) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 PROVISIONAL_LOAD_LAST_ENTRY); | 330 PROVISIONAL_LOAD_LAST_ENTRY); |
311 } else { | 331 } else { |
312 UMA_HISTOGRAM_ENUMERATION(kProvisionalEvents, event, | 332 UMA_HISTOGRAM_ENUMERATION(kProvisionalEvents, event, |
313 PROVISIONAL_LOAD_LAST_ENTRY); | 333 PROVISIONAL_LOAD_LAST_ENTRY); |
314 } | 334 } |
315 } | 335 } |
316 | 336 |
317 // RecordCommittedEvent needs a backgrounded input because we need to special | 337 // RecordCommittedEvent needs a backgrounded input because we need to special |
318 // case a few events that need either precise timing measurements, or different | 338 // case a few events that need either precise timing measurements, or different |
319 // logic than simply "Did I background before logging this event?" | 339 // logic than simply "Did I background before logging this event?" |
320 void PageLoadTracker::RecordCommittedEvent(CommittedLoadEvent event, | 340 void PageLoadTracker::RecordCommittedEvent(CommittedRelevantLoadEvent event, |
321 bool backgrounded) { | 341 bool backgrounded) { |
322 if (backgrounded) { | 342 if (backgrounded) { |
323 UMA_HISTOGRAM_ENUMERATION(kBackgroundCommittedEvents, event, | 343 UMA_HISTOGRAM_ENUMERATION(kBackgroundCommittedEvents, event, |
324 COMMITTED_LOAD_LAST_ENTRY); | 344 RELEVANT_LOAD_LAST_ENTRY); |
325 } else { | 345 } else { |
326 UMA_HISTOGRAM_ENUMERATION(kCommittedEvents, event, | 346 UMA_HISTOGRAM_ENUMERATION(kCommittedEvents, event, |
327 COMMITTED_LOAD_LAST_ENTRY); | 347 RELEVANT_LOAD_LAST_ENTRY); |
328 } | 348 } |
329 } | 349 } |
330 | 350 |
331 void PageLoadTracker::RecordRappor() { | 351 void PageLoadTracker::RecordRappor() { |
332 DCHECK(!GetCommittedURL().is_empty()); | 352 DCHECK(!committed_url().is_empty()); |
333 rappor::RapporService* rappor_service = | 353 rappor::RapporService* rappor_service = |
334 embedder_interface_->GetRapporService(); | 354 embedder_interface_->GetRapporService(); |
335 if (!rappor_service) | 355 if (!rappor_service) |
336 return; | 356 return; |
337 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); | 357 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); |
338 // Log the eTLD+1 of sites that show poor loading performance. | 358 // Log the eTLD+1 of sites that show poor loading performance. |
339 if (!first_contentful_paint.is_zero() && | 359 if (!first_contentful_paint.is_zero() && |
340 first_contentful_paint < GetBackgroundDelta()) { | 360 first_contentful_paint < GetBackgroundDelta()) { |
341 scoped_ptr<rappor::Sample> sample = | 361 scoped_ptr<rappor::Sample> sample = |
342 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); | 362 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); |
343 sample->SetStringField("Domain", rappor::GetDomainAndRegistrySampleFromGURL( | 363 sample->SetStringField("Domain", rappor::GetDomainAndRegistrySampleFromGURL( |
344 GetCommittedURL())); | 364 committed_url())); |
345 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint); | 365 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint); |
346 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index, | 366 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index, |
347 kNumRapporHistogramBuckets); | 367 kNumRapporHistogramBuckets); |
348 // The IsSlow flag is just a one bit boolean if the first layout was > 10s. | 368 // The IsSlow flag is just a one bit boolean if the first layout was > 10s. |
349 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10, | 369 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10, |
350 1); | 370 1); |
351 rappor_service->RecordSampleObj(kRapporMetricsNameCoarseTiming, | 371 rappor_service->RecordSampleObj(kRapporMetricsNameCoarseTiming, |
352 sample.Pass()); | 372 sample.Pass()); |
353 } | 373 } |
354 } | 374 } |
(...skipping 17 matching lines...) Expand all Loading... | |
372 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass()); | 392 new MetricsWebContentsObserver(web_contents, embedder_interface.Pass()); |
373 web_contents->SetUserData(UserDataKey(), metrics); | 393 web_contents->SetUserData(UserDataKey(), metrics); |
374 } | 394 } |
375 return metrics; | 395 return metrics; |
376 } | 396 } |
377 | 397 |
378 MetricsWebContentsObserver::~MetricsWebContentsObserver() { | 398 MetricsWebContentsObserver::~MetricsWebContentsObserver() { |
379 // Reset PageLoadTrackers so observers get final notifications. | 399 // Reset PageLoadTrackers so observers get final notifications. |
380 committed_load_.reset(); | 400 committed_load_.reset(); |
381 provisional_loads_.clear(); | 401 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 } | 402 } |
395 | 403 |
396 bool MetricsWebContentsObserver::OnMessageReceived( | 404 bool MetricsWebContentsObserver::OnMessageReceived( |
397 const IPC::Message& message, | 405 const IPC::Message& message, |
398 content::RenderFrameHost* render_frame_host) { | 406 content::RenderFrameHost* render_frame_host) { |
399 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 407 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
400 bool handled = true; | 408 bool handled = true; |
401 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, | 409 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, |
402 render_frame_host) | 410 render_frame_host) |
403 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) | 411 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) |
404 IPC_MESSAGE_UNHANDLED(handled = false) | 412 IPC_MESSAGE_UNHANDLED(handled = false) |
405 IPC_END_MESSAGE_MAP() | 413 IPC_END_MESSAGE_MAP() |
406 return handled; | 414 return handled; |
407 } | 415 } |
408 | 416 |
409 void MetricsWebContentsObserver::DidStartNavigation( | 417 void MetricsWebContentsObserver::DidStartNavigation( |
410 content::NavigationHandle* navigation_handle) { | 418 content::NavigationHandle* navigation_handle) { |
411 if (!navigation_handle->IsInMainFrame()) | 419 if (!navigation_handle->IsInMainFrame()) |
412 return; | 420 return; |
413 if (embedder_interface_->IsPrerendering(web_contents())) | 421 if (embedder_interface_->IsPrerendering(web_contents())) |
414 return; | 422 return; |
415 // We can have two provisional loads in some cases. E.g. a same-site | 423 // We can have two provisional loads in some cases. E.g. a same-site |
416 // navigation can have a concurrent cross-process navigation started | 424 // navigation can have a concurrent cross-process navigation started |
417 // from the omnibox. | 425 // from the omnibox. |
418 DCHECK_GT(2ul, provisional_loads_.size()); | 426 DCHECK_GT(2ul, provisional_loads_.size()); |
419 // Passing raw pointers to observers_ and embedder_interface_ is safe because | 427 // Passing raw pointers to observers_ and embedder_interface_ is safe because |
420 // the MetricsWebContentsObserver owns them both list and they are torn down | 428 // the MetricsWebContentsObserver owns them both list and they are torn down |
421 // after the PageLoadTracker. | 429 // after the PageLoadTracker. |
422 provisional_loads_.insert(std::make_pair( | 430 provisional_loads_.insert(std::make_pair( |
423 navigation_handle, make_scoped_ptr(new PageLoadTracker( | 431 navigation_handle, |
424 in_foreground_, embedder_interface_.get(), | 432 make_scoped_ptr(new PageLoadTracker( |
425 navigation_handle, &observers_)))); | 433 in_foreground_, embedder_interface_.get(), navigation_handle)))); |
426 } | 434 } |
427 | 435 |
428 void MetricsWebContentsObserver::DidFinishNavigation( | 436 void MetricsWebContentsObserver::DidFinishNavigation( |
429 content::NavigationHandle* navigation_handle) { | 437 content::NavigationHandle* navigation_handle) { |
430 if (!navigation_handle->IsInMainFrame()) | 438 if (!navigation_handle->IsInMainFrame()) |
431 return; | 439 return; |
432 | 440 |
433 scoped_ptr<PageLoadTracker> finished_nav( | 441 scoped_ptr<PageLoadTracker> finished_nav( |
434 std::move(provisional_loads_[navigation_handle])); | 442 std::move(provisional_loads_[navigation_handle])); |
435 provisional_loads_.erase(navigation_handle); | 443 provisional_loads_.erase(navigation_handle); |
(...skipping 13 matching lines...) Expand all Loading... | |
449 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED | 457 : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED |
450 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT); | 458 : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT); |
451 return; | 459 return; |
452 } | 460 } |
453 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED); | 461 finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED); |
454 | 462 |
455 // Don't treat a same-page nav as a new page load. | 463 // Don't treat a same-page nav as a new page load. |
456 if (navigation_handle->IsSamePage()) | 464 if (navigation_handle->IsSamePage()) |
457 return; | 465 return; |
458 | 466 |
459 // Eagerly log the previous UMA even if we don't care about the current | 467 committed_load_ = finished_nav.Pass(); |
460 // navigation. | |
461 committed_load_.reset(); | |
462 | 468 |
463 const GURL& browser_url = web_contents()->GetLastCommittedURL(); | 469 const GURL& browser_url = web_contents()->GetLastCommittedURL(); |
464 const std::string& mime_type = web_contents()->GetContentsMimeType(); | 470 const std::string& mime_type = web_contents()->GetContentsMimeType(); |
465 DCHECK(!browser_url.is_empty()); | 471 DCHECK(!browser_url.is_empty()); |
466 DCHECK(!mime_type.empty()); | 472 DCHECK(!mime_type.empty()); |
467 if (!IsRelevantNavigation(navigation_handle, browser_url, mime_type)) | 473 committed_load_->set_renderer_tracked( |
468 return; | 474 IsRelevantNavigation(navigation_handle, browser_url, mime_type)); |
469 | 475 |
470 committed_load_ = finished_nav.Pass(); | |
471 committed_load_->Commit(navigation_handle); | 476 committed_load_->Commit(navigation_handle); |
472 } | 477 } |
473 | 478 |
474 void MetricsWebContentsObserver::DidRedirectNavigation( | 479 void MetricsWebContentsObserver::DidRedirectNavigation( |
475 content::NavigationHandle* navigation_handle) { | 480 content::NavigationHandle* navigation_handle) { |
476 if (!navigation_handle->IsInMainFrame()) | 481 if (!navigation_handle->IsInMainFrame()) |
477 return; | 482 return; |
478 auto it = provisional_loads_.find(navigation_handle); | 483 auto it = provisional_loads_.find(navigation_handle); |
479 if (it == provisional_loads_.end()) | 484 if (it == provisional_loads_.end()) |
480 return; | 485 return; |
(...skipping 23 matching lines...) Expand all Loading... | |
504 // we have one. | 509 // we have one. |
505 void MetricsWebContentsObserver::RenderProcessGone( | 510 void MetricsWebContentsObserver::RenderProcessGone( |
506 base::TerminationStatus status) { | 511 base::TerminationStatus status) { |
507 committed_load_.reset(); | 512 committed_load_.reset(); |
508 } | 513 } |
509 | 514 |
510 void MetricsWebContentsObserver::OnTimingUpdated( | 515 void MetricsWebContentsObserver::OnTimingUpdated( |
511 content::RenderFrameHost* render_frame_host, | 516 content::RenderFrameHost* render_frame_host, |
512 const PageLoadTiming& timing) { | 517 const PageLoadTiming& timing) { |
513 bool error = false; | 518 bool error = false; |
514 if (!committed_load_) { | 519 if (!committed_load_ || !committed_load_->renderer_tracked()) { |
515 RecordInternalError(ERR_IPC_WITH_NO_COMMITTED_LOAD); | 520 RecordInternalError(ERR_IPC_WITH_NO_RELEVANT_LOAD); |
516 error = true; | 521 error = true; |
517 } | 522 } |
518 | 523 |
519 // We may receive notifications from frames that have been navigated away | 524 // We may receive notifications from frames that have been navigated away |
520 // from. We simply ignore them. | 525 // from. We simply ignore them. |
521 if (render_frame_host != web_contents()->GetMainFrame()) { | 526 if (render_frame_host != web_contents()->GetMainFrame()) { |
522 RecordInternalError(ERR_IPC_FROM_WRONG_FRAME); | 527 RecordInternalError(ERR_IPC_FROM_WRONG_FRAME); |
523 error = true; | 528 error = true; |
524 } | 529 } |
525 | 530 |
(...skipping 10 matching lines...) Expand all Loading... | |
536 | 541 |
537 if (!committed_load_->UpdateTiming(timing)) { | 542 if (!committed_load_->UpdateTiming(timing)) { |
538 // If the page load tracker cannot update its timing, something is wrong | 543 // 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). | 544 // 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. | 545 // We expect this to be a rare occurrence. |
541 RecordInternalError(ERR_BAD_TIMING_IPC); | 546 RecordInternalError(ERR_BAD_TIMING_IPC); |
542 } | 547 } |
543 } | 548 } |
544 | 549 |
545 } // namespace page_load_metrics | 550 } // namespace page_load_metrics |
OLD | NEW |