Commit b0468d94 authored by Varun Mohan's avatar Varun Mohan Committed by Commit Bot

Adding metrics for native window occlusion count on Windows

These metrics will record the number of occluded/visible/hidden native Chrome windows on Windows. This information will be polled and computed on a repeating timer. This information will be used to determine if occlusion tracking on Windows is worth pursuing going forward.

Bug: 813093
Change-Id: Icc9d18ddd6ef293aca15a787b3fc5c1d64b4a4cd
Reviewed-on: https://chromium-review.googlesource.com/1025074
Commit-Queue: Varun Mohan <varunmohan@google.com>
Reviewed-by: default avatarSébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554213}
parent 768166bb
......@@ -2540,6 +2540,9 @@ jumbo_split_static_library("browser") {
"metrics/tab_stats_data_store.h",
"metrics/tab_stats_tracker.cc",
"metrics/tab_stats_tracker.h",
"metrics/tab_stats_tracker_delegate.h",
"metrics/tab_stats_tracker_delegate_win.cc",
"metrics/tab_stats_tracker_win.cc",
"metrics/tab_usage_recorder.cc",
"metrics/tab_usage_recorder.h",
"notifications/message_center_notification_manager.cc",
......@@ -2935,6 +2938,7 @@ jumbo_split_static_library("browser") {
"//third_party/iaccessible2",
"//third_party/isimpledom",
"//third_party/wtl",
"//ui/aura_extra",
"//ui/base:fullscreen_win",
]
......
......@@ -45,6 +45,11 @@ constexpr base::TimeDelta kTabUsageReportingIntervals[] = {
base::TimeDelta::FromMinutes(10), base::TimeDelta::FromHours(1),
base::TimeDelta::FromHours(5), base::TimeDelta::FromHours(12)};
#if defined(OS_WIN)
const base::TimeDelta kNativeWindowOcclusionCalculationInterval =
base::TimeDelta::FromMinutes(10);
#endif
// The global TabStatsTracker instance.
TabStatsTracker* g_tab_stats_tracker_instance = nullptr;
......@@ -87,6 +92,7 @@ const TabStatsDataStore::TabsStats& TabStatsTracker::tab_stats() const {
TabStatsTracker::TabStatsTracker(PrefService* pref_service)
: reporting_delegate_(std::make_unique<UmaStatsReportingDelegate>()),
delegate_(std::make_unique<TabStatsTrackerDelegate>()),
tab_stats_data_store_(std::make_unique<TabStatsDataStore>(pref_service)),
daily_event_(
std::make_unique<DailyEvent>(pref_service,
......@@ -130,6 +136,14 @@ TabStatsTracker::TabStatsTracker(PrefService* pref_service)
interval, interval_map));
usage_interval_timers_.push_back(std::move(timer));
}
// The native window occlusion calculation is specific to Windows.
#if defined(OS_WIN)
native_window_occlusion_timer_.Start(
FROM_HERE, kNativeWindowOcclusionCalculationInterval,
Bind(&TabStatsTracker::CalculateAndRecordNativeWindowVisibilities,
base::Unretained(this)));
#endif
}
TabStatsTracker::~TabStatsTracker() {
......@@ -162,6 +176,11 @@ void TabStatsTracker::RegisterPrefs(PrefRegistrySimple* registry) {
DailyEvent::RegisterPref(registry, ::prefs::kTabStatsDailySample);
}
void TabStatsTracker::SetDelegateForTesting(
std::unique_ptr<TabStatsTrackerDelegate> new_delegate) {
delegate_ = std::move(new_delegate);
}
void TabStatsTracker::TabStatsDailyObserver::OnDailyEvent(
DailyEvent::IntervalType type) {
reporting_delegate_->ReportDailyMetrics(data_store_->tab_stats());
......
......@@ -10,13 +10,16 @@
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/power_monitor/power_observer.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "chrome/browser/metrics/tab_stats_data_store.h"
#include "chrome/browser/metrics/tab_stats_tracker_delegate.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/metrics/daily_event.h"
......@@ -26,7 +29,6 @@ class PrefRegistrySimple;
class PrefService;
namespace metrics {
FORWARD_DECLARE_TEST(TabStatsTrackerBrowserTest,
TabDeletionGetsHandledProperly);
......@@ -53,12 +55,19 @@ class TabStatsTracker : public TabStripModelObserver,
// Registers prefs used to track tab stats.
static void RegisterPrefs(PrefRegistrySimple* registry);
void SetDelegateForTesting(
std::unique_ptr<TabStatsTrackerDelegate> new_delegate);
// Accessors.
const TabStatsDataStore::TabsStats& tab_stats() const;
protected:
FRIEND_TEST_ALL_PREFIXES(TabStatsTrackerBrowserTest,
TabDeletionGetsHandledProperly);
#if defined(OS_WIN)
FRIEND_TEST_ALL_PREFIXES(TabStatsTrackerBrowserTest,
TestCalculateAndRecordNativeWindowVisibilities);
#endif
// The UmaStatsReportingDelegate is responsible for delivering statistics
// reported by the TabStatsTracker via UMA.
......@@ -146,6 +155,12 @@ class TabStatsTracker : public TabStripModelObserver,
// Functions to call when a WebContents get destroyed.
void OnWebContentsDestroyed(content::WebContents* web_contents);
#if defined(OS_WIN)
// Function to call aura_extra::ComputeNativeWindowOcclusionStatus() and
// record the Visibility of all Chrome browser windows on Windows.
void CalculateAndRecordNativeWindowVisibilities();
#endif
// The name of the histogram used to report that the daily event happened.
static const char kTabStatsDailyEventHistogramName[];
......@@ -157,6 +172,9 @@ class TabStatsTracker : public TabStripModelObserver,
// The delegate that reports the events.
std::unique_ptr<UmaStatsReportingDelegate> reporting_delegate_;
// Delegate to collect data;
std::unique_ptr<TabStatsTrackerDelegate> delegate_;
// The tab stats.
std::unique_ptr<TabStatsDataStore> tab_stats_data_store_;
......@@ -167,6 +185,12 @@ class TabStatsTracker : public TabStripModelObserver,
// triggered.
base::RepeatingTimer timer_;
#if defined(OS_WIN)
// The timer used to periodically calculate the occlusion status of native
// windows on Windows.
base::RepeatingTimer native_window_occlusion_timer_;
#endif
// The timers used to analyze how tabs are used during a given interval of
// time.
std::vector<std::unique_ptr<base::RepeatingTimer>> usage_interval_timers_;
......@@ -222,6 +246,12 @@ class TabStatsTracker::UmaStatsReportingDelegate {
const TabStatsDataStore::TabsStateDuringIntervalMap& interval_map,
base::TimeDelta interval);
#if defined(OS_WIN)
void RecordNativeWindowVisibilities(size_t num_occluded,
size_t num_visible,
size_t num_hidden);
#endif
protected:
// Generates the name of the histograms that will track tab usage during a
// given period of time.
......
......@@ -4,8 +4,12 @@
#include "chrome/browser/metrics/tab_stats_tracker.h"
#include "base/containers/flat_map.h"
#include "base/test/histogram_tester.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -26,6 +30,26 @@ void EnsureTabStatsMatchExpectations(const TabsStats& expected,
} // namespace
class MockTabStatsTrackerDelegate : public TabStatsTrackerDelegate {
public:
MockTabStatsTrackerDelegate() = default;
~MockTabStatsTrackerDelegate() override = default;
#if defined(OS_WIN)
OcclusionStatusMap CallComputeNativeWindowOcclusionStatus(
std::vector<aura::WindowTreeHost*> hosts) override {
return mock_occlusion_results_;
}
void SetMockOcclusionResults(OcclusionStatusMap mock_occlusion_results) {
mock_occlusion_results_ = mock_occlusion_results;
}
private:
OcclusionStatusMap mock_occlusion_results_;
#endif
};
class TabStatsTrackerBrowserTest : public InProcessBrowserTest {
public:
TabStatsTrackerBrowserTest() : tab_stats_tracker_(nullptr) {}
......@@ -36,6 +60,9 @@ class TabStatsTrackerBrowserTest : public InProcessBrowserTest {
}
protected:
// Used to make sure that the metrics are reported properly.
base::HistogramTester histogram_tester_;
TabStatsTracker* tab_stats_tracker_;
DISALLOW_COPY_AND_ASSIGN(TabStatsTrackerBrowserTest);
......@@ -134,4 +161,85 @@ IN_PROC_BROWSER_TEST_F(TabStatsTrackerBrowserTest,
EXPECT_EQ(0U, interval_map->size());
}
#if defined(OS_WIN)
IN_PROC_BROWSER_TEST_F(TabStatsTrackerBrowserTest,
TestCalculateAndRecordNativeWindowVisibilities) {
std::unique_ptr<MockTabStatsTrackerDelegate> mock_delegate =
std::make_unique<MockTabStatsTrackerDelegate>();
// Maintaining this reference to |mock_delegate| is safe because the
// TabStatsTracker will outlive this test class.
MockTabStatsTrackerDelegate* mock_delegate_raw = mock_delegate.get();
tab_stats_tracker_->SetDelegateForTesting(std::move(mock_delegate));
TabStatsTrackerDelegate::OcclusionStatusMap mock_occlusion_results;
mock_delegate_raw->SetMockOcclusionResults(mock_occlusion_results);
tab_stats_tracker_->CalculateAndRecordNativeWindowVisibilities();
// There should be 1 entry for each zero window bucket.
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Occluded",
0, 1);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Visible",
0, 1);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Hidden",
0, 1);
// There should be no entries in the 1 window bucket.
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Occluded",
1, 0);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Visible",
1, 0);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Hidden",
1, 0);
// Create a browser for each aura::Window::OcclusionState.
mock_occlusion_results[CreateBrowser(ProfileManager::GetActiveUserProfile())
->window()
->GetNativeWindow()
->GetHost()] =
aura::Window::OcclusionState::HIDDEN;
mock_occlusion_results[CreateBrowser(ProfileManager::GetActiveUserProfile())
->window()
->GetNativeWindow()
->GetHost()] =
aura::Window::OcclusionState::VISIBLE;
mock_occlusion_results[CreateBrowser(ProfileManager::GetActiveUserProfile())
->window()
->GetNativeWindow()
->GetHost()] =
aura::Window::OcclusionState::OCCLUDED;
mock_delegate_raw->SetMockOcclusionResults(mock_occlusion_results);
// There should now be 1 entry for each 1 window bucket.
tab_stats_tracker_->CalculateAndRecordNativeWindowVisibilities();
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Occluded",
1, 1);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Visible",
1, 1);
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Hidden",
1, 1);
mock_occlusion_results.clear();
// Create 5 aura::Window::OcclusionState browsers.
for (int count = 0; count < 5; count++) {
mock_occlusion_results[CreateBrowser(ProfileManager::GetActiveUserProfile())
->window()
->GetNativeWindow()
->GetHost()] =
aura::Window::OcclusionState::OCCLUDED;
}
mock_delegate_raw->SetMockOcclusionResults(mock_occlusion_results);
tab_stats_tracker_->CalculateAndRecordNativeWindowVisibilities();
// There should be 1 entry in the 5 window occluded bucket.
histogram_tester_.ExpectBucketCount("Windows.NativeWindowVisibility.Occluded",
5, 1);
}
#endif // defined(OS_WIN)
} // namespace metrics
// Copyright 2018 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_TRACKER_DELEGATE_H_
#define CHROME_BROWSER_METRICS_TAB_STATS_TRACKER_DELEGATE_H_
#include "build/build_config.h"
#if defined(OS_WIN)
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#endif
class TabStatsTrackerDelegate {
public:
TabStatsTrackerDelegate() {}
virtual ~TabStatsTrackerDelegate() {}
#if defined(OS_WIN)
using OcclusionStatusMap =
base::flat_map<aura::WindowTreeHost*, aura::Window::OcclusionState>;
virtual OcclusionStatusMap CallComputeNativeWindowOcclusionStatus(
std::vector<aura::WindowTreeHost*> hosts);
#endif // OS_WIN
};
#endif // CHROME_BROWSER_METRICS_TAB_STATS_TRACKER_DELEGATE_H_
// Copyright 2018 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_stats_tracker_delegate.h"
#include "ui/aura_extra/window_occlusion_win.h"
TabStatsTrackerDelegate::OcclusionStatusMap
TabStatsTrackerDelegate::CallComputeNativeWindowOcclusionStatus(
std::vector<aura::WindowTreeHost*> hosts) {
return aura_extra::ComputeNativeWindowOcclusionStatus(hosts);
}
// Copyright 2018 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_stats_tracker.h"
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
namespace metrics {
void TabStatsTracker::CalculateAndRecordNativeWindowVisibilities() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BrowserList* browser_list = BrowserList::GetInstance();
std::vector<aura::WindowTreeHost*> hosts(browser_list->size());
// Get the aura::WindowTreeHost for each Chrome browser.
for (Browser* browser : *browser_list) {
aura::WindowTreeHost* host =
browser->window()->GetNativeWindow()->GetHost();
hosts.push_back(host);
}
// Compute native window occlusion if not using mock occlusion results.
TabStatsTrackerDelegate::OcclusionStatusMap native_window_visibilities =
delegate_->CallComputeNativeWindowOcclusionStatus(hosts);
size_t num_occluded = 0;
size_t num_visible = 0;
size_t num_hidden = 0;
// Determine the number of Chrome browser windows in each visibility state.
for (auto& window_visibility_pair : native_window_visibilities) {
aura::Window::OcclusionState visibility = window_visibility_pair.second;
switch (visibility) {
case aura::Window::OcclusionState::OCCLUDED:
num_occluded++;
break;
case aura::Window::OcclusionState::VISIBLE:
num_visible++;
break;
case aura::Window::OcclusionState::HIDDEN:
num_hidden++;
break;
case aura::Window::OcclusionState::UNKNOWN:
break;
}
}
reporting_delegate_->RecordNativeWindowVisibilities(num_occluded, num_visible,
num_hidden);
}
void TabStatsTracker::UmaStatsReportingDelegate::RecordNativeWindowVisibilities(
size_t num_occluded,
size_t num_visible,
size_t num_hidden) {
UMA_HISTOGRAM_COUNTS_10000("Windows.NativeWindowVisibility.Occluded",
num_occluded);
UMA_HISTOGRAM_COUNTS_10000("Windows.NativeWindowVisibility.Visible",
num_visible);
UMA_HISTOGRAM_COUNTS_10000("Windows.NativeWindowVisibility.Hidden",
num_hidden);
}
} // namespace metrics
......@@ -106688,6 +106688,15 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary>
</histogram>
<histogram name="Windows.NativeWindowVisibility" units="windows">
<owner>fdoray@chromium.org</owner>
<summary>
The number of Chrome browser windows in a given visibility state. This is
computed using ComputeNativeWindowOcclusionStatus() and is recorded every 10
minutes.
</summary>
</histogram>
<histogram name="Windows.ParentProcessNameHash" enum="ProcessNameHash">
<owner>wfh@chromium.org</owner>
<summary>
......@@ -111722,6 +111731,17 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
name="Net.ResourceDispatcherHost.PeakOutstandingRequests"/>
</histogram_suffixes>
<histogram_suffixes name="NativeWindowVisibility" separator=".">
<suffix name="Hidden"
label="The native window is not visible because it is in a minimized
window"/>
<suffix name="Occluded"
label="The native window is fully covered by other windows"/>
<suffix name="Visible"
label="The native window is visible or partially visible."/>
<affected-histogram name="Windows.NativeWindowVisibility"/>
</histogram_suffixes>
<histogram_suffixes name="NatType" separator=".">
<suffix name="NoNAT"/>
<suffix name="NonSymNAT"/>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment