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

Side by Side Diff: chrome/browser/metrics/first_web_contents_profiler.cc

Issue 2651823002: Add .SingleTab and .MultiTabs suffix to Startup.FirstWebContents.MainNavigationStart histogram. (Closed)
Patch Set: rebase on r448292 Created 3 years, 10 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #if !defined(OS_ANDROID)
6
7 #include "chrome/browser/metrics/first_web_contents_profiler.h" 5 #include "chrome/browser/metrics/first_web_contents_profiler.h"
8 6
9 #include <string> 7 #include <string>
10 8
11 #include "base/location.h" 9 #include "base/location.h"
12 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
14 #include "base/time/time.h" 13 #include "base/time/time.h"
15 #include "build/build_config.h" 14 #include "build/build_config.h"
16 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h" 17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "components/metrics/profiler/tracking_synchronizer.h" 18 #include "components/metrics/profiler/tracking_synchronizer.h"
20 #include "components/metrics/proto/profiler_event.pb.h" 19 #include "components/metrics/proto/profiler_event.pb.h"
21 #include "components/startup_metric_utils/browser/startup_metric_utils.h" 20 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
22 #include "content/public/browser/navigation_handle.h" 21 #include "content/public/browser/navigation_handle.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_observer.h"
23 #include "content/public/common/browser_side_navigation_policy.h" 24 #include "content/public/common/browser_side_navigation_policy.h"
24 25
25 // static 26 namespace {
26 void FirstWebContentsProfiler::Start() { 27
27 for (auto* browser : *BrowserList::GetInstance()) { 28 class FirstWebContentsProfiler : public content::WebContentsObserver {
28 content::WebContents* web_contents = 29 public:
29 browser->tab_strip_model()->GetActiveWebContents(); 30 FirstWebContentsProfiler(content::WebContents* web_contents,
30 if (web_contents) { 31 startup_metric_utils::WebContentsWorkload workload);
31 // FirstWebContentsProfiler owns itself and is also bound to 32
32 // |web_contents|'s lifetime by observing WebContentsDestroyed(). 33 private:
33 new FirstWebContentsProfiler(web_contents); 34 // Reasons for which profiling is deemed complete. Logged in UMA (do not re-
34 return; 35 // order or re-assign).
35 } 36 enum FinishReason {
36 } 37 // All metrics were successfully gathered.
37 } 38 DONE = 0,
39 // Abandon if blocking UI was shown during startup.
40 ABANDON_BLOCKING_UI = 1,
41 // Abandon if the content is hidden (lowers scheduling priority).
42 ABANDON_CONTENT_HIDDEN = 2,
43 // Abandon if the content is destroyed.
44 ABANDON_CONTENT_DESTROYED = 3,
45 // Abandon if the WebContents navigates away from its initial page.
46 ABANDON_NEW_NAVIGATION = 4,
47 // Abandon if the WebContents fails to load (e.g. network error, etc.).
48 ABANDON_NAVIGATION_ERROR = 5,
49 ENUM_MAX
50 };
51
52 ~FirstWebContentsProfiler() override = default;
53
54 // content::WebContentsObserver:
55 void DidFirstVisuallyNonEmptyPaint() override;
56 void DocumentOnLoadCompletedInMainFrame() override;
57 void DidStartNavigation(
58 content::NavigationHandle* navigation_handle) override;
59 void DidFinishNavigation(
60 content::NavigationHandle* navigation_handle) override;
61 void WasHidden() override;
62 void WebContentsDestroyed() override;
63
64 // Whether this instance has finished collecting first-paint and main-frame-
65 // load metrics (navigation metrics are recorded on a best effort but don't
66 // prevent the FirstWebContentsProfiler from calling it).
67 bool IsFinishedCollectingMetrics();
68
69 // Logs |finish_reason| to UMA and deletes this FirstWebContentsProfiler.
70 void FinishedCollectingMetrics(FinishReason finish_reason);
71
72 // Whether an attempt was made to collect the "NonEmptyPaint" metric.
73 bool collected_paint_metric_;
74
75 // Whether an attempt was made to collect the "MainFrameLoad" metric.
76 bool collected_load_metric_;
77
78 // Whether an attempt was made to collect the "MainNavigationStart" metric.
79 bool collected_main_navigation_start_metric_;
80
81 // Whether an attempt was made to collect the "MainNavigationFinished" metric.
82 bool collected_main_navigation_finished_metric_;
83
84 const startup_metric_utils::WebContentsWorkload workload_;
85
86 DISALLOW_COPY_AND_ASSIGN(FirstWebContentsProfiler);
87 };
38 88
39 FirstWebContentsProfiler::FirstWebContentsProfiler( 89 FirstWebContentsProfiler::FirstWebContentsProfiler(
40 content::WebContents* web_contents) 90 content::WebContents* web_contents,
91 startup_metric_utils::WebContentsWorkload workload)
41 : content::WebContentsObserver(web_contents), 92 : content::WebContentsObserver(web_contents),
42 collected_paint_metric_(false), 93 collected_paint_metric_(false),
43 collected_load_metric_(false), 94 collected_load_metric_(false),
44 collected_main_navigation_start_metric_(false), 95 collected_main_navigation_start_metric_(false),
45 collected_main_navigation_finished_metric_(false) {} 96 collected_main_navigation_finished_metric_(false),
97 workload_(workload) {}
46 98
47 void FirstWebContentsProfiler::DidFirstVisuallyNonEmptyPaint() { 99 void FirstWebContentsProfiler::DidFirstVisuallyNonEmptyPaint() {
48 if (collected_paint_metric_) 100 if (collected_paint_metric_)
49 return; 101 return;
50 if (startup_metric_utils::WasNonBrowserUIDisplayed()) { 102 if (startup_metric_utils::WasNonBrowserUIDisplayed()) {
51 FinishedCollectingMetrics(FinishReason::ABANDON_BLOCKING_UI); 103 FinishedCollectingMetrics(FinishReason::ABANDON_BLOCKING_UI);
52 return; 104 return;
53 } 105 }
54 106
55 collected_paint_metric_ = true; 107 collected_paint_metric_ = true;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // browser-initiated loads instead of through an IPC. This means that we 145 // browser-initiated loads instead of through an IPC. This means that we
94 // will miss this signal. Instead we record it when the commit completes. 146 // will miss this signal. Instead we record it when the commit completes.
95 return; 147 return;
96 } 148 }
97 149
98 // The first navigation has to be the main frame's. 150 // The first navigation has to be the main frame's.
99 DCHECK(navigation_handle->IsInMainFrame()); 151 DCHECK(navigation_handle->IsInMainFrame());
100 152
101 collected_main_navigation_start_metric_ = true; 153 collected_main_navigation_start_metric_ = true;
102 startup_metric_utils::RecordFirstWebContentsMainNavigationStart( 154 startup_metric_utils::RecordFirstWebContentsMainNavigationStart(
103 base::TimeTicks::Now()); 155 base::TimeTicks::Now(), workload_);
104 } 156 }
105 157
106 void FirstWebContentsProfiler::DidFinishNavigation( 158 void FirstWebContentsProfiler::DidFinishNavigation(
107 content::NavigationHandle* navigation_handle) { 159 content::NavigationHandle* navigation_handle) {
108 if (collected_main_navigation_finished_metric_) { 160 if (collected_main_navigation_finished_metric_) {
109 // Abandon profiling on a top-level navigation to a different page as it: 161 // Abandon profiling on a top-level navigation to a different page as it:
110 // (1) is no longer a fair timing; and 162 // (1) is no longer a fair timing; and
111 // (2) can cause http://crbug.com/525209 where one of the timing 163 // (2) can cause http://crbug.com/525209 where one of the timing
112 // heuristics (e.g. first paint) didn't fire for the initial content 164 // heuristics (e.g. first paint) didn't fire for the initial content
113 // but fires after a lot of idle time when the user finally navigates 165 // but fires after a lot of idle time when the user finally navigates
(...skipping 15 matching lines...) Expand all
129 DCHECK(navigation_handle->IsInMainFrame()); 181 DCHECK(navigation_handle->IsInMainFrame());
130 182
131 if (!navigation_handle->HasCommitted() || 183 if (!navigation_handle->HasCommitted() ||
132 navigation_handle->IsErrorPage()) { 184 navigation_handle->IsErrorPage()) {
133 FinishedCollectingMetrics(FinishReason::ABANDON_NAVIGATION_ERROR); 185 FinishedCollectingMetrics(FinishReason::ABANDON_NAVIGATION_ERROR);
134 return; 186 return;
135 } 187 }
136 188
137 if (content::IsBrowserSideNavigationEnabled()) { 189 if (content::IsBrowserSideNavigationEnabled()) {
138 startup_metric_utils::RecordFirstWebContentsMainNavigationStart( 190 startup_metric_utils::RecordFirstWebContentsMainNavigationStart(
139 navigation_handle->NavigationStart()); 191 navigation_handle->NavigationStart(), workload_);
140 collected_main_navigation_start_metric_ = true; 192 collected_main_navigation_start_metric_ = true;
141 } 193 }
142 194
143 collected_main_navigation_finished_metric_ = true; 195 collected_main_navigation_finished_metric_ = true;
144 startup_metric_utils::RecordFirstWebContentsMainNavigationFinished( 196 startup_metric_utils::RecordFirstWebContentsMainNavigationFinished(
145 base::TimeTicks::Now()); 197 base::TimeTicks::Now());
146 } 198 }
147 199
148 void FirstWebContentsProfiler::WasHidden() { 200 void FirstWebContentsProfiler::WasHidden() {
149 // Stop profiling if the content gets hidden as its load may be deprioritized 201 // Stop profiling if the content gets hidden as its load may be deprioritized
(...skipping 18 matching lines...) Expand all
168 finish_reason, FinishReason::ENUM_MAX); 220 finish_reason, FinishReason::ENUM_MAX);
169 } 221 }
170 if (!collected_load_metric_) { 222 if (!collected_load_metric_) {
171 UMA_HISTOGRAM_ENUMERATION("Startup.FirstWebContents.FinishReason_NoLoad", 223 UMA_HISTOGRAM_ENUMERATION("Startup.FirstWebContents.FinishReason_NoLoad",
172 finish_reason, FinishReason::ENUM_MAX); 224 finish_reason, FinishReason::ENUM_MAX);
173 } 225 }
174 226
175 delete this; 227 delete this;
176 } 228 }
177 229
178 #endif // !defined(OS_ANDROID) 230 } // namespace
231
232 namespace metrics {
233
234 void BeginFirstWebContentsProfiling() {
235 using startup_metric_utils::WebContentsWorkload;
236
237 const BrowserList* browser_list = BrowserList::GetInstance();
238
239 const auto first_browser = browser_list->begin();
240 if (first_browser == browser_list->end())
241 return;
242
243 const TabStripModel* tab_strip = (*first_browser)->tab_strip_model();
244 DCHECK(!tab_strip->empty());
245
246 content::WebContents* web_contents = tab_strip->GetActiveWebContents();
247 DCHECK(web_contents);
248
249 const bool single_tab = browser_list->size() == 1 && tab_strip->count() == 1;
250
251 // FirstWebContentsProfiler owns itself and is also bound to
252 // |web_contents|'s lifetime by observing WebContentsDestroyed().
253 new FirstWebContentsProfiler(web_contents,
254 single_tab ? WebContentsWorkload::SINGLE_TAB
255 : WebContentsWorkload::MULTI_TABS);
256 }
257
258 } // namespace metrics
OLDNEW
« no previous file with comments | « chrome/browser/metrics/first_web_contents_profiler.h ('k') | components/startup_metric_utils/browser/startup_metric_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698