Chromium Code Reviews| Index: chrome/browser/metrics/tab_usage_recorder.cc |
| diff --git a/chrome/browser/metrics/tab_usage_recorder.cc b/chrome/browser/metrics/tab_usage_recorder.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d5f08e3cb443b0a862c508d76b9802e2077d9b87 |
| --- /dev/null |
| +++ b/chrome/browser/metrics/tab_usage_recorder.cc |
| @@ -0,0 +1,165 @@ |
| +// Copyright 2016 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/metrics/tab_usage_recorder.h" |
| + |
| +#include "base/metrics/histogram_macros.h" |
| +#include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "components/bookmarks/browser/bookmark_model.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/web_contents_user_data.h" |
| +#include "content/public/common/page_importance_signals.h" |
| + |
| +DEFINE_WEB_CONTENTS_USER_DATA_KEY(metrics::TabUsageRecorder::WebContentsData); |
| + |
| +namespace metrics { |
| + |
| +namespace { |
| + |
| +// This global is never freed. |
| +TabUsageRecorder* g_tab_usage_recorder = nullptr; |
| + |
| +} // namespace |
| + |
| +// This class is used to track the activation/deactivation cycle per |
| +// WebContents. It also keeps track of the pinned state of the tab. |
| +class TabUsageRecorder::WebContentsData |
| + : public content::WebContentsUserData<WebContentsData> { |
| + public: |
| + ~WebContentsData() override; |
| + |
| + void OnTabActivating(); |
| + void OnTabDeactivating(); |
| + void OnTabClosing(); |
| + void OnTabPinnedStateChanging(bool is_pinned); |
| + |
| + private: |
| + friend class content::WebContentsUserData<WebContentsData>; |
| + |
| + explicit WebContentsData(content::WebContents* contents); |
| + |
| + // Returns true if |contents_|'s URL is bookmarked. |
| + bool IsBookmarked(); |
| + |
| + void RecordTabDeactivation(); |
| + void RecordTabReactivation(); |
| + |
| + // The WebContents associated to this instance. |
| + content::WebContents* contents_; |
| + |
| + // Indicates if the tab is pinned to the tab strip. |
| + bool is_pinned_; |
| + |
| + // Indicates if the tab has been deactivated before as to only count |
| + // reactivations. |
| + bool was_deactivated_once_; |
| + |
| + // The deactivation metric is not recorded for closing tabs. |
| + bool is_closing_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebContentsData); |
| +}; |
| + |
| +TabUsageRecorder::WebContentsData::~WebContentsData() = default; |
| + |
| +void TabUsageRecorder::WebContentsData::OnTabActivating() { |
| + if (was_deactivated_once_) |
| + RecordTabReactivation(); |
| +} |
| + |
| +void TabUsageRecorder::WebContentsData::OnTabDeactivating() { |
| + was_deactivated_once_ = true; |
| + if (!is_closing_) |
| + RecordTabDeactivation(); |
| +} |
| + |
| +void TabUsageRecorder::WebContentsData::OnTabClosing() { |
| + is_closing_ = true; |
| +} |
| + |
| +void TabUsageRecorder::WebContentsData::OnTabPinnedStateChanging( |
| + bool is_pinned) { |
| + is_pinned_ = is_pinned; |
| +} |
| + |
| +TabUsageRecorder::WebContentsData::WebContentsData( |
| + content::WebContents* contents) |
| + : contents_(contents), |
| + is_pinned_(false), |
| + was_deactivated_once_(false), |
| + is_closing_(false) {} |
| + |
| +bool TabUsageRecorder::WebContentsData::IsBookmarked() { |
| + bookmarks::BookmarkModel* bookmark_model = |
| + BookmarkModelFactory::GetForBrowserContextIfExists( |
| + contents_->GetBrowserContext()); |
| + |
| + return bookmark_model && |
| + bookmark_model->IsBookmarked(contents_->GetLastCommittedURL()); |
| +} |
| + |
| +void TabUsageRecorder::WebContentsData::RecordTabDeactivation() { |
| + UMA_HISTOGRAM_BOOLEAN("Tab.Deactivation.Pinned", is_pinned_); |
| + UMA_HISTOGRAM_BOOLEAN( |
| + "Tab.Deactivation.HadFormInteraction", |
| + contents_->GetPageImportanceSignals().had_form_interaction); |
| + UMA_HISTOGRAM_BOOLEAN("Tab.Deactivation.Bookmarked", IsBookmarked()); |
| +} |
| + |
| +void TabUsageRecorder::WebContentsData::RecordTabReactivation() { |
| + UMA_HISTOGRAM_BOOLEAN("Tab.Reactivation.Pinned", is_pinned_); |
| + UMA_HISTOGRAM_BOOLEAN( |
| + "Tab.Reactivation.HadFormInteraction", |
| + contents_->GetPageImportanceSignals().had_form_interaction); |
| + UMA_HISTOGRAM_BOOLEAN("Tab.Reactivation.Bookmarked", IsBookmarked()); |
| +} |
| + |
| +// static |
| +void TabUsageRecorder::Initialize() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + DCHECK(!g_tab_usage_recorder); |
| + g_tab_usage_recorder = new TabUsageRecorder(); |
| +} |
| + |
| +void TabUsageRecorder::TabInsertedAt(TabStripModel* tab_strip_model, |
| + content::WebContents* contents, |
| + int index, |
| + bool foreground) { |
| + WebContentsData::CreateForWebContents(contents); |
|
Georges Khalil
2016/09/20 21:36:31
I think we can have news WebContentses that don't
Patrick Monette
2016/09/21 21:03:18
Done.
|
| + // Set the initial pinned value. |
| + TabPinnedStateChanged(tab_strip_model, contents, index); |
| +} |
| + |
| +void TabUsageRecorder::TabClosingAt(TabStripModel* tab_strip_model, |
| + content::WebContents* contents, |
| + int index) { |
| + WebContentsData::FromWebContents(contents)->OnTabClosing(); |
| +} |
| + |
| +void TabUsageRecorder::ActiveTabChanged(content::WebContents* old_contents, |
| + content::WebContents* new_contents, |
| + int index, |
| + int reason) { |
| + if (old_contents) |
| + WebContentsData::FromWebContents(old_contents)->OnTabDeactivating(); |
| + WebContentsData::FromWebContents(new_contents)->OnTabActivating(); |
| +} |
| + |
| +void TabUsageRecorder::TabPinnedStateChanged(TabStripModel* tab_strip_model, |
| + content::WebContents* contents, |
| + int index) { |
| + WebContentsData::FromWebContents(contents)->OnTabPinnedStateChanging( |
| + tab_strip_model->IsTabPinned(index)); |
| +} |
| + |
| +TabUsageRecorder::TabUsageRecorder() |
| + : browser_tab_strip_tracker_(this, nullptr, nullptr) { |
| + browser_tab_strip_tracker_.Init( |
| + BrowserTabStripTracker::InitWith::ALL_BROWERS); |
| +} |
| + |
| +TabUsageRecorder::~TabUsageRecorder() = default; |
| + |
| +} // namespace metrics |