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

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

Issue 2189543002: Notify page load metrics when the app enters the background. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@clankbackgroundcallback
Patch Set: rename method Created 4 years, 4 months 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 "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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698