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 #ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ | 5 #ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ |
6 #define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ | 6 #define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ |
7 | 7 |
8 #include <set> | 8 #include <map> |
9 | 9 |
10 #include "base/callback_list.h" | 10 #include "base/callback_list.h" |
11 #include "chrome/browser/sessions/session_restore.h" | 11 #include "chrome/browser/sessions/session_restore.h" |
12 #include "chrome/browser/sessions/session_restore_delegate.h" | 12 #include "chrome/browser/sessions/session_restore_delegate.h" |
13 #include "content/public/browser/notification_observer.h" | 13 #include "content/public/browser/notification_observer.h" |
14 #include "content/public/browser/notification_registrar.h" | 14 #include "content/public/browser/notification_registrar.h" |
15 #include "content/public/browser/render_widget_host.h" | 15 #include "content/public/browser/render_widget_host.h" |
16 | 16 |
17 namespace content { | 17 namespace content { |
18 class NavigationController; | 18 class NavigationController; |
19 } | 19 } |
20 | 20 |
21 // SessionRestoreStatsCollector observes SessionRestore events ands records UMA | 21 // SessionRestoreStatsCollector observes SessionRestore events ands records UMA |
22 // accordingly. | 22 // accordingly. |
23 // | |
24 // A SessionRestoreStatsCollector is tied to an instance of a session restore, | |
25 // currently being instantianted and owned by the TabLoader. It has two main | |
26 // phases to its life: | |
27 // | |
28 // 1. The session restore is active and ongoing (the TabLoader is still | |
29 // scheduling tabs for loading). This phases ends when there are no | |
30 // non-deferred tabs left to be loaded. During this phases statistics are | |
31 // gathered in a structure before being emitted as UMA metrics at the end of | |
32 // this phase. At this point the TabLoader ceases to exist and destroys it's | |
33 // reference to the SessionRestoreStatsCollector. | |
34 // 2. If any tabs have been deferred the SessionRestoreStatsCollector continues | |
35 // tracking deferred tabs. This continues to observe the tabs to see which | |
36 // (if any) of the deferred tabs are subsequently forced to be loaded by the | |
37 // user. Since such tabs may exist until the end of the browsers life the | |
38 // statistics are emitted immediately, or risk being lost entirely. When | |
39 // there are no longer deferred tabs to track the | |
40 // SessionRestoreStatsCollector will destroy itself. | |
41 // | |
42 // TODO(chrisha): Many of these metrics don't make sense to collect in the | |
43 // presence of an unavailable network, or when tabs are closed during loading. | |
44 // Rethink the collection in these cases. | |
23 class SessionRestoreStatsCollector | 45 class SessionRestoreStatsCollector |
24 : public content::NotificationObserver, | 46 : public content::NotificationObserver, |
25 public base::RefCounted<SessionRestoreStatsCollector> { | 47 public base::RefCounted<SessionRestoreStatsCollector> { |
26 public: | 48 public: |
27 // Called to start tracking tabs. If a restore is already occuring, the tabs | 49 // Houses all of the statistics gathered by the SessionRestoreStatsCollector |
28 // are added to the existing list of tracked tabs. | 50 // while the underlying TabLoader is active. These statistics are all reported |
29 static void TrackTabs( | 51 // at once via ReportTabLoaderStats. |
30 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, | 52 struct TabLoaderStats { |
31 const base::TimeTicks& restore_started); | 53 // Constructor that initializes everything to zero. |
32 | 54 TabLoaderStats(); |
33 // Called to start tracking only active tabs. If a restore is already | 55 |
34 // occuring, the tabs are added to the existing list of tracked tabs. | 56 // The number of tabs involved in the session restore. This corresponds to |
sky
2015/05/27 15:18:39
Using 'the session restore' is confusing here as t
chrisha
2015/06/03 21:16:36
Done.
| |
35 static void TrackActiveTabs( | 57 // the "SessionRestore.TabCount" metric and one bucket of the |
36 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, | 58 // "SessionRestore.TabActions" histogram. |
37 const base::TimeTicks& restore_started); | 59 size_t tab_count; |
60 | |
61 // The number of tabs automatically loaded by the TabLoader. This | |
sky
2015/05/27 15:18:40
It's not clear what automatically loaded means her
chrisha
2015/06/03 21:16:36
Done.
| |
62 // corresponds to one bucket of the "SessionRestore.TabActions" histogram. | |
63 size_t tabs_loaded; | |
64 | |
65 // The time taken to load the first foreground tab. If this is zero it is | |
sky
2015/05/27 15:18:40
Clarify what this is relative to and what 'load' c
chrisha
2015/06/03 21:16:36
Done.
| |
66 // because it has not been recorded (tab was closed before loading). | |
67 // Corresponds to "SessionRestore.ForegroundTabFirstLoaded" and its _XX | |
68 // variants. | |
69 base::TimeDelta foreground_tab_first_loaded; | |
70 | |
71 // The time taken to paint the first foreground tab. If this is zero it is | |
sky
2015/05/27 15:18:40
Same comment about what this is relative to. It's
chrisha
2015/06/03 21:16:36
Done.
| |
72 // because it has not been recorded (tab was closed before painting or user | |
73 // switched to another tab). Corresponds to | |
74 // "SessionRestore.ForegroundTabFirstPaint" and | |
75 // "SessionRestore.ForegroundTabFirstPaint2" metrics and their _XX variants. | |
76 base::TimeDelta foreground_tab_first_paint; | |
77 | |
78 // The time taken for all non-deferred tabs to be loaded. This corresponds | |
79 // to the "SessionRestore.AllTabsLoaded" metric and its _XX variants. | |
80 base::TimeDelta all_tabs_loaded; | |
sky
2015/05/27 15:18:40
all is too overloaded here. Maybe time_to_non_defe
chrisha
2015/06/03 21:16:36
Done.
| |
81 | |
82 // The maximum number of tabs loading in parallel. This corresponds to the | |
83 // "SessionRestore.ParallelTabLoads" metric. | |
84 size_t parallel_tab_loads; | |
85 }; | |
86 | |
87 explicit SessionRestoreStatsCollector(const base::TimeTicks& restore_started); | |
88 | |
89 // Adds new tabs to the list of tracked tabs. | |
90 void TrackTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs); | |
91 | |
92 // Called to indicate that the loading of a tab has been deferred by session | |
93 // restore. | |
94 void DeferTab(content::NavigationController* tab); | |
95 | |
96 // Exposed for unittesting. | |
97 const TabLoaderStats& tab_loader_stats() const { return tab_loader_stats_; } | |
98 | |
99 protected: | |
100 // Reporting functions that cause actual UMA metrics to be emitted. Exposed as | |
101 // a unittesting seams. | |
102 virtual void ReportTabLoaderStats(); | |
sky
2015/05/27 15:18:40
I would prefer a delegate rather than subclassing.
chrisha
2015/06/03 21:16:36
Done.
| |
103 virtual void ReportTabDeferred(); | |
104 virtual void ReportDeferredTabLoaded(); | |
38 | 105 |
39 private: | 106 private: |
40 friend class base::RefCounted<SessionRestoreStatsCollector>; | 107 friend class base::RefCounted<SessionRestoreStatsCollector>; |
41 | 108 |
42 using RenderWidgetHostSet = std::set<content::RenderWidgetHost*>; | 109 // Indicates whether the loading state of a tab. |
43 | 110 enum TabLoadingState { |
44 explicit SessionRestoreStatsCollector(const base::TimeTicks& restore_started); | 111 TAB_IS_NOT_LOADING, |
112 TAB_IS_LOADING, | |
113 TAB_IS_LOADED | |
114 }; | |
115 | |
116 // State that is tracked for a tab while it is being observed. | |
117 struct TabState { | |
118 TabState(content::NavigationController* controller); | |
sky
2015/05/27 15:18:40
explicit
chrisha
2015/06/03 21:16:37
Done.
| |
119 | |
120 // The NavigationController associated with the tab. This is the primary | |
121 // index for it and is never null. | |
122 content::NavigationController* controller; | |
123 | |
124 // The RenderWidgetHost associated with the tab. This is the secondary | |
125 // index and starts out being null. If it is not null it is because the tab | |
126 // is actively loading or waiting to be painted. | |
127 content::RenderWidgetHost* render_widget_host; | |
128 | |
129 // Set to true if the tab has been deferred by the TabLoader. | |
130 bool is_deferred; | |
131 | |
132 // The current loading state of the tab. | |
133 TabLoadingState loading_state; | |
134 }; | |
135 | |
136 // Maps a NavigationController to its state. This is the primary map and | |
137 // physically houses the state. | |
138 using NavigationControllerMap = std::map<content::NavigationController*, | |
139 TabState>; | |
140 | |
141 // Maps a RenderWidgetHost to its state. This is a secondary index and maps | |
142 // the tab to a pointer to its state housed in the primary map. | |
143 using RenderWidgetHostMap = std::map<content::RenderWidgetHost*, TabState*>; | |
144 | |
45 ~SessionRestoreStatsCollector() override; | 145 ~SessionRestoreStatsCollector() override; |
46 | 146 |
47 // NotificationObserver method. | 147 // NotificationObserver method. This is the workhorse of the class and drives |
148 // all state transitions. | |
48 void Observe(int type, | 149 void Observe(int type, |
49 const content::NotificationSource& source, | 150 const content::NotificationSource& source, |
50 const content::NotificationDetails& details) override; | 151 const content::NotificationDetails& details) override; |
51 | 152 |
52 // Adds new tabs to the list of tracked tabs. | 153 // Called when a tab is no longer tracked. This is called by the 'Observe' |
53 void AddTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs); | 154 // notification callback. Takes care of unregistering all observers and |
54 | 155 // removing the tab from all internal data structures. |
55 // Called when a tab is no longer tracked. | |
56 void RemoveTab(content::NavigationController* tab); | 156 void RemoveTab(content::NavigationController* tab); |
57 | 157 |
58 // Registers for relevant notifications for a tab. | 158 // Registers for relevant notifications for a tab and inserts the tab into |
59 void RegisterForNotifications(content::NavigationController* tab); | 159 // to tabs_tracked_ map. Return a pointer to the newly created TabState. |
160 TabState* RegisterForNotifications(content::NavigationController* tab); | |
60 | 161 |
61 // Returns the RenderWidgetHost of a tab. | 162 // Returns the RenderWidgetHost of a tab. |
62 content::RenderWidgetHost* GetRenderWidgetHost( | 163 content::RenderWidgetHost* GetRenderWidgetHost( |
63 content::NavigationController* tab); | 164 content::NavigationController* tab); |
64 | 165 |
65 // Have we recorded the times for a foreground tab load? | 166 // Returns the tab state, nullptr if not found. |
167 TabState* GetTabState(content::NavigationController* tab); | |
168 TabState* GetTabState(content::RenderWidgetHost* tab); | |
169 | |
170 // Marks a tab as loading. | |
171 void MarkTabAsLoading(TabState* tab_state); | |
172 | |
173 // Returns true if done tracking non-deferred tabs. When this returns true | |
174 // the TabLoader will have finished its work and aggregate statistics will be | |
175 // emitted via Record | |
176 bool DoneTrackingNonDeferredTabs() const; | |
177 | |
178 // Returns true when no longer tracking any tabs. When this returns true the | |
179 // collector will destory itself. Called from Observe. | |
180 bool DoneTracking() const; | |
181 | |
182 // Has DoneTrackingNonDeferredTabs returned true? | |
183 bool got_done_tracking_non_deferred_tabs_; | |
184 | |
185 // Has the time for foreground tab load been recorded? | |
66 bool got_first_foreground_load_; | 186 bool got_first_foreground_load_; |
67 | 187 |
68 // Have we recorded the times for a foreground tab paint? | 188 // Has the time for foreground tab paint been recorded? |
69 bool got_first_paint_; | 189 bool got_first_paint_; |
70 | 190 |
191 // Has ReportTabDeferred been called? | |
192 bool got_report_tab_deferred_; | |
193 | |
71 // The time the restore process started. | 194 // The time the restore process started. |
72 base::TimeTicks restore_started_; | 195 base::TimeTicks restore_started_; |
sky
2015/05/27 15:18:39
const
chrisha
2015/06/03 21:16:36
Done.
| |
73 | 196 |
74 // The renderers we have started loading into. | 197 // List of tracked tabs, mapped to their TabState. |
75 RenderWidgetHostSet render_widget_hosts_loading_; | 198 NavigationControllerMap tabs_tracked_; |
76 | 199 |
77 // The renderers we have loaded and are waiting on to paint. | 200 // A secondary index of TabState by their RenderWidgetHosts. |
78 RenderWidgetHostSet render_widget_hosts_to_paint_; | 201 RenderWidgetHostMap render_widget_map_; |
79 | 202 |
80 // List of tracked tabs. | 203 // Counts the number of non-deferred tabs that the |
81 std::set<content::NavigationController*> tabs_tracked_; | 204 // SessionRestoreStatsCollector is waiting to see load. |
82 | 205 size_t waiting_for_load_tab_count_; |
83 // The number of tabs that have been restored. | 206 |
84 int tab_count_; | 207 // Counts the current number of actively loading tabs. |
85 | 208 size_t loading_tab_count_; |
86 // Max number of tabs that were loaded in parallel (for metrics). | |
87 size_t max_parallel_tab_loads_; | |
88 | 209 |
89 // Notification registrar. | 210 // Notification registrar. |
90 content::NotificationRegistrar registrar_; | 211 content::NotificationRegistrar registrar_; |
91 | 212 |
92 // To keep the collector alive as long as needed. | 213 // Statistics gathered regarding the TabLoader. |
214 TabLoaderStats tab_loader_stats_; | |
215 | |
216 // For keeping SessionRestoreStatsCollector alive while it is still working | |
217 // even if no TabLoader references it. The object only lives on if it still | |
218 // has deferred tabs remaining from an interrupted session restore. | |
93 scoped_refptr<SessionRestoreStatsCollector> this_retainer_; | 219 scoped_refptr<SessionRestoreStatsCollector> this_retainer_; |
94 | 220 |
95 // The shared SessionRestoreNotifier instance for all SessionRestores running | |
96 // at this time. | |
97 static SessionRestoreStatsCollector* shared_collector_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector); | 221 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector); |
100 }; | 222 }; |
101 | 223 |
102 #endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ | 224 #endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ |
OLD | NEW |