blob: 630dfd53bc217fd4492697d3b85be33b72c2f7cb [file] [log] [blame]
// Copyright 2017 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.
#ifndef CHROME_BROWSER_METRICS_TAB_STATS_DATA_STORE_H_
#define CHROME_BROWSER_METRICS_TAB_STATS_DATA_STORE_H_
#include <memory>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
class PrefService;
namespace content {
class WebContents;
} // namespace content
namespace metrics {
FORWARD_DECLARE_TEST(TabStatsTrackerBrowserTest,
TabDeletionGetsHandledProperly);
// The data store that keeps track of all the information that the
// TabStatsTracker wants to track.
class TabStatsDataStore {
public:
// Houses all of the statistics gathered by the TabStatsTracker.
struct TabsStats {
// Constructor, initializes everything to zero.
TabsStats();
// The total number of tabs opened across all the windows.
size_t total_tab_count;
// The maximum total number of tabs that has been opened across all the
// windows at the same time.
size_t total_tab_count_max;
// The maximum total number of tabs that has been opened at the same time in
// a single window.
size_t max_tab_per_window;
// The total number of windows opened.
size_t window_count;
// The maximum total number of windows opened at the same time.
size_t window_count_max;
};
// Structure describing the state of a tab during an interval of time.
struct TabStateDuringInterval {
// Indicates if the tab exists at the beginning of the interval.
bool existed_before_interval;
// Indicates if the tab still exists.
bool exists_currently;
// Indicates if the tab has been visible or audible at any moment during the
// interval.
bool visible_or_audible_during_interval;
// Indicates if the tab has been interacted with or active at any moment
// during the interval. See the |OnTabInteraction| for the list of possible
// interactions.
bool interacted_during_interval;
};
// A TabID is used instead of a WebContents* because:
// - The WebContents of a tab can change during its lifetime.
// - A WebContents* can be reused for a separate tab after a tab has been
// closed.
using TabID = size_t;
// Represents the state of a set of tabs during an interval of time.
using TabsStateDuringIntervalMap =
base::flat_map<TabID, TabStateDuringInterval>;
explicit TabStatsDataStore(PrefService* pref_service);
virtual ~TabStatsDataStore();
// Functions used to update the window/tab count.
void OnWindowAdded();
void OnWindowRemoved();
// Virtual for unittesting.
virtual void OnTabAdded(content::WebContents* web_contents);
virtual void OnTabRemoved(content::WebContents* web_contents);
void OnTabReplaced(content::WebContents* old_contents,
content::WebContents* new_contents);
// Update the maximum number of tabs in a single window if |value| exceeds
// this.
// TODO(sebmarchand): Store a list of windows in this class and track the
// number of tabs per window.
void UpdateMaxTabsPerWindowIfNeeded(size_t value);
// Reset all the maximum values to the current state, to be used once the
// metrics have been reported.
void ResetMaximumsToCurrentState();
// Records that there's been a direct user interaction with a tab, see the
// comment for |DidGetUserInteraction| in
// content/public/browser/web_contents_observer.h for a list of the possible
// type of interactions.
void OnTabInteraction(content::WebContents* web_contents);
// Records that a tab became audible.
void OnTabAudible(content::WebContents* web_contents);
// Records that a tab became visible.
void OnTabVisible(content::WebContents* web_contents);
// Creates a new interval map. The returned pointer is owned by |this|.
TabsStateDuringIntervalMap* AddInterval();
// Reset |interval_map| with the list of current tabs.
void ResetIntervalData(TabsStateDuringIntervalMap* interval_map);
const TabsStats& tab_stats() const { return tab_stats_; }
base::Optional<TabID> GetTabIDForTesting(content::WebContents* web_contents);
base::flat_map<content::WebContents*, TabID>* existing_tabs_for_testing() {
return &existing_tabs_;
}
protected:
FRIEND_TEST_ALL_PREFIXES(TabStatsTrackerBrowserTest,
TabDeletionGetsHandledProperly);
// Update the maximums metrics if needed.
void UpdateTotalTabCountMaxIfNeeded();
void UpdateWindowCountMaxIfNeeded();
// Adds a tab to an interval map.
void AddTabToIntervalMap(content::WebContents* web_contents,
TabID tab_id,
bool existed_before_interval,
TabsStateDuringIntervalMap* interval_map);
// Returns the TabID associated with a tab.
TabID GetTabID(content::WebContents* web_contents);
private:
void OnTabAudibleOrVisible(content::WebContents* web_contents);
// The tabs stats.
TabsStats tab_stats_;
// A raw pointer to the PrefService used to read and write the statistics.
PrefService* pref_service_;
// The interval maps, one per period of time that we want to observe.
std::vector<std::unique_ptr<TabsStateDuringIntervalMap>> interval_maps_;
// The tabs that currently exist.
base::flat_map<content::WebContents*, TabID> existing_tabs_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(TabStatsDataStore);
};
} // namespace metrics
#endif // CHROME_BROWSER_METRICS_TAB_STATS_DATA_STORE_H_