Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / sessions / session_restore_stats_collector.h
blob9daa043f9dc4a4b809aeb7a44055017516f1e9dc
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 #ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
6 #define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
8 #include <map>
10 #include "base/callback_list.h"
11 #include "base/time/tick_clock.h"
12 #include "chrome/browser/sessions/session_restore.h"
13 #include "chrome/browser/sessions/session_restore_delegate.h"
14 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h"
17 namespace content {
18 class NavigationController;
19 class RenderWidgetHost;
22 // SessionRestoreStatsCollector observes SessionRestore events ands records UMA
23 // accordingly.
25 // A SessionRestoreStatsCollector is tied to an instance of a session restore,
26 // currently being instantianted and owned by the TabLoader. It has two main
27 // phases to its life:
29 // 1. The session restore is active and ongoing (the TabLoader is still
30 // scheduling tabs for loading). This phases ends when there are no
31 // non-deferred tabs left to be loaded. During this phases statistics are
32 // gathered in a structure before being emitted as UMA metrics at the end of
33 // this phase. At this point the TabLoader ceases to exist and destroys it's
34 // reference to the SessionRestoreStatsCollector.
35 // 2. If any tabs have been deferred the SessionRestoreStatsCollector continues
36 // tracking deferred tabs. This continues to observe the tabs to see which
37 // (if any) of the deferred tabs are subsequently forced to be loaded by the
38 // user. Since such tabs may exist until the end of the browsers life the
39 // statistics are emitted immediately, or risk being lost entirely. When
40 // there are no longer deferred tabs to track the
41 // SessionRestoreStatsCollector will destroy itself.
43 // TODO(chrisha): Many of these metrics don't make sense to collect in the
44 // presence of an unavailable network, or when tabs are closed during loading.
45 // Rethink the collection in these cases.
46 class SessionRestoreStatsCollector
47 : public content::NotificationObserver,
48 public base::RefCounted<SessionRestoreStatsCollector> {
49 public:
50 // Houses all of the statistics gathered by the SessionRestoreStatsCollector
51 // while the underlying TabLoader is active. These statistics are all reported
52 // at once via the reporting delegate.
53 struct TabLoaderStats {
54 // Constructor that initializes everything to zero.
55 TabLoaderStats();
57 // The number of tabs involved in all overlapping session restores being
58 // tracked by this SessionRestoreStatsCollector. This corresponds to the
59 // "SessionRestore.TabCount" metric and one bucket of the
60 // "SessionRestore.TabActions" histogram. If any tabs were deferred it also
61 // corresponds to the "SessionRestore.TabCount.MemoryPressure.Total"
62 // histogram.
63 size_t tab_count;
65 // The number of restored tabs that were deferred. Corresponds to the
66 // "SessionRestore.TabCount.MemoryPressure.Deferred" histogram.
67 size_t tabs_deferred;
69 // The number of tabs whose loading was automatically started because they
70 // are active or explicitly caused to be loaded by the TabLoader. This
71 // corresponds to one bucket of the "SessionRestore.TabActions" histogram
72 // and the "SessionRestore.TabCount.MemoryPressure.LoadStarted".
73 size_t tabs_load_started;
75 // The number of tabs loaded automatically because they are active, or
76 // explicitly caused to be loaded by the TabLoader. This corresponds to one
77 // bucket of the "SessionRestore.TabActions" histogram, and the
78 // "SessionRestore.TabCount.MemoryPressure.Loaded" histogram.
79 size_t tabs_loaded;
81 // The time elapsed between |restore_started| and reception of the first
82 // NOTIFICATION_LOAD_STOP event for any of the active tabs involved in the
83 // session restore. If this is zero it is because it has not been
84 // recorded (all visible tabs were closed before they finished loading, or
85 // the user switched to an already loaded tab before a visible session
86 // restore tab finished loading). Corresponds to
87 // "SessionRestore.ForegroundTabFirstLoaded" and its _XX variants.
88 base::TimeDelta foreground_tab_first_loaded;
90 // The time elapsed between |restore_started| and reception of the first
91 // NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE event for any of
92 // the tabs involved in the session restore. If this is zero it is because
93 // it has not been recorded (all visible tabs were closed or switched away
94 // from before they were painted). Corresponds to
95 // "SessionRestore.ForegroundTabFirstPaint3" and its _XX variants.
96 base::TimeDelta foreground_tab_first_paint;
98 // The time taken for all non-deferred tabs to be loaded. This corresponds
99 // to the "SessionRestore.AllTabsLoaded" metric and its _XX variants
100 // (vaguely named for historical reasons, as it predates the concept of
101 // deferred tabs).
102 base::TimeDelta non_deferred_tabs_loaded;
104 // The maximum number of tabs loading in parallel. This corresponds to the
105 // "SessionRestore.ParallelTabLoads" metric.
106 size_t parallel_tab_loads;
109 // The StatsReportingDelegate is responsible for delivering statistics
110 // reported by the SessionRestoreStatsCollector.
111 class StatsReportingDelegate;
113 // An implementation of StatsReportingDelegate for reporting via UMA.
114 class UmaStatsReportingDelegate;
116 // Constructs a SessionRestoreStatsCollector.
117 SessionRestoreStatsCollector(
118 const base::TimeTicks& restore_started,
119 scoped_ptr<StatsReportingDelegate> reporting_delegate);
121 // Adds new tabs to the list of tracked tabs.
122 void TrackTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs);
124 // Called to indicate that the loading of a tab has been deferred by session
125 // restore.
126 void DeferTab(content::NavigationController* tab);
128 // Exposed for unittesting.
129 const TabLoaderStats& tab_loader_stats() const { return tab_loader_stats_; }
131 private:
132 friend class TestSessionRestoreStatsCollector;
133 friend class base::RefCounted<SessionRestoreStatsCollector>;
135 enum TabLoadingState { TAB_IS_NOT_LOADING, TAB_IS_LOADING, TAB_IS_LOADED };
137 // State that is tracked for a tab while it is being observed.
138 struct TabState {
139 explicit TabState(content::NavigationController* controller);
141 // The NavigationController associated with the tab. This is the primary
142 // index for it and is never null.
143 content::NavigationController* controller;
145 // Set to true if the tab has been deferred by the TabLoader.
146 bool is_deferred;
148 // The current loading state of the tab.
149 TabLoadingState loading_state;
152 // Maps a NavigationController to its state. This is the primary map and
153 // physically houses the state.
154 using NavigationControllerMap =
155 std::map<content::NavigationController*, TabState>;
157 ~SessionRestoreStatsCollector() override;
159 // NotificationObserver method. This is the workhorse of the class and drives
160 // all state transitions.
161 void Observe(int type,
162 const content::NotificationSource& source,
163 const content::NotificationDetails& details) override;
165 // Called when a tab is no longer tracked. This is called by the 'Observe'
166 // notification callback. Takes care of unregistering all observers and
167 // removing the tab from all internal data structures.
168 void RemoveTab(content::NavigationController* tab);
170 // Registers for relevant notifications for a tab and inserts the tab into
171 // to tabs_tracked_ map. Return a pointer to the newly created TabState.
172 TabState* RegisterForNotifications(content::NavigationController* tab);
174 // Returns the tab state, nullptr if not found.
175 TabState* GetTabState(content::NavigationController* tab);
176 TabState* GetTabState(content::RenderWidgetHost* tab);
178 // Marks a tab as loading.
179 void MarkTabAsLoading(TabState* tab_state);
181 // Checks to see if the SessionRestoreStatsCollector has finished collecting,
182 // and if so, releases the self reference to the shared pointer.
183 void ReleaseIfDoneTracking();
185 // Testing seam for configuring the tick clock in use.
186 void set_tick_clock(scoped_ptr<base::TickClock> tick_clock) {
187 tick_clock_ = tick_clock.Pass();
190 // Has ReleaseIfDoneTracking determined that there are no non-deferred tabs to
191 // track?
192 bool done_tracking_non_deferred_tabs_;
194 // Has the time for foreground tab load been recorded?
195 bool got_first_foreground_load_;
197 // Has the time for foreground tab paint been recorded?
198 bool got_first_paint_;
200 // The time the restore process started.
201 const base::TimeTicks restore_started_;
203 // List of tracked tabs, mapped to their TabState.
204 NavigationControllerMap tabs_tracked_;
206 // Counts the number of non-deferred tabs that the
207 // SessionRestoreStatsCollector is waiting to see load.
208 size_t waiting_for_load_tab_count_;
210 // Counts the current number of actively loading tabs.
211 size_t loading_tab_count_;
213 // Counts the current number of deferred tabs.
214 size_t deferred_tab_count_;
216 // Notification registrar.
217 content::NotificationRegistrar registrar_;
219 // Statistics gathered regarding the TabLoader.
220 TabLoaderStats tab_loader_stats_;
222 // The source of ticks used for taking timing information. This is
223 // configurable as a testing seam. Defaults to using base::DefaultTickClock,
224 // which in turn uses base::TimeTicks.
225 scoped_ptr<base::TickClock> tick_clock_;
227 // The reporting delegate used to report gathered statistics.
228 scoped_ptr<StatsReportingDelegate> reporting_delegate_;
230 // For keeping SessionRestoreStatsCollector alive while it is still working
231 // even if no TabLoader references it. The object only lives on if it still
232 // has deferred tabs remaining from an interrupted session restore.
233 scoped_refptr<SessionRestoreStatsCollector> this_retainer_;
235 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector);
238 // An abstract reporting delegate is used as a testing seam.
239 class SessionRestoreStatsCollector::StatsReportingDelegate {
240 public:
241 StatsReportingDelegate() {}
242 virtual ~StatsReportingDelegate() {}
244 // Called when TabLoader has completed its work.
245 virtual void ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) = 0;
247 // Called when a tab has been deferred.
248 virtual void ReportTabDeferred() = 0;
250 // Called when a deferred tab has been loaded.
251 virtual void ReportDeferredTabLoaded() = 0;
253 private:
254 DISALLOW_COPY_AND_ASSIGN(StatsReportingDelegate);
257 // The default reporting delegate, which reports statistics via UMA.
258 class SessionRestoreStatsCollector::UmaStatsReportingDelegate
259 : public StatsReportingDelegate {
260 public:
261 UmaStatsReportingDelegate();
262 ~UmaStatsReportingDelegate() override {}
264 // StatsReportingDelegate:
265 void ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) override;
266 void ReportTabDeferred() override;
267 void ReportDeferredTabLoaded() override;
269 private:
270 // Has ReportTabDeferred been called?
271 bool got_report_tab_deferred_;
273 DISALLOW_COPY_AND_ASSIGN(UmaStatsReportingDelegate);
276 #endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_