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

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

Issue 2335203003: Add metrics to keep track of the tab activate/deactivate cycle (Closed)
Patch Set: Created 4 years, 3 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
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
chrisha 2016/09/14 09:57:39 2016?
Patrick Monette 2016/09/16 00:14:00 Done.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/metrics/tab_usage_recorder.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_list.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/web_contents_user_data.h"
15
16 namespace metrics {
17
18 namespace {
19
20 void RecordTabDeactivation(bool is_pinned) {
21 if (is_pinned)
22 UMA_HISTOGRAM_COUNTS("Tab.DeactivationCount.Pinned", 1);
23 else
24 UMA_HISTOGRAM_COUNTS("Tab.DeactivationCount", 1);
chrisha 2016/09/14 09:57:39 Always record this, and then have a separate speci
Patrick Monette 2016/09/16 00:14:00 I added a histogram suffix to get the best of both
25 }
26
27 void RecordTabReactivation(bool is_pinned) {
28 if (is_pinned)
29 UMA_HISTOGRAM_COUNTS("Tab.ReactivationCount.Pinned", 1);
30 else
31 UMA_HISTOGRAM_COUNTS("Tab.ReactivationCount", 1);
32 }
33
34 // This class is used to track the activation/deactivation cycle per
35 // WebContents. It also keep tracks of the pinned state of the tab.
Georges Khalil 2016/09/14 16:10:16 nit: s/keep tracks/keeps track.
Patrick Monette 2016/09/16 00:14:00 Done.
36 class WebContentsData : public content::WebContentsUserData<WebContentsData> {
Georges Khalil 2016/09/14 16:10:16 Make this internal to TabUsageRecorder.
Patrick Monette 2016/09/16 00:14:00 Done.
37 public:
38 static void CreateForWebContents(content::WebContents* contents,
39 bool is_pinned);
40
41 ~WebContentsData() override;
42
43 void OnTabActivating();
44 void OnTabDeactivating();
45 void OnTabClosing();
46 void OnTabPinnedStateChanging(bool is_pinned);
47
48 private:
49 friend class content::WebContentsUserData<WebContentsData>;
50
51 explicit WebContentsData(content::WebContents* contents, bool is_pinned);
52
53 // Indicates if the tab is pinned to the tab strip.
54 bool is_pinned_;
55
56 // Indicates if the tab has been deactivated before as to only count
57 // reactivations.
58 bool was_deactivated_once_;
59
60 // The deactivation metric is not recorded for closing tabs.
61 bool is_closing_;
Georges Khalil 2016/09/14 16:10:17 Disallow copy.
Patrick Monette 2016/09/16 00:14:00 Done.
62 };
63
64 // static
65 void WebContentsData::CreateForWebContents(content::WebContents* contents,
66 bool is_pinned) {
67 DCHECK(contents);
68 if (FromWebContents(contents))
69 return;
70
71 contents->SetUserData(UserDataKey(),
72 new WebContentsData(contents, is_pinned));
Georges Khalil 2016/09/14 16:10:16 Use DEFINE_WEB_CONTENTS_USER_DATA_KEY so you don't
Patrick Monette 2016/09/16 00:13:59 DEFINE_WEB_CONTENTS_USER_DATA_KEY is already used
Georges Khalil 2016/09/16 18:58:35 I missed DEFINE_WEB_CONTENTS_USER_DATA_KEY at the
Patrick Monette 2016/09/19 17:47:12 I addressed the confusing expectation. The change
73 }
74
75 WebContentsData::~WebContentsData() = default;
76
77 void WebContentsData::OnTabActivating() {
78 if (was_deactivated_once_) {
79 RecordTabReactivation(is_pinned_);
80 }
81 }
82
83 void WebContentsData::OnTabDeactivating() {
84 was_deactivated_once_ = true;
85 if (!is_closing_)
86 RecordTabDeactivation(is_pinned_);
87 }
88
89 void WebContentsData::OnTabClosing() {
90 is_closing_ = true;
91 }
92
93 void WebContentsData::OnTabPinnedStateChanging(bool is_pinned) {
94 is_pinned_ = is_pinned;
95 }
96
97 WebContentsData::WebContentsData(content::WebContents* contents, bool is_pinned)
98 : // content::WebContentsObserver(contents),
Georges Khalil 2016/09/14 16:10:16 nit: remove.
Patrick Monette 2016/09/16 00:13:59 Done.
99 is_pinned_(is_pinned),
100 was_deactivated_once_(false),
101 is_closing_(false) {}
102
103 } // namespace
104
105 // This class is used to keep track of which browser owns the tab strip model.
106 // The browser is necessary to check for the pinned state of the tab
107 // in an efficient manner.
108 class TabUsageRecorder::TabStripObserver : public TabStripModelObserver {
109 public:
110 explicit TabStripObserver(Browser* browser);
111 ~TabStripObserver();
112
113 // TabStripModelObserver:
114 void TabInsertedAt(content::WebContents* contents,
115 int index,
116 bool foreground) override;
117 void TabClosingAt(TabStripModel* tab_strip_model,
118 content::WebContents* contents,
119 int index) override;
120 void ActiveTabChanged(content::WebContents* old_contents,
121 content::WebContents* new_contents,
122 int index,
123 int reason) override;
124 void TabPinnedStateChanged(content::WebContents* contents,
125 int index) override;
126
127 private:
128 Browser* browser_;
Georges Khalil 2016/09/14 16:10:16 Disallow copy.
Patrick Monette 2016/09/16 00:14:00 Removed the class.
129 };
130
131 TabUsageRecorder::TabStripObserver::TabStripObserver(Browser* browser)
132 : browser_(browser) {
133 // Process tabs that are already open.
134 TabStripModel* tab_strip_model = browser_->tab_strip_model();
135 int active_index = tab_strip_model->active_index();
136 for (int i = 0; i < tab_strip_model->count(); ++i) {
Georges Khalil 2016/09/14 16:10:16 nit: no braces.
Patrick Monette 2016/09/16 00:14:00 Removed this class.
137 TabInsertedAt(tab_strip_model->GetWebContentsAt(i), i, i == active_index);
138 }
139
140 browser_->tab_strip_model()->AddObserver(this);
141 }
142
143 TabUsageRecorder::TabStripObserver::~TabStripObserver() {
144 browser_->tab_strip_model()->RemoveObserver(this);
145 }
146
147 void TabUsageRecorder::TabStripObserver::TabInsertedAt(
148 content::WebContents* contents,
149 int index,
150 bool foreground) {
151 WebContentsData::CreateForWebContents(
152 contents, browser_->tab_strip_model()->IsTabPinned(index));
153 }
154
155 void TabUsageRecorder::TabStripObserver::TabClosingAt(
156 TabStripModel* tab_strip_model,
157 content::WebContents* contents,
158 int index) {
159 WebContentsData::FromWebContents(contents)->OnTabClosing();
160 }
161
162 void TabUsageRecorder::TabStripObserver::ActiveTabChanged(
163 content::WebContents* old_contents,
164 content::WebContents* new_contents,
165 int index,
166 int reason) {
167 if (old_contents) {
168 WebContentsData::FromWebContents(old_contents)->OnTabDeactivating();
169 }
170 WebContentsData::FromWebContents(new_contents)->OnTabActivating();
171 }
172
173 void TabUsageRecorder::TabStripObserver::TabPinnedStateChanged(
174 content::WebContents* contents,
175 int index) {
176 WebContentsData::FromWebContents(contents)->OnTabPinnedStateChanging(
177 browser_->tab_strip_model()->IsTabPinned(index));
178 }
179
180 // static
181 void TabUsageRecorder::Initialize() {
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
183 static TabUsageRecorder* tab_usage_metrics = new TabUsageRecorder();
Georges Khalil 2016/09/14 16:10:17 This should be global and its lifetime well docume
Patrick Monette 2016/09/16 00:13:59 Done.
184 }
185
186 TabUsageRecorder::TabUsageRecorder() {
187 for (Browser* browser : *BrowserList::GetInstance()) {
Georges Khalil 2016/09/14 16:10:16 nit: no braces.
Patrick Monette 2016/09/16 00:13:59 Done.
188 OnBrowserAdded(browser);
189 }
190 BrowserList::GetInstance()->AddObserver(this);
191 }
192
193 TabUsageRecorder::~TabUsageRecorder() = default;
194
195 void TabUsageRecorder::OnBrowserAdded(Browser* browser) {
196 tab_strip_observer_map_.emplace(browser,
197 base::MakeUnique<TabStripObserver>(browser));
198 }
199
200 void TabUsageRecorder::OnBrowserRemoved(Browser* browser) {
201 tab_strip_observer_map_.erase(browser);
202 }
203
204 } // namespace metrics
205
206 DEFINE_WEB_CONTENTS_USER_DATA_KEY(metrics::WebContentsData);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698