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 <algorithm> | 7 #include <algorithm> |
8 #include <ostream> | |
8 #include <string> | 9 #include <string> |
9 #include <utility> | 10 #include <utility> |
10 | 11 |
11 #include "base/location.h" | 12 #include "base/location.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
14 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
15 #include "base/metrics/user_metrics.h" | 16 #include "base/metrics/user_metrics.h" |
16 #include "components/page_load_metrics/browser/page_load_metrics_util.h" | 17 #include "components/page_load_metrics/browser/page_load_metrics_util.h" |
17 #include "components/page_load_metrics/common/page_load_metrics_messages.h" | 18 #include "components/page_load_metrics/common/page_load_metrics_messages.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
46 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL"; | 47 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL"; |
47 const char kAbortChainSizeNoCommit[] = | 48 const char kAbortChainSizeNoCommit[] = |
48 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"; | 49 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"; |
49 const char kClientRedirectDelayAfterPaint[] = | 50 const char kClientRedirectDelayAfterPaint[] = |
50 "PageLoad.Internal.ClientRedirectDelayAfterPaint"; | 51 "PageLoad.Internal.ClientRedirectDelayAfterPaint"; |
51 | 52 |
52 } // namespace internal | 53 } // namespace internal |
53 | 54 |
54 namespace { | 55 namespace { |
55 | 56 |
57 // Helper to allow use of Optional<> values in LOG() messages. | |
58 std::ostream& operator<<(std::ostream& os, | |
59 const base::Optional<base::TimeDelta>& opt) { | |
60 if (opt) | |
61 os << opt.value(); | |
62 else | |
63 os << "(unset)"; | |
64 return os; | |
65 } | |
66 | |
shivanisha
2016/07/07 15:38:57
Would the operator definition be a good fit for ba
Bryan McQuade
2016/07/08 18:39:35
I had wanted to do this as well. I asked the base/
| |
56 // The url we see from the renderer side is not always the same as what | 67 // The url we see from the renderer side is not always the same as what |
57 // we see from the browser side (e.g. chrome://newtab). We want to be | 68 // we see from the browser side (e.g. chrome://newtab). We want to be |
58 // sure here that we aren't logging UMA for internal pages. | 69 // sure here that we aren't logging UMA for internal pages. |
59 bool IsRelevantNavigation(content::NavigationHandle* navigation_handle, | 70 bool IsRelevantNavigation(content::NavigationHandle* navigation_handle, |
60 const GURL& browser_url, | 71 const GURL& browser_url, |
61 const std::string& mime_type) { | 72 const std::string& mime_type) { |
62 DCHECK(navigation_handle->HasCommitted()); | 73 DCHECK(navigation_handle->HasCommitted()); |
63 return navigation_handle->IsInMainFrame() && | 74 return navigation_handle->IsInMainFrame() && |
64 !navigation_handle->IsSamePage() && | 75 !navigation_handle->IsSamePage() && |
65 !navigation_handle->IsErrorPage() && | 76 !navigation_handle->IsErrorPage() && |
66 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() && | 77 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() && |
67 browser_url.SchemeIsHTTPOrHTTPS() && | 78 browser_url.SchemeIsHTTPOrHTTPS() && |
68 (mime_type == "text/html" || mime_type == "application/xhtml+xml"); | 79 (mime_type == "text/html" || mime_type == "application/xhtml+xml"); |
69 } | 80 } |
70 | 81 |
71 // If second is non-zero, first must also be non-zero and less than or equal to | 82 // If second is non-zero, first must also be non-zero and less than or equal to |
72 // second. | 83 // second. |
73 bool EventsInOrder(base::TimeDelta first, base::TimeDelta second) { | 84 bool EventsInOrder(const base::Optional<base::TimeDelta>& first, |
74 if (second.is_zero()) { | 85 const base::Optional<base::TimeDelta>& second) { |
86 if (!second) { | |
75 return true; | 87 return true; |
76 } | 88 } |
77 return !first.is_zero() && first <= second; | 89 return first && first <= second; |
78 } | 90 } |
79 | 91 |
80 bool IsValidPageLoadTiming(const PageLoadTiming& timing) { | 92 bool IsValidPageLoadTiming(const PageLoadTiming& timing) { |
81 if (timing.IsEmpty()) | 93 if (timing.IsEmpty()) |
82 return false; | 94 return false; |
83 | 95 |
84 // If we have a non-empty timing, it should always have a navigation start. | 96 // If we have a non-empty timing, it should always have a navigation start. |
85 if (timing.navigation_start.is_null()) { | 97 if (timing.navigation_start.is_null()) { |
86 NOTREACHED() << "Received null navigation_start."; | 98 NOTREACHED() << "Received null navigation_start."; |
87 return false; | 99 return false; |
(...skipping 16 matching lines...) Expand all Loading... | |
104 << " for parse_start " << timing.parse_start; | 116 << " for parse_start " << timing.parse_start; |
105 return false; | 117 return false; |
106 } | 118 } |
107 | 119 |
108 if (!EventsInOrder(timing.parse_start, timing.parse_stop)) { | 120 if (!EventsInOrder(timing.parse_start, timing.parse_stop)) { |
109 NOTREACHED() << "Invalid parse_start " << timing.parse_start | 121 NOTREACHED() << "Invalid parse_start " << timing.parse_start |
110 << " for parse_stop " << timing.parse_stop; | 122 << " for parse_stop " << timing.parse_stop; |
111 return false; | 123 return false; |
112 } | 124 } |
113 | 125 |
114 if (!timing.parse_stop.is_zero()) { | 126 if (timing.parse_stop) { |
115 const base::TimeDelta parse_duration = | 127 const base::TimeDelta parse_duration = |
116 timing.parse_stop - timing.parse_start; | 128 timing.parse_stop.value() - timing.parse_start.value(); |
117 if (timing.parse_blocked_on_script_load_duration > parse_duration) { | 129 if (timing.parse_blocked_on_script_load_duration > parse_duration) { |
118 NOTREACHED() << "Invalid parse_blocked_on_script_load_duration " | 130 NOTREACHED() << "Invalid parse_blocked_on_script_load_duration " |
119 << timing.parse_blocked_on_script_load_duration | 131 << timing.parse_blocked_on_script_load_duration |
120 << " for parse duration " << parse_duration; | 132 << " for parse duration " << parse_duration; |
121 return false; | 133 return false; |
122 } | 134 } |
123 } | 135 } |
124 | 136 |
125 if (timing.parse_blocked_on_script_load_from_document_write_duration > | 137 if (timing.parse_blocked_on_script_load_from_document_write_duration > |
126 timing.parse_blocked_on_script_load_duration) { | 138 timing.parse_blocked_on_script_load_duration) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 aborted_chain_size_same_url); | 217 aborted_chain_size_same_url); |
206 } | 218 } |
207 } | 219 } |
208 | 220 |
209 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, | 221 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, |
210 const PageLoadTiming& last_timing, | 222 const PageLoadTiming& last_timing, |
211 const PageLoadTiming& new_timing, | 223 const PageLoadTiming& new_timing, |
212 const PageLoadMetadata& last_metadata, | 224 const PageLoadMetadata& last_metadata, |
213 const PageLoadExtraInfo& extra_info) { | 225 const PageLoadExtraInfo& extra_info) { |
214 observer->OnTimingUpdate(new_timing, extra_info); | 226 observer->OnTimingUpdate(new_timing, extra_info); |
215 if (!new_timing.dom_content_loaded_event_start.is_zero() && | 227 if (new_timing.dom_content_loaded_event_start && |
216 last_timing.dom_content_loaded_event_start.is_zero()) | 228 !last_timing.dom_content_loaded_event_start) |
217 observer->OnDomContentLoadedEventStart(new_timing, extra_info); | 229 observer->OnDomContentLoadedEventStart(new_timing, extra_info); |
218 if (!new_timing.load_event_start.is_zero() && | 230 if (new_timing.load_event_start && !last_timing.load_event_start) |
219 last_timing.load_event_start.is_zero()) | |
220 observer->OnLoadEventStart(new_timing, extra_info); | 231 observer->OnLoadEventStart(new_timing, extra_info); |
221 if (!new_timing.first_layout.is_zero() && last_timing.first_layout.is_zero()) | 232 if (new_timing.first_layout && !last_timing.first_layout) |
222 observer->OnFirstLayout(new_timing, extra_info); | 233 observer->OnFirstLayout(new_timing, extra_info); |
223 if (!new_timing.first_paint.is_zero() && last_timing.first_paint.is_zero()) | 234 if (new_timing.first_paint && !last_timing.first_paint) |
224 observer->OnFirstPaint(new_timing, extra_info); | 235 observer->OnFirstPaint(new_timing, extra_info); |
225 if (!new_timing.first_text_paint.is_zero() && | 236 if (new_timing.first_text_paint && !last_timing.first_text_paint) |
226 last_timing.first_text_paint.is_zero()) | |
227 observer->OnFirstTextPaint(new_timing, extra_info); | 237 observer->OnFirstTextPaint(new_timing, extra_info); |
228 if (!new_timing.first_image_paint.is_zero() && | 238 if (new_timing.first_image_paint && !last_timing.first_image_paint) |
229 last_timing.first_image_paint.is_zero()) | |
230 observer->OnFirstImagePaint(new_timing, extra_info); | 239 observer->OnFirstImagePaint(new_timing, extra_info); |
231 if (!new_timing.first_contentful_paint.is_zero() && | 240 if (new_timing.first_contentful_paint && !last_timing.first_contentful_paint) |
232 last_timing.first_contentful_paint.is_zero()) | |
233 observer->OnFirstContentfulPaint(new_timing, extra_info); | 241 observer->OnFirstContentfulPaint(new_timing, extra_info); |
234 if (!new_timing.parse_start.is_zero() && last_timing.parse_start.is_zero()) | 242 if (new_timing.parse_start && !last_timing.parse_start) |
235 observer->OnParseStart(new_timing, extra_info); | 243 observer->OnParseStart(new_timing, extra_info); |
236 if (!new_timing.parse_stop.is_zero() && last_timing.parse_stop.is_zero()) | 244 if (new_timing.parse_stop && !last_timing.parse_stop) |
237 observer->OnParseStop(new_timing, extra_info); | 245 observer->OnParseStop(new_timing, extra_info); |
238 if (extra_info.metadata.behavior_flags != last_metadata.behavior_flags) | 246 if (extra_info.metadata.behavior_flags != last_metadata.behavior_flags) |
239 observer->OnLoadingBehaviorObserved(extra_info); | 247 observer->OnLoadingBehaviorObserved(extra_info); |
240 } | 248 } |
241 | 249 |
242 } // namespace | 250 } // namespace |
243 | 251 |
244 PageLoadTracker::PageLoadTracker( | 252 PageLoadTracker::PageLoadTracker( |
245 bool in_foreground, | 253 bool in_foreground, |
246 PageLoadMetricsEmbedderInterface* embedder_interface, | 254 PageLoadMetricsEmbedderInterface* embedder_interface, |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 | 391 |
384 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 392 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
385 for (const auto& observer : observers_) { | 393 for (const auto& observer : observers_) { |
386 observer->OnUserInput(event); | 394 observer->OnUserInput(event); |
387 } | 395 } |
388 } | 396 } |
389 | 397 |
390 void PageLoadTracker::NotifyClientRedirectTo( | 398 void PageLoadTracker::NotifyClientRedirectTo( |
391 const PageLoadTracker& destination) { | 399 const PageLoadTracker& destination) { |
392 base::TimeDelta redirect_delay_after_paint; | 400 base::TimeDelta redirect_delay_after_paint; |
393 if (!timing_.first_paint.is_zero()) { | 401 if (timing_.first_paint) { |
394 base::TimeTicks first_paint_time = navigation_start() + timing_.first_paint; | 402 base::TimeTicks first_paint_time = |
403 navigation_start() + timing_.first_paint.value(); | |
395 if (destination.navigation_start() > first_paint_time) | 404 if (destination.navigation_start() > first_paint_time) |
396 redirect_delay_after_paint = | 405 redirect_delay_after_paint = |
397 destination.navigation_start() - first_paint_time; | 406 destination.navigation_start() - first_paint_time; |
398 } | 407 } |
399 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectDelayAfterPaint, | 408 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectDelayAfterPaint, |
400 redirect_delay_after_paint); | 409 redirect_delay_after_paint); |
401 } | 410 } |
402 | 411 |
403 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing, | 412 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing, |
404 const PageLoadMetadata& new_metadata) { | 413 const PageLoadMetadata& new_metadata) { |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
912 | 921 |
913 if (!committed_load_->UpdateTiming(timing, metadata)) { | 922 if (!committed_load_->UpdateTiming(timing, metadata)) { |
914 // If the page load tracker cannot update its timing, something is wrong | 923 // If the page load tracker cannot update its timing, something is wrong |
915 // with the IPC (it's from another load, or it's invalid in some other way). | 924 // with the IPC (it's from another load, or it's invalid in some other way). |
916 // We expect this to be a rare occurrence. | 925 // We expect this to be a rare occurrence. |
917 RecordInternalError(ERR_BAD_TIMING_IPC); | 926 RecordInternalError(ERR_BAD_TIMING_IPC); |
918 } | 927 } |
919 } | 928 } |
920 | 929 |
921 } // namespace page_load_metrics | 930 } // namespace page_load_metrics |
OLD | NEW |