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

Unified Diff: chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc

Issue 1277843002: [WillSplitBeforeLand] Add UMAs to measure how user interacts with tabs Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: tzik review/rebase Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
diff --git a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9dad9864109575bcb73eb5fc603eb902519e73c3
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
@@ -0,0 +1,271 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/tab_strip_model_stats_recorder.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+
+namespace chrome {
+
+TabStripModelStatsRecorder::TabStripModelStatsRecorder() {
+ BrowserList::AddObserver(this);
+}
+
+TabStripModelStatsRecorder::~TabStripModelStatsRecorder() {
+ BrowserList::RemoveObserver(this);
+}
+
+void TabStripModelStatsRecorder::OnBrowserAdded(Browser* browser) {
+ browser->tab_strip_model()->AddObserver(this);
+}
+
+void TabStripModelStatsRecorder::OnBrowserRemoved(Browser* browser) {
+ browser->tab_strip_model()->RemoveObserver(this);
+}
+
+using TabState = TabStripModelStatsRecorder::TabInfo::State;
+
+void TabStripModelStatsRecorder::TabInfo::UpdateState(TabState new_state) {
+ if (new_state == current_state_) {
+ return;
+ }
+
+ base::Time now = base::Time::Now();
+ base::TimeDelta delta = now - last_state_modified_;
+
+ switch (current_state_) {
+ case TabState::INITIAL:
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransferTarget.Initial",
+ static_cast<int>(new_state),
+ static_cast<int>(TabState::MAX));
+ break;
+ case TabState::ACTIVE:
+ switch (new_state) {
+ case TabState::INITIAL:
+ case TabState::ACTIVE:
+ case TabState::MAX:
+ NOTREACHED();
+ break;
+ case TabState::INACTIVE:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Active.Inactive",
+ delta);
+ break;
+ case TabState::DETACHED:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Active.Detached",
+ delta);
+ break;
+ case TabState::CLOSED:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Active.Closed",
+ delta);
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransferTarget.Active",
+ static_cast<int>(new_state),
+ static_cast<int>(TabState::MAX));
+ break;
+ case TabState::INACTIVE:
+ switch (new_state) {
+ case TabState::INITIAL:
+ case TabState::INACTIVE:
+ case TabState::MAX:
+ NOTREACHED();
+ break;
+ case TabState::ACTIVE:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Inactive.Active",
+ delta);
+ break;
+ case TabState::DETACHED:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Inactive.Detached",
+ delta);
+ break;
+ case TabState::CLOSED:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Inactive.Closed",
+ delta);
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransferTarget.Inactive",
+ static_cast<int>(new_state),
+ static_cast<int>(TabState::MAX));
+ break;
+ case TabState::DETACHED:
+ switch (new_state) {
+ case TabState::INITIAL:
+ case TabState::DETACHED:
+ case TabState::MAX:
+ NOTREACHED();
+ break;
+ case TabState::ACTIVE:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Detached.Active",
+ delta);
+ break;
+ case TabState::INACTIVE:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Detached.Inactive",
+ delta);
+ break;
+ case TabState::CLOSED:
+ UMA_HISTOGRAM_LONG_TIMES_100("TabStateTransferTime.Detached.Closed",
+ delta);
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransferTarget.Detached",
+ static_cast<int>(new_state),
+ static_cast<int>(TabState::MAX));
+ break;
+ case TabState::CLOSED:
+ case TabState::MAX:
+ NOTREACHED();
+ break;
+ }
+ last_state_modified_ = now;
+ current_state_ = new_state;
+}
+
+void TabStripModelStatsRecorder::TabInsertedAt(content::WebContents* contents,
+ int index,
+ bool foreground) {
+ tab_info_map_[contents].UpdateState(foreground ? TabState::ACTIVE
+ : TabState::INACTIVE);
+}
+
+void TabStripModelStatsRecorder::TabClosingAt(TabStripModel*,
+ content::WebContents* contents,
+ int index) {
+ auto it = tab_info_map_.find(contents);
+ if (it == tab_info_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ auto& info = it->second;
+ info.UpdateState(TabState::CLOSED);
+ tab_info_map_.erase(it);
+
+ for (auto it = active_tab_history_.begin(); it != active_tab_history_.end();
+ ++it) {
+ if (*it == contents) {
+ active_tab_history_.erase(it);
+ break;
+ }
+ }
+}
+
+void TabStripModelStatsRecorder::TabDetachedAt(content::WebContents* contents,
+ int index) {
+ auto it = tab_info_map_.find(contents);
+ if (it == tab_info_map_.end()) {
+ return;
+ }
+
+ auto& info = it->second;
+ info.UpdateState(TabState::DETACHED);
+}
+
+void TabStripModelStatsRecorder::ActiveTabChanged(
+ content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) {
+ if (reason & TabStripModelObserver::CHANGE_REASON_REPLACED) {
+ // We already handled tab clobber at TabReplacedAt notification.
+ return;
+ }
+
+ if (old_contents) {
+ auto it = tab_info_map_.find(old_contents);
+ if (it == tab_info_map_.end()) {
+ // The old tab already closed.
+ return;
+ }
+ auto& old_tab_info = it->second;
+ old_tab_info.UpdateState(TabState::INACTIVE);
+ }
+
+ DCHECK(new_contents);
+ auto it = tab_info_map_.find(new_contents);
+ if (it == tab_info_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ auto& tab_info = it->second;
+
+ bool was_inactive = tab_info.state() == TabState::INACTIVE;
+ tab_info.UpdateState(TabState::ACTIVE);
+
+ int distance = last_active_index_ - index;
+ last_active_index_ = index;
+
+ if (was_inactive) {
+ // We offset and clamp the |distance| by MAX_DIST, as UMA enum only supports
+ // positive bounded int.
+ const int MAX_DIST = 50;
+ int encoded_dist = distance + MAX_DIST;
+ encoded_dist = std::max(std::min(encoded_dist, MAX_DIST * 2), 0);
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransfer.TabDistanceInactiveToActive",
+ encoded_dist, MAX_DIST * 2);
+ }
+
+ const int MAX_AGE = 64;
+ int age = 1;
+ for (auto it = active_tab_history_.begin();;) {
+ if (it == active_tab_history_.end()) {
+ // If the active tab was never active before, record it as 0.
+ // This can happen if the tab was created in the background.
+ if (was_inactive) {
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransfer.TabAgeInactiveToActive", 0,
+ MAX_AGE);
+ }
+ break;
+ }
+
+ if (*it == new_contents) {
+ active_tab_history_.erase(it);
+
+ if (was_inactive) {
+ UMA_HISTOGRAM_ENUMERATION("TabStateTransfer.TabAgeInactiveToActive",
+ std::min(age, MAX_AGE), MAX_AGE);
+ }
+ break;
+ }
+
+ ++age;
+ ++it;
+ }
+ active_tab_history_.push_front(new_contents);
+}
+
+void TabStripModelStatsRecorder::TabReplacedAt(
+ TabStripModel* tab_strip_model,
+ content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index) {
+ DCHECK(old_contents != new_contents);
+
+ auto it = tab_info_map_.find(old_contents);
+ if (it == tab_info_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ auto& tab_info = it->second;
+ tab_info_map_.insert(std::make_pair(new_contents, tab_info));
+ tab_info_map_.erase(it);
+
+ for (auto it = active_tab_history_.begin(); it != active_tab_history_.end();
+ ++it) {
+ if (*it == old_contents) {
+ *it = new_contents;
+ break;
+ }
+ }
+}
+
+} // namespace chrome
« no previous file with comments | « chrome/browser/ui/tabs/tab_strip_model_stats_recorder.h ('k') | chrome/browser/ui/uma_browsing_activity_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698