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 "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <ostream> | 8 #include <ostream> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/location.h" | 12 #include "base/location.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/metrics/user_metrics.h" | 16 #include "base/metrics/user_metrics.h" |
17 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" | 17 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" |
18 #include "chrome/common/page_load_metrics/page_load_metrics_messages.h" | 18 #include "chrome/common/page_load_metrics/page_load_metrics_messages.h" |
19 #include "chrome/common/page_load_metrics/page_load_timing.h" | 19 #include "chrome/common/page_load_metrics/page_load_timing.h" |
20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/navigation_details.h" | 21 #include "content/public/browser/navigation_details.h" |
22 #include "content/public/browser/navigation_handle.h" | 22 #include "content/public/browser/navigation_handle.h" |
23 #include "content/public/browser/render_frame_host.h" | 23 #include "content/public/browser/render_frame_host.h" |
24 #include "content/public/browser/render_view_host.h" | 24 #include "content/public/browser/render_view_host.h" |
25 #include "content/public/browser/render_widget_host.h" | |
26 #include "content/public/browser/render_widget_host_iterator.h" | |
25 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
26 #include "content/public/browser/web_contents_observer.h" | 28 #include "content/public/browser/web_contents_observer.h" |
27 #include "content/public/browser/web_contents_user_data.h" | 29 #include "content/public/browser/web_contents_user_data.h" |
28 #include "ipc/ipc_message.h" | 30 #include "ipc/ipc_message.h" |
29 #include "ipc/ipc_message_macros.h" | 31 #include "ipc/ipc_message_macros.h" |
30 #include "ui/base/page_transition_types.h" | 32 #include "ui/base/page_transition_types.h" |
31 | 33 |
32 DEFINE_WEB_CONTENTS_USER_DATA_KEY( | 34 DEFINE_WEB_CONTENTS_USER_DATA_KEY( |
33 page_load_metrics::MetricsWebContentsObserver); | 35 page_load_metrics::MetricsWebContentsObserver); |
34 | 36 |
(...skipping 11 matching lines...) Expand all Loading... | |
46 const char kAbortChainSizeSameURL[] = | 48 const char kAbortChainSizeSameURL[] = |
47 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL"; | 49 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL"; |
48 const char kAbortChainSizeNoCommit[] = | 50 const char kAbortChainSizeNoCommit[] = |
49 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"; | 51 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"; |
50 const char kClientRedirectFirstPaintToNavigation[] = | 52 const char kClientRedirectFirstPaintToNavigation[] = |
51 "PageLoad.Internal.ClientRedirect.FirstPaintToNavigation"; | 53 "PageLoad.Internal.ClientRedirect.FirstPaintToNavigation"; |
52 const char kClientRedirectWithoutPaint[] = | 54 const char kClientRedirectWithoutPaint[] = |
53 "PageLoad.Internal.ClientRedirect.NavigationWithoutPaint"; | 55 "PageLoad.Internal.ClientRedirect.NavigationWithoutPaint"; |
54 const char kCommitToCompleteNoTimingIPCs[] = | 56 const char kCommitToCompleteNoTimingIPCs[] = |
55 "PageLoad.Internal.CommitToComplete.NoTimingIPCs"; | 57 "PageLoad.Internal.CommitToComplete.NoTimingIPCs"; |
58 const char kPageLoadCompletedAfterAppBackground[] = | |
59 "PageLoad.Internal.PageLoadCompleted.AfterAppBackground"; | |
56 | 60 |
57 } // namespace internal | 61 } // namespace internal |
58 | 62 |
59 namespace { | 63 namespace { |
60 | 64 |
61 // Helper to allow use of Optional<> values in LOG() messages. | 65 // Helper to allow use of Optional<> values in LOG() messages. |
62 std::ostream& operator<<(std::ostream& os, | 66 std::ostream& operator<<(std::ostream& os, |
63 const base::Optional<base::TimeDelta>& opt) { | 67 const base::Optional<base::TimeDelta>& opt) { |
64 if (opt) | 68 if (opt) |
65 os << opt.value(); | 69 os << opt.value(); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } // namespace | 244 } // namespace |
241 | 245 |
242 PageLoadTracker::PageLoadTracker( | 246 PageLoadTracker::PageLoadTracker( |
243 bool in_foreground, | 247 bool in_foreground, |
244 PageLoadMetricsEmbedderInterface* embedder_interface, | 248 PageLoadMetricsEmbedderInterface* embedder_interface, |
245 const GURL& currently_committed_url, | 249 const GURL& currently_committed_url, |
246 content::NavigationHandle* navigation_handle, | 250 content::NavigationHandle* navigation_handle, |
247 int aborted_chain_size, | 251 int aborted_chain_size, |
248 int aborted_chain_size_same_url) | 252 int aborted_chain_size_same_url) |
249 : did_stop_tracking_(false), | 253 : did_stop_tracking_(false), |
254 app_entered_background_(false), | |
250 navigation_start_(navigation_handle->NavigationStart()), | 255 navigation_start_(navigation_handle->NavigationStart()), |
251 url_(navigation_handle->GetURL()), | 256 url_(navigation_handle->GetURL()), |
252 abort_type_(ABORT_NONE), | 257 abort_type_(ABORT_NONE), |
253 started_in_foreground_(in_foreground), | 258 started_in_foreground_(in_foreground), |
254 aborted_chain_size_(aborted_chain_size), | 259 aborted_chain_size_(aborted_chain_size), |
255 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 260 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
256 embedder_interface_(embedder_interface) { | 261 embedder_interface_(embedder_interface) { |
257 DCHECK(!navigation_handle->HasCommitted()); | 262 DCHECK(!navigation_handle->HasCommitted()); |
258 embedder_interface_->RegisterObservers(this); | 263 embedder_interface_->RegisterObservers(this); |
259 for (const auto& observer : observers_) { | 264 for (const auto& observer : observers_) { |
260 observer->OnStart(navigation_handle, currently_committed_url, | 265 observer->OnStart(navigation_handle, currently_committed_url, |
261 started_in_foreground_); | 266 started_in_foreground_); |
262 } | 267 } |
263 } | 268 } |
264 | 269 |
265 PageLoadTracker::~PageLoadTracker() { | 270 PageLoadTracker::~PageLoadTracker() { |
271 if (app_entered_background_) { | |
Charlie Harrison
2016/07/28 14:45:27
Hm. Can you log a 3-state histogram instead of a 2
Bryan McQuade
2016/07/28 16:26:11
I think the third state you describe should just b
Bryan McQuade
2016/07/28 16:29:15
Ah, sorry, re-reading your comment, I think this h
Charlie Harrison
2016/07/28 16:38:04
Ah you're right, my mistake.
| |
272 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, true); | |
273 } | |
274 | |
266 if (did_stop_tracking_) | 275 if (did_stop_tracking_) |
267 return; | 276 return; |
268 | 277 |
269 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 278 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
270 DCHECK_NE(static_cast<bool>(info.time_to_commit), | 279 DCHECK_NE(static_cast<bool>(info.time_to_commit), |
271 static_cast<bool>(failed_provisional_load_info_)); | 280 static_cast<bool>(failed_provisional_load_info_)); |
272 if (info.time_to_commit && timing_.IsEmpty()) { | 281 if (info.time_to_commit && timing_.IsEmpty()) { |
273 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 282 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
274 const base::TimeTicks commit_time = | 283 const base::TimeTicks commit_time = |
275 navigation_start_ + info.time_to_commit.value(); | 284 navigation_start_ + info.time_to_commit.value(); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 observer->OnRedirect(navigation_handle); | 400 observer->OnRedirect(navigation_handle); |
392 } | 401 } |
393 } | 402 } |
394 | 403 |
395 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 404 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
396 for (const auto& observer : observers_) { | 405 for (const auto& observer : observers_) { |
397 observer->OnUserInput(event); | 406 observer->OnUserInput(event); |
398 } | 407 } |
399 } | 408 } |
400 | 409 |
410 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { | |
411 if (!app_entered_background_) { | |
412 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, | |
413 false); | |
414 app_entered_background_ = true; | |
415 } | |
416 } | |
417 | |
401 void PageLoadTracker::NotifyClientRedirectTo( | 418 void PageLoadTracker::NotifyClientRedirectTo( |
402 const PageLoadTracker& destination) { | 419 const PageLoadTracker& destination) { |
403 if (timing_.first_paint) { | 420 if (timing_.first_paint) { |
404 base::TimeTicks first_paint_time = | 421 base::TimeTicks first_paint_time = |
405 navigation_start() + timing_.first_paint.value(); | 422 navigation_start() + timing_.first_paint.value(); |
406 base::TimeDelta first_paint_to_navigation; | 423 base::TimeDelta first_paint_to_navigation; |
407 if (destination.navigation_start() > first_paint_time) | 424 if (destination.navigation_start() > first_paint_time) |
408 first_paint_to_navigation = | 425 first_paint_to_navigation = |
409 destination.navigation_start() - first_paint_time; | 426 destination.navigation_start() - first_paint_time; |
410 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, | 427 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 std::move(embedder_interface)); | 625 std::move(embedder_interface)); |
609 web_contents->SetUserData(UserDataKey(), metrics); | 626 web_contents->SetUserData(UserDataKey(), metrics); |
610 } | 627 } |
611 return metrics; | 628 return metrics; |
612 } | 629 } |
613 | 630 |
614 MetricsWebContentsObserver::~MetricsWebContentsObserver() { | 631 MetricsWebContentsObserver::~MetricsWebContentsObserver() { |
615 NotifyAbortAllLoads(ABORT_CLOSE); | 632 NotifyAbortAllLoads(ABORT_CLOSE); |
616 } | 633 } |
617 | 634 |
635 // static | |
636 std::vector<MetricsWebContentsObserver*> | |
637 MetricsWebContentsObserver::GetAllObservers() { | |
638 std::vector<MetricsWebContentsObserver*> result; | |
639 std::unique_ptr<content::RenderWidgetHostIterator> widgets( | |
640 content::RenderWidgetHost::GetRenderWidgetHosts()); | |
641 while (content::RenderWidgetHost* rwh = widgets->GetNextHost()) { | |
642 content::RenderViewHost* rvh = content::RenderViewHost::From(rwh); | |
643 if (!rvh) | |
644 continue; | |
645 content::WebContents* web_contents = | |
646 content::WebContents::FromRenderViewHost(rvh); | |
647 if (!web_contents) | |
648 continue; | |
649 if (web_contents->GetRenderViewHost() != rvh) | |
Charlie Harrison
2016/07/28 14:45:27
How can this happen?
Bryan McQuade
2016/07/28 16:26:11
I actually lifted this logic from
https://cs.chrom
Charlie Harrison
2016/07/28 16:38:04
Yeah, let's see if we can expose this. No point du
Charlie Reis
2016/07/28 17:36:49
Adding jam@, who has been against having a public
Charlie Harrison
2016/07/28 17:42:17
Ah that makes sense. Bryan, have you look at doing
Charlie Reis
2016/07/28 17:56:44
That would be great if it covered all the cases yo
| |
650 continue; | |
651 MetricsWebContentsObserver* observer = | |
652 MetricsWebContentsObserver::FromWebContents(web_contents); | |
653 if (!observer) | |
654 continue; | |
655 // Verify there are no duplicates. | |
656 DCHECK(std::find(result.begin(), result.end(), observer) == result.end()); | |
Charlie Harrison
2016/07/28 14:45:27
If you want this feature let's use an std::set ins
Bryan McQuade
2016/07/28 16:26:11
The drawback to set<> is that iteration order will
Charlie Harrison
2016/07/28 16:38:04
No, your reasoning makes sense. Keeping this DCHEC
| |
657 result.push_back(observer); | |
658 } | |
659 return result; | |
660 } | |
661 | |
618 void MetricsWebContentsObserver::RegisterInputEventObserver( | 662 void MetricsWebContentsObserver::RegisterInputEventObserver( |
619 content::RenderViewHost* host) { | 663 content::RenderViewHost* host) { |
620 if (host != nullptr) | 664 if (host != nullptr) |
621 host->GetWidget()->AddInputEventObserver(this); | 665 host->GetWidget()->AddInputEventObserver(this); |
622 } | 666 } |
623 | 667 |
624 void MetricsWebContentsObserver::UnregisterInputEventObserver( | 668 void MetricsWebContentsObserver::UnregisterInputEventObserver( |
625 content::RenderViewHost* host) { | 669 content::RenderViewHost* host) { |
626 if (host != nullptr) | 670 if (host != nullptr) |
627 host->GetWidget()->RemoveInputEventObserver(this); | 671 host->GetWidget()->RemoveInputEventObserver(this); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
798 void MetricsWebContentsObserver::OnInputEvent( | 842 void MetricsWebContentsObserver::OnInputEvent( |
799 const blink::WebInputEvent& event) { | 843 const blink::WebInputEvent& event) { |
800 // Ignore browser navigation or reload which comes with type Undefined. | 844 // Ignore browser navigation or reload which comes with type Undefined. |
801 if (event.type == blink::WebInputEvent::Type::Undefined) | 845 if (event.type == blink::WebInputEvent::Type::Undefined) |
802 return; | 846 return; |
803 | 847 |
804 if (committed_load_) | 848 if (committed_load_) |
805 committed_load_->OnInputEvent(event); | 849 committed_load_->OnInputEvent(event); |
806 } | 850 } |
807 | 851 |
852 void MetricsWebContentsObserver::FlushMetricsOnAppEnterBackground() { | |
853 if (committed_load_) | |
854 committed_load_->FlushMetricsOnAppEnterBackground(); | |
855 for (const auto& kv : provisional_loads_) { | |
856 kv.second->FlushMetricsOnAppEnterBackground(); | |
857 } | |
858 for (const auto& tracker : aborted_provisional_loads_) { | |
859 tracker->FlushMetricsOnAppEnterBackground(); | |
860 } | |
861 } | |
862 | |
808 void MetricsWebContentsObserver::DidRedirectNavigation( | 863 void MetricsWebContentsObserver::DidRedirectNavigation( |
809 content::NavigationHandle* navigation_handle) { | 864 content::NavigationHandle* navigation_handle) { |
810 if (!navigation_handle->IsInMainFrame()) | 865 if (!navigation_handle->IsInMainFrame()) |
811 return; | 866 return; |
812 auto it = provisional_loads_.find(navigation_handle); | 867 auto it = provisional_loads_.find(navigation_handle); |
813 if (it == provisional_loads_.end()) | 868 if (it == provisional_loads_.end()) |
814 return; | 869 return; |
815 it->second->Redirect(navigation_handle); | 870 it->second->Redirect(navigation_handle); |
816 } | 871 } |
817 | 872 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage()) | 1006 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage()) |
952 return false; | 1007 return false; |
953 const std::string& mime_type = web_contents()->GetContentsMimeType(); | 1008 const std::string& mime_type = web_contents()->GetContentsMimeType(); |
954 if (mime_type != "text/html" && mime_type != "application/xhtml+xml") | 1009 if (mime_type != "text/html" && mime_type != "application/xhtml+xml") |
955 return false; | 1010 return false; |
956 } | 1011 } |
957 return true; | 1012 return true; |
958 } | 1013 } |
959 | 1014 |
960 } // namespace page_load_metrics | 1015 } // namespace page_load_metrics |
OLD | NEW |