[Extensions] Make extension message bubble factory platform-abstract
[chromium-blink-merge.git] / chrome / browser / sessions / session_restore_stats_collector.cc
blob26e1b647ee09e8d989be3e015b2ee682c6fd30ea
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
3 // found in the LICENSE file.
5 #include "chrome/browser/sessions/session_restore_stats_collector.h"
7 #include <string>
9 #include "base/metrics/histogram.h"
10 #include "base/strings/stringprintf.h"
11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents.h"
16 using content::NavigationController;
17 using content::RenderWidgetHost;
18 using content::WebContents;
20 // static
21 void SessionRestoreStatsCollector::TrackTabs(
22 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
23 const base::TimeTicks& restore_started,
24 bool active_only) {
25 if (!shared_collector_)
26 shared_collector_ = new SessionRestoreStatsCollector(restore_started);
28 shared_collector_->AddTabs(tabs, active_only);
31 SessionRestoreStatsCollector::SessionRestoreStatsCollector(
32 const base::TimeTicks& restore_started)
33 : got_first_foreground_load_(false),
34 got_first_paint_(false),
35 restore_started_(restore_started),
36 tab_count_(0),
37 max_parallel_tab_loads_(0) {
38 this_retainer_ = this;
39 registrar_.Add(
40 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
41 content::NotificationService::AllSources());
44 SessionRestoreStatsCollector::~SessionRestoreStatsCollector() {
45 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
46 tabs_tracked_.empty() && render_widget_hosts_loading_.empty());
47 DCHECK(shared_collector_ == this);
48 shared_collector_ = nullptr;
51 void SessionRestoreStatsCollector::Observe(
52 int type,
53 const content::NotificationSource& source,
54 const content::NotificationDetails& details) {
55 switch (type) {
56 case content::NOTIFICATION_LOAD_START: {
57 // Add this render_widget_host to the set of those we're waiting for
58 // paints on. We want to only record stats for paints that occur after
59 // a load has finished.
60 NavigationController* tab =
61 content::Source<NavigationController>(source).ptr();
62 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
63 DCHECK(render_widget_host);
64 render_widget_hosts_loading_.insert(render_widget_host);
65 break;
67 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
68 WebContents* web_contents = content::Source<WebContents>(source).ptr();
69 RemoveTab(&web_contents->GetController());
70 break;
72 case content::NOTIFICATION_LOAD_STOP: {
73 NavigationController* tab =
74 content::Source<NavigationController>(source).ptr();
75 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
76 render_widget_hosts_to_paint_.insert(render_widget_host);
77 RemoveTab(tab);
78 if (!got_first_foreground_load_ && render_widget_host &&
79 render_widget_host->GetView() &&
80 render_widget_host->GetView()->IsShowing()) {
81 got_first_foreground_load_ = true;
82 base::TimeDelta time_to_load =
83 base::TimeTicks::Now() - restore_started_;
84 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded",
85 time_to_load,
86 base::TimeDelta::FromMilliseconds(10),
87 base::TimeDelta::FromSeconds(100), 100);
88 // Record a time for the number of tabs, to help track down
89 // contention.
90 std::string time_for_count = base::StringPrintf(
91 "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_);
92 base::HistogramBase* counter_for_count =
93 base::Histogram::FactoryTimeGet(
94 time_for_count, base::TimeDelta::FromMilliseconds(10),
95 base::TimeDelta::FromSeconds(100), 100,
96 base::Histogram::kUmaTargetedHistogramFlag);
97 counter_for_count->AddTime(time_to_load);
99 break;
101 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
102 RenderWidgetHost* render_widget_host =
103 content::Source<RenderWidgetHost>(source).ptr();
104 if (!got_first_paint_ && render_widget_host->GetView() &&
105 render_widget_host->GetView()->IsShowing()) {
106 if (render_widget_hosts_to_paint_.find(render_widget_host) !=
107 render_widget_hosts_to_paint_.end()) {
108 // Got a paint for one of our renderers, so record time.
109 got_first_paint_ = true;
110 base::TimeDelta time_to_paint =
111 base::TimeTicks::Now() - restore_started_;
112 // TODO(danduong): to remove this with 467680, to make sure we
113 // don't forget to clean this up.
114 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint",
115 time_to_paint,
116 base::TimeDelta::FromMilliseconds(10),
117 base::TimeDelta::FromSeconds(100), 100);
118 // Record a time for the number of tabs, to help track down
119 // contention.
120 std::string time_for_count = base::StringPrintf(
121 "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_);
122 base::HistogramBase* counter_for_count =
123 base::Histogram::FactoryTimeGet(
124 time_for_count, base::TimeDelta::FromMilliseconds(10),
125 base::TimeDelta::FromSeconds(100), 100,
126 base::Histogram::kUmaTargetedHistogramFlag);
127 counter_for_count->AddTime(time_to_paint);
128 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint2",
129 time_to_paint,
130 base::TimeDelta::FromMilliseconds(100),
131 base::TimeDelta::FromMinutes(16), 50);
132 // Record a time for the number of tabs, to help track down
133 // contention.
134 std::string time_for_count2 = base::StringPrintf(
135 "SessionRestore.ForegroundTabFirstPaint2_%d", tab_count_);
136 base::HistogramBase* counter_for_count2 =
137 base::Histogram::FactoryTimeGet(
138 time_for_count2, base::TimeDelta::FromMilliseconds(100),
139 base::TimeDelta::FromMinutes(16), 50,
140 base::Histogram::kUmaTargetedHistogramFlag);
141 counter_for_count2->AddTime(time_to_paint);
142 } else if (render_widget_hosts_loading_.find(render_widget_host) ==
143 render_widget_hosts_loading_.end()) {
144 // If this is a host for a tab we're not loading some other tab
145 // has rendered and there's no point tracking the time. This could
146 // happen because the user opened a different tab or restored tabs
147 // to an already existing browser and an existing tab painted.
148 got_first_paint_ = true;
151 break;
153 default:
154 NOTREACHED() << "Unknown notification received:" << type;
155 break;
158 // Check if we are done and if so, reset |this_retainer_| as the collector no
159 // longer needs to stay alive.
160 if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
161 tabs_tracked_.empty() && render_widget_hosts_loading_.empty())
162 this_retainer_ = nullptr;
165 void SessionRestoreStatsCollector::AddTabs(
166 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
167 bool active_only) {
168 tab_count_ += tabs.size();
169 for (auto& tab : tabs) {
170 // If we are only restoring active tabs and the tab is not active, nothing
171 // to do.
172 if (active_only && !tab.is_active)
173 continue;
174 RegisterForNotifications(&tab.contents->GetController());
175 if (tab.is_active) {
176 RenderWidgetHost* render_widget_host =
177 GetRenderWidgetHost(&tab.contents->GetController());
178 render_widget_hosts_loading_.insert(render_widget_host);
183 void SessionRestoreStatsCollector::RemoveTab(NavigationController* tab) {
184 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
185 content::Source<WebContents>(tab->GetWebContents()));
186 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
187 content::Source<NavigationController>(tab));
188 registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
189 content::Source<NavigationController>(tab));
190 if (render_widget_hosts_loading_.size() > max_parallel_tab_loads_)
191 max_parallel_tab_loads_ = render_widget_hosts_loading_.size();
192 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
193 render_widget_hosts_loading_.erase(render_widget_host);
194 tabs_tracked_.erase(tab);
196 // If there are no more tabs loading or being tracked, restore is done and
197 // record the time. Note that we are not yet finished, as we might still be
198 // waiting for our first paint, which can happen after all tabs are done
199 // loading.
200 // TODO(georgesak): review behaviour of ForegroundTabFirstPaint.
201 if (tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) {
202 base::TimeDelta time_to_load = base::TimeTicks::Now() - restore_started_;
203 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", time_to_load,
204 base::TimeDelta::FromMilliseconds(10),
205 base::TimeDelta::FromSeconds(100), 100);
206 // Record a time for the number of tabs, to help track down contention.
207 std::string time_for_count =
208 base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
209 base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet(
210 time_for_count, base::TimeDelta::FromMilliseconds(10),
211 base::TimeDelta::FromSeconds(100), 100,
212 base::Histogram::kUmaTargetedHistogramFlag);
213 counter_for_count->AddTime(time_to_load);
215 UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads",
216 max_parallel_tab_loads_);
220 void SessionRestoreStatsCollector::RegisterForNotifications(
221 NavigationController* tab) {
222 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
223 content::Source<WebContents>(tab->GetWebContents()));
224 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
225 content::Source<NavigationController>(tab));
226 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
227 content::Source<NavigationController>(tab));
228 tabs_tracked_.insert(tab);
231 RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost(
232 NavigationController* tab) {
233 WebContents* web_contents = tab->GetWebContents();
234 if (web_contents) {
235 content::RenderWidgetHostView* render_widget_host_view =
236 web_contents->GetRenderWidgetHostView();
237 if (render_widget_host_view)
238 return render_widget_host_view->GetRenderWidgetHost();
240 return nullptr;
243 // static
244 SessionRestoreStatsCollector* SessionRestoreStatsCollector::shared_collector_ =
245 nullptr;