Commit 4d2b2e3f authored by Glen Robertson's avatar Glen Robertson Committed by Commit Bot

Expose jank_monitor.h and CreateAccessibilityMetricsProvider.

These interfaces were hidden within //content but depended upon from
//chrome/browser. This clarifies the layering issues present but does
not completely fix them (see additions to DEPS). It does also resolve
`gn check` errors in //chrome/browser.

Specifically, profile_provider_chromeos.h includes jank_monitor.h
(holds a pointer and is an observer) and
chrome_metrics_service_client.cc includes
accessibility_metrics_provider.h (only to create one).
Let me know if there's a better way to layer this.

Split out from crrev.com/c/2383400

Bug: 898837
Change-Id: I4786b903e52164841d91b431d3bcd2cabc2df54e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2383515
Commit-Queue: Glen Robertson <glenrob@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803751}
parent d75b11e5
...@@ -4095,6 +4095,10 @@ static_library("browser") { ...@@ -4095,6 +4095,10 @@ static_library("browser") {
} else { # Non - ChromeOS. } else { # Non - ChromeOS.
sources += [ sources += [
"fullscreen.h", "fullscreen.h",
# ChromeOS accessibility metrics provider is in chromeos_metrics_provider.
"metrics/accessibility_metrics_provider.cc",
"metrics/accessibility_metrics_provider.h",
"policy/browser_signin_policy_handler.cc", "policy/browser_signin_policy_handler.cc",
"policy/browser_signin_policy_handler.h", "policy/browser_signin_policy_handler.h",
"policy/cloud/user_cloud_policy_manager_builder.cc", "policy/cloud/user_cloud_policy_manager_builder.cc",
......
include_rules = [ include_rules = [
"+chrome/services/util_win/util_win_impl.h", "+chrome/services/util_win/util_win_impl.h",
"+content/browser/accessibility/accessibility_metrics_provider.h",
] ]
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "content/browser/accessibility/accessibility_metrics_provider.h" #include "chrome/browser/metrics/accessibility_metrics_provider.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h" #include "content/public/browser/browser_accessibility_state.h"
AccessibilityMetricsProvider::AccessibilityMetricsProvider() {} AccessibilityMetricsProvider::AccessibilityMetricsProvider() {}
...@@ -12,6 +12,6 @@ AccessibilityMetricsProvider::~AccessibilityMetricsProvider() {} ...@@ -12,6 +12,6 @@ AccessibilityMetricsProvider::~AccessibilityMetricsProvider() {}
void AccessibilityMetricsProvider::ProvideCurrentSessionData( void AccessibilityMetricsProvider::ProvideCurrentSessionData(
metrics::ChromeUserMetricsExtension* uma_proto) { metrics::ChromeUserMetricsExtension* uma_proto) {
content::BrowserAccessibilityStateImpl::GetInstance() content::BrowserAccessibilityState::GetInstance()
->UpdateUniqueUserHistograms(); ->UpdateUniqueUserHistograms();
} }
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_METRICS_PROVIDER_H_ #ifndef CHROME_BROWSER_METRICS_ACCESSIBILITY_METRICS_PROVIDER_H_
#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_METRICS_PROVIDER_H_ #define CHROME_BROWSER_METRICS_ACCESSIBILITY_METRICS_PROVIDER_H_
#include "components/metrics/metrics_provider.h" #include "components/metrics/metrics_provider.h"
#include "content/common/content_export.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
...@@ -16,8 +15,7 @@ ...@@ -16,8 +15,7 @@
// histograms on Win, Mac and Android, enable accurate counting of unique users. // histograms on Win, Mac and Android, enable accurate counting of unique users.
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CONTENT_EXPORT AccessibilityMetricsProvider class AccessibilityMetricsProvider : public metrics::MetricsProvider {
: public metrics::MetricsProvider {
public: public:
AccessibilityMetricsProvider(); AccessibilityMetricsProvider();
~AccessibilityMetricsProvider() override; ~AccessibilityMetricsProvider() override;
...@@ -30,4 +28,4 @@ class CONTENT_EXPORT AccessibilityMetricsProvider ...@@ -30,4 +28,4 @@ class CONTENT_EXPORT AccessibilityMetricsProvider
DISALLOW_COPY_AND_ASSIGN(AccessibilityMetricsProvider); DISALLOW_COPY_AND_ASSIGN(AccessibilityMetricsProvider);
}; };
#endif // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_METRICS_PROVIDER_H_ #endif // CHROME_BROWSER_METRICS_ACCESSIBILITY_METRICS_PROVIDER_H_
...@@ -101,7 +101,6 @@ ...@@ -101,7 +101,6 @@
#include "components/ukm/field_trials_provider_helper.h" #include "components/ukm/field_trials_provider_helper.h"
#include "components/ukm/ukm_service.h" #include "components/ukm/ukm_service.h"
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/browser/accessibility/accessibility_metrics_provider.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/histogram_fetcher.h" #include "content/public/browser/histogram_fetcher.h"
...@@ -170,6 +169,7 @@ ...@@ -170,6 +169,7 @@
#endif #endif
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
#include "chrome/browser/metrics/accessibility_metrics_provider.h"
#include "chrome/browser/signin/chrome_signin_status_metrics_provider_delegate.h" #include "chrome/browser/signin/chrome_signin_status_metrics_provider_delegate.h"
#include "components/signin/core/browser/signin_status_metrics_provider.h" #include "components/signin/core/browser/signin_status_metrics_provider.h"
#endif // !defined(OS_CHROMEOS) #endif // !defined(OS_CHROMEOS)
......
...@@ -96,8 +96,7 @@ void ProfileProvider::Init() { ...@@ -96,8 +96,7 @@ void ProfileProvider::Init() {
if (base::FeatureList::IsEnabled(kBrowserJankinessProfiling)) { if (base::FeatureList::IsEnabled(kBrowserJankinessProfiling)) {
// Set up the JankMonitor for watching browser jankiness. // Set up the JankMonitor for watching browser jankiness.
jank_monitor_ = jank_monitor_ = content::JankMonitor::Create();
base::MakeRefCounted<content::responsiveness::JankMonitor>();
jank_monitor_->SetUp(); jank_monitor_->SetUp();
jank_monitor_->AddObserver(this); jank_monitor_->AddObserver(this);
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/sessions/session_restore.h"
#include "chromeos/dbus/power/power_manager_client.h" #include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/login/login_state/login_state.h" #include "chromeos/login/login_state/login_state.h"
#include "content/browser/scheduler/responsiveness/jank_monitor.h" #include "content/public/browser/jank_monitor.h"
namespace metrics { namespace metrics {
...@@ -24,7 +24,7 @@ class SampledProfile; ...@@ -24,7 +24,7 @@ class SampledProfile;
// mode, or user logging in, which it forwards to the registered collectors. // mode, or user logging in, which it forwards to the registered collectors.
class ProfileProvider : public chromeos::PowerManagerClient::Observer, class ProfileProvider : public chromeos::PowerManagerClient::Observer,
public chromeos::LoginState::Observer, public chromeos::LoginState::Observer,
public content::responsiveness::JankMonitor::Observer { public content::JankMonitor::Observer {
public: public:
ProfileProvider(); ProfileProvider();
~ProfileProvider() override; ~ProfileProvider() override;
...@@ -55,7 +55,7 @@ class ProfileProvider : public chromeos::PowerManagerClient::Observer, ...@@ -55,7 +55,7 @@ class ProfileProvider : public chromeos::PowerManagerClient::Observer,
void OnJankStopped() override; void OnJankStopped() override;
// For testing. // For testing.
scoped_refptr<content::responsiveness::JankMonitor> jank_monitor() const { scoped_refptr<content::JankMonitor> jank_monitor() const {
return jank_monitor_; return jank_monitor_;
} }
// For testing. // For testing.
...@@ -75,7 +75,7 @@ class ProfileProvider : public chromeos::PowerManagerClient::Observer, ...@@ -75,7 +75,7 @@ class ProfileProvider : public chromeos::PowerManagerClient::Observer,
SessionRestore::CallbackSubscription SessionRestore::CallbackSubscription
on_session_restored_callback_subscription_; on_session_restored_callback_subscription_;
scoped_refptr<content::responsiveness::JankMonitor> jank_monitor_; scoped_refptr<content::JankMonitor> jank_monitor_;
// Timestamp of the most recent jank observed. // Timestamp of the most recent jank observed.
base::TimeTicks last_jank_start_time_; base::TimeTicks last_jank_start_time_;
......
...@@ -1667,8 +1667,8 @@ source_set("browser") { ...@@ -1667,8 +1667,8 @@ source_set("browser") {
"scheduler/browser_ui_thread_scheduler.h", "scheduler/browser_ui_thread_scheduler.h",
"scheduler/responsiveness/calculator.cc", "scheduler/responsiveness/calculator.cc",
"scheduler/responsiveness/calculator.h", "scheduler/responsiveness/calculator.h",
"scheduler/responsiveness/jank_monitor.cc", "scheduler/responsiveness/jank_monitor_impl.cc",
"scheduler/responsiveness/jank_monitor.h", "scheduler/responsiveness/jank_monitor_impl.h",
"scheduler/responsiveness/message_loop_observer.cc", "scheduler/responsiveness/message_loop_observer.cc",
"scheduler/responsiveness/message_loop_observer.h", "scheduler/responsiveness/message_loop_observer.h",
"scheduler/responsiveness/metric_source.cc", "scheduler/responsiveness/metric_source.cc",
...@@ -2684,12 +2684,6 @@ source_set("browser") { ...@@ -2684,12 +2684,6 @@ source_set("browser") {
"//chromeos/system", "//chromeos/system",
"//components/session_manager/core", "//components/session_manager/core",
] ]
} else {
sources += [
# ChromeOS accessibility metrics provider is in chromeos_metrics_provider.
"accessibility/accessibility_metrics_provider.cc",
"accessibility/accessibility_metrics_provider.h",
]
} }
if (use_aura) { if (use_aura) {
......
...@@ -60,6 +60,7 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl ...@@ -60,6 +60,7 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
bool IsAccessibleBrowser() override; bool IsAccessibleBrowser() override;
void AddUIThreadHistogramCallback(base::OnceClosure callback) override; void AddUIThreadHistogramCallback(base::OnceClosure callback) override;
void AddOtherThreadHistogramCallback(base::OnceClosure callback) override; void AddOtherThreadHistogramCallback(base::OnceClosure callback) override;
void UpdateUniqueUserHistograms() override;
void UpdateHistogramsForTesting() override; void UpdateHistogramsForTesting() override;
void SetCaretBrowsingState(bool enabled) override; void SetCaretBrowsingState(bool enabled) override;
...@@ -70,11 +71,6 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl ...@@ -70,11 +71,6 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
// AXModeObserver // AXModeObserver
void OnAXModeAdded(ui::AXMode mode) override; void OnAXModeAdded(ui::AXMode mode) override;
// Fire frequent metrics signals to ensure users keeping browser open multiple
// days are counted each day, not only at launch. This is necessary, because
// UMA only aggregates uniques on a daily basis,
void UpdateUniqueUserHistograms();
// Accessibility objects can have the "hot tracked" state set when // Accessibility objects can have the "hot tracked" state set when
// the mouse is hovering over them, but this makes tests flaky because // the mouse is hovering over them, but this makes tests flaky because
// the test behaves differently when the mouse happens to be over an // the test behaves differently when the mouse happens to be over an
......
...@@ -2,15 +2,26 @@ ...@@ -2,15 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "content/browser/scheduler/responsiveness/jank_monitor.h" #include "content/browser/scheduler/responsiveness/jank_monitor_impl.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_features.h"
namespace content { namespace content {
JankMonitor::~JankMonitor() = default;
JankMonitor::Observer::~Observer() = default;
// static
scoped_refptr<JankMonitor> JankMonitor::Create() {
return base::MakeRefCounted<responsiveness::JankMonitorImpl>();
}
namespace responsiveness { namespace responsiveness {
// Interval of the monitor performing jankiness checks against the watched // Interval of the monitor performing jankiness checks against the watched
...@@ -22,9 +33,7 @@ static constexpr int64_t kJankThresholdMs = 1000; ...@@ -22,9 +33,7 @@ static constexpr int64_t kJankThresholdMs = 1000;
static constexpr int64_t kInactivityThresholdUs = static constexpr int64_t kInactivityThresholdUs =
10 * base::TimeTicks::kMicrosecondsPerSecond; 10 * base::TimeTicks::kMicrosecondsPerSecond;
JankMonitor::Observer::~Observer() = default; JankMonitorImpl::JankMonitorImpl()
JankMonitor::JankMonitor()
: timer_(std::make_unique<base::RepeatingTimer>()), : timer_(std::make_unique<base::RepeatingTimer>()),
timer_running_(false), timer_running_(false),
janky_task_id_(nullptr), janky_task_id_(nullptr),
...@@ -33,19 +42,19 @@ JankMonitor::JankMonitor() ...@@ -33,19 +42,19 @@ JankMonitor::JankMonitor()
DETACH_FROM_SEQUENCE(monitor_sequence_checker_); DETACH_FROM_SEQUENCE(monitor_sequence_checker_);
} }
JankMonitor::~JankMonitor() = default; JankMonitorImpl::~JankMonitorImpl() = default;
void JankMonitor::AddObserver(Observer* observer) { void JankMonitorImpl::AddObserver(content::JankMonitor::Observer* observer) {
base::AutoLock auto_lock(observers_lock_); base::AutoLock auto_lock(observers_lock_);
observers_.AddObserver(observer); observers_.AddObserver(observer);
} }
void JankMonitor::RemoveObserver(Observer* observer) { void JankMonitorImpl::RemoveObserver(content::JankMonitor::Observer* observer) {
base::AutoLock auto_lock(observers_lock_); base::AutoLock auto_lock(observers_lock_);
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void JankMonitor::SetUp() { void JankMonitorImpl::SetUp() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Dependencies in SetUp() and Destroy(): // Dependencies in SetUp() and Destroy():
...@@ -65,7 +74,7 @@ void JankMonitor::SetUp() { ...@@ -65,7 +74,7 @@ void JankMonitor::SetUp() {
metric_source_->SetUp(); metric_source_->SetUp();
} }
void JankMonitor::Destroy() { void JankMonitorImpl::Destroy() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Destroy shuts down the monitor timer and the metric source in parallel. // Destroy shuts down the monitor timer and the metric source in parallel.
...@@ -75,79 +84,80 @@ void JankMonitor::Destroy() { ...@@ -75,79 +84,80 @@ void JankMonitor::Destroy() {
// JankMonitor dtor, which can happen on either the monitor or the UI thread. // JankMonitor dtor, which can happen on either the monitor or the UI thread.
monitor_task_runner_->PostTask( monitor_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&JankMonitor::DestroyOnMonitorThread, FROM_HERE, base::BindOnce(&JankMonitorImpl::DestroyOnMonitorThread,
base::RetainedRef(this))); base::RetainedRef(this)));
base::ScopedClosureRunner finish_destroy_metric_source(base::BindOnce( base::ScopedClosureRunner finish_destroy_metric_source(base::BindOnce(
&JankMonitor::FinishDestroyMetricSource, base::RetainedRef(this))); &JankMonitorImpl::FinishDestroyMetricSource, base::RetainedRef(this)));
metric_source_->Destroy(std::move(finish_destroy_metric_source)); metric_source_->Destroy(std::move(finish_destroy_metric_source));
} }
void JankMonitor::FinishDestroyMetricSource() { void JankMonitorImpl::FinishDestroyMetricSource() {
// Destruction of MetricSource takes place on the UI thread. // Destruction of MetricSource takes place on the UI thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
metric_source_ = nullptr; metric_source_ = nullptr;
} }
void JankMonitor::SetUpOnIOThread() {} void JankMonitorImpl::SetUpOnIOThread() {}
void JankMonitor::TearDownOnUIThread() { void JankMonitorImpl::TearDownOnUIThread() {
// Don't destroy |ui_thread_exec_state_| yet because it might be used if the // Don't destroy |ui_thread_exec_state_| yet because it might be used if the
// monitor timer runs. // monitor timer runs.
} }
void JankMonitor::TearDownOnIOThread() { void JankMonitorImpl::TearDownOnIOThread() {
// Don't destroy |io_thread_exec_state_| yet because it might be used if the // Don't destroy |io_thread_exec_state_| yet because it might be used if the
// monitor timer fires. // monitor timer fires.
} }
void JankMonitor::WillRunTaskOnUIThread( void JankMonitorImpl::WillRunTaskOnUIThread(
const base::PendingTask* task, const base::PendingTask* task,
bool /* was_blocked_or_low_priority */) { bool /* was_blocked_or_low_priority */) {
DCHECK(ui_thread_exec_state_); DCHECK(ui_thread_exec_state_);
WillRunTaskOrEvent(ui_thread_exec_state_.get(), task); WillRunTaskOrEvent(ui_thread_exec_state_.get(), task);
} }
void JankMonitor::DidRunTaskOnUIThread(const base::PendingTask* task) { void JankMonitorImpl::DidRunTaskOnUIThread(const base::PendingTask* task) {
DCHECK(ui_thread_exec_state_); DCHECK(ui_thread_exec_state_);
DidRunTaskOrEvent(ui_thread_exec_state_.get(), task); DidRunTaskOrEvent(ui_thread_exec_state_.get(), task);
} }
void JankMonitor::WillRunTaskOnIOThread( void JankMonitorImpl::WillRunTaskOnIOThread(
const base::PendingTask* task, const base::PendingTask* task,
bool /* was_blocked_or_low_priority */) { bool /* was_blocked_or_low_priority */) {
DCHECK(io_thread_exec_state_); DCHECK(io_thread_exec_state_);
WillRunTaskOrEvent(io_thread_exec_state_.get(), task); WillRunTaskOrEvent(io_thread_exec_state_.get(), task);
} }
void JankMonitor::DidRunTaskOnIOThread(const base::PendingTask* task) { void JankMonitorImpl::DidRunTaskOnIOThread(const base::PendingTask* task) {
DCHECK(io_thread_exec_state_); DCHECK(io_thread_exec_state_);
DidRunTaskOrEvent(io_thread_exec_state_.get(), task); DidRunTaskOrEvent(io_thread_exec_state_.get(), task);
} }
void JankMonitor::WillRunEventOnUIThread(const void* opaque_identifier) { void JankMonitorImpl::WillRunEventOnUIThread(const void* opaque_identifier) {
DCHECK(ui_thread_exec_state_); DCHECK(ui_thread_exec_state_);
WillRunTaskOrEvent(ui_thread_exec_state_.get(), opaque_identifier); WillRunTaskOrEvent(ui_thread_exec_state_.get(), opaque_identifier);
} }
void JankMonitor::DidRunEventOnUIThread(const void* opaque_identifier) { void JankMonitorImpl::DidRunEventOnUIThread(const void* opaque_identifier) {
DCHECK(ui_thread_exec_state_); DCHECK(ui_thread_exec_state_);
DidRunTaskOrEvent(ui_thread_exec_state_.get(), opaque_identifier); DidRunTaskOrEvent(ui_thread_exec_state_.get(), opaque_identifier);
} }
void JankMonitor::WillRunTaskOrEvent(ThreadExecutionState* thread_exec_state, void JankMonitorImpl::WillRunTaskOrEvent(
const void* opaque_identifier) { ThreadExecutionState* thread_exec_state,
const void* opaque_identifier) {
thread_exec_state->WillRunTaskOrEvent(opaque_identifier); thread_exec_state->WillRunTaskOrEvent(opaque_identifier);
if (!timer_running_) { if (!timer_running_) {
monitor_task_runner_->PostTask( monitor_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&JankMonitor::StartTimerIfNecessary, FROM_HERE, base::BindOnce(&JankMonitorImpl::StartTimerIfNecessary,
base::RetainedRef(this))); base::RetainedRef(this)));
} }
} }
void JankMonitor::DidRunTaskOrEvent(ThreadExecutionState* thread_exec_state, void JankMonitorImpl::DidRunTaskOrEvent(ThreadExecutionState* thread_exec_state,
const void* opaque_identifier) { const void* opaque_identifier) {
thread_exec_state->DidRunTaskOrEvent(opaque_identifier); thread_exec_state->DidRunTaskOrEvent(opaque_identifier);
NotifyJankStopIfNecessary(opaque_identifier); NotifyJankStopIfNecessary(opaque_identifier);
...@@ -157,7 +167,7 @@ void JankMonitor::DidRunTaskOrEvent(ThreadExecutionState* thread_exec_state, ...@@ -157,7 +167,7 @@ void JankMonitor::DidRunTaskOrEvent(ThreadExecutionState* thread_exec_state,
(base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds(); (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds();
} }
void JankMonitor::StartTimerIfNecessary() { void JankMonitorImpl::StartTimerIfNecessary() {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
// |timer_| is already destroyed. This function is posted from UI or IO thread // |timer_| is already destroyed. This function is posted from UI or IO thread
...@@ -177,12 +187,12 @@ void JankMonitor::StartTimerIfNecessary() { ...@@ -177,12 +187,12 @@ void JankMonitor::StartTimerIfNecessary() {
// RepeatingClosure bound to the timer doesn't hold a ref to |this| because // RepeatingClosure bound to the timer doesn't hold a ref to |this| because
// the ref will only be released on timer destruction. // the ref will only be released on timer destruction.
timer_->Start(FROM_HERE, monitor_check_interval, timer_->Start(FROM_HERE, monitor_check_interval,
base::BindRepeating(&JankMonitor::OnCheckJankiness, base::BindRepeating(&JankMonitorImpl::OnCheckJankiness,
base::Unretained(this))); base::Unretained(this)));
timer_running_ = true; timer_running_ = true;
} }
void JankMonitor::StopTimerIfIdle() { void JankMonitorImpl::StopTimerIfIdle() {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
DCHECK(timer_->IsRunning()); DCHECK(timer_->IsRunning());
...@@ -194,11 +204,11 @@ void JankMonitor::StopTimerIfIdle() { ...@@ -194,11 +204,11 @@ void JankMonitor::StopTimerIfIdle() {
timer_running_ = false; timer_running_ = false;
} }
std::unique_ptr<MetricSource> JankMonitor::CreateMetricSource () { std::unique_ptr<MetricSource> JankMonitorImpl::CreateMetricSource() {
return std::make_unique<MetricSource>(this); return std::make_unique<MetricSource>(this);
} }
void JankMonitor::DestroyOnMonitorThread() { void JankMonitorImpl::DestroyOnMonitorThread() {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
DCHECK(timer_); DCHECK(timer_);
...@@ -207,11 +217,11 @@ void JankMonitor::DestroyOnMonitorThread() { ...@@ -207,11 +217,11 @@ void JankMonitor::DestroyOnMonitorThread() {
timer_running_ = false; timer_running_ = false;
} }
bool JankMonitor::timer_running() const { bool JankMonitorImpl::timer_running() const {
return timer_running_; return timer_running_;
} }
void JankMonitor::OnCheckJankiness() { void JankMonitorImpl::OnCheckJankiness() {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
if (janky_task_id_) { if (janky_task_id_) {
...@@ -236,17 +246,17 @@ void JankMonitor::OnCheckJankiness() { ...@@ -236,17 +246,17 @@ void JankMonitor::OnCheckJankiness() {
StopTimerIfIdle(); StopTimerIfIdle();
} }
void JankMonitor::OnJankStarted(const void* opaque_identifier) { void JankMonitorImpl::OnJankStarted(const void* opaque_identifier) {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
janky_task_id_ = opaque_identifier; janky_task_id_ = opaque_identifier;
base::AutoLock auto_lock(observers_lock_); base::AutoLock auto_lock(observers_lock_);
for (Observer& observer : observers_) for (content::JankMonitor::Observer& observer : observers_)
observer.OnJankStarted(); observer.OnJankStarted();
} }
void JankMonitor::OnJankStopped(const void* opaque_identifier) { void JankMonitorImpl::OnJankStopped(const void* opaque_identifier) {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
DCHECK_NE(opaque_identifier, nullptr); DCHECK_NE(opaque_identifier, nullptr);
if (janky_task_id_ != opaque_identifier) if (janky_task_id_ != opaque_identifier)
...@@ -255,34 +265,34 @@ void JankMonitor::OnJankStopped(const void* opaque_identifier) { ...@@ -255,34 +265,34 @@ void JankMonitor::OnJankStopped(const void* opaque_identifier) {
janky_task_id_ = nullptr; janky_task_id_ = nullptr;
base::AutoLock auto_lock(observers_lock_); base::AutoLock auto_lock(observers_lock_);
for (Observer& observer : observers_) for (content::JankMonitor::Observer& observer : observers_)
observer.OnJankStopped(); observer.OnJankStopped();
} }
void JankMonitor::NotifyJankStopIfNecessary(const void* opaque_identifier) { void JankMonitorImpl::NotifyJankStopIfNecessary(const void* opaque_identifier) {
if (LIKELY(!janky_task_id_ || janky_task_id_ != opaque_identifier)) { if (LIKELY(!janky_task_id_ || janky_task_id_ != opaque_identifier)) {
// Most tasks are unlikely to be janky. // Most tasks are unlikely to be janky.
return; return;
} }
monitor_task_runner_->PostTask( monitor_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&JankMonitor::OnJankStopped, FROM_HERE, base::BindOnce(&JankMonitorImpl::OnJankStopped,
base::RetainedRef(this), opaque_identifier)); base::RetainedRef(this), opaque_identifier));
} }
JankMonitor::ThreadExecutionState::TaskMetadata::~TaskMetadata() = default; JankMonitorImpl::ThreadExecutionState::TaskMetadata::~TaskMetadata() = default;
JankMonitor::ThreadExecutionState::ThreadExecutionState() { JankMonitorImpl::ThreadExecutionState::ThreadExecutionState() {
// Constructor is always on the UI thread. Detach |target_sequence_checker_| // Constructor is always on the UI thread. Detach |target_sequence_checker_|
// to make it work on IO thread. // to make it work on IO thread.
DETACH_FROM_SEQUENCE(target_sequence_checker_); DETACH_FROM_SEQUENCE(target_sequence_checker_);
DETACH_FROM_SEQUENCE(monitor_sequence_checker_); DETACH_FROM_SEQUENCE(monitor_sequence_checker_);
} }
JankMonitor::ThreadExecutionState::~ThreadExecutionState() = default; JankMonitorImpl::ThreadExecutionState::~ThreadExecutionState() = default;
base::Optional<const void*> base::Optional<const void*>
JankMonitor::ThreadExecutionState::CheckJankiness() { JankMonitorImpl::ThreadExecutionState::CheckJankiness() {
DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_checker_);
base::TimeTicks now = base::TimeTicks::Now(); base::TimeTicks now = base::TimeTicks::Now();
...@@ -301,7 +311,7 @@ JankMonitor::ThreadExecutionState::CheckJankiness() { ...@@ -301,7 +311,7 @@ JankMonitor::ThreadExecutionState::CheckJankiness() {
return task_execution_metadata_.back().identifier; return task_execution_metadata_.back().identifier;
} }
void JankMonitor::ThreadExecutionState::WillRunTaskOrEvent( void JankMonitorImpl::ThreadExecutionState::WillRunTaskOrEvent(
const void* opaque_identifier) { const void* opaque_identifier) {
AssertOnTargetThread(); AssertOnTargetThread();
...@@ -311,7 +321,7 @@ void JankMonitor::ThreadExecutionState::WillRunTaskOrEvent( ...@@ -311,7 +321,7 @@ void JankMonitor::ThreadExecutionState::WillRunTaskOrEvent(
task_execution_metadata_.emplace_back(now, opaque_identifier); task_execution_metadata_.emplace_back(now, opaque_identifier);
} }
void JankMonitor::ThreadExecutionState::DidRunTaskOrEvent( void JankMonitorImpl::ThreadExecutionState::DidRunTaskOrEvent(
const void* opaque_identifier) { const void* opaque_identifier) {
AssertOnTargetThread(); AssertOnTargetThread();
...@@ -331,7 +341,7 @@ void JankMonitor::ThreadExecutionState::DidRunTaskOrEvent( ...@@ -331,7 +341,7 @@ void JankMonitor::ThreadExecutionState::DidRunTaskOrEvent(
task_execution_metadata_.pop_back(); task_execution_metadata_.pop_back();
} }
void JankMonitor::ThreadExecutionState::AssertOnTargetThread() { void JankMonitorImpl::ThreadExecutionState::AssertOnTargetThread() {
DCHECK_CALLED_ON_VALID_SEQUENCE(target_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(target_sequence_checker_);
} }
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_H_ #ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_
#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_H_ #define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_
#include <atomic> #include <atomic>
...@@ -17,71 +17,24 @@ ...@@ -17,71 +17,24 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "content/browser/scheduler/responsiveness/metric_source.h" #include "content/browser/scheduler/responsiveness/metric_source.h"
#include "content/public/browser/jank_monitor.h"
namespace content { namespace content {
namespace responsiveness { namespace responsiveness {
// This class monitors the responsiveness of the browser to notify the presence
// of janks to its observers. A jank is defined as a task or native event
// running for longer than a threshold on the UI or IO thread. An observer of
// this class is notified through the Observer interface on jank starts/stops so
// the observer can take actions (e.g. gather system-wide profile to capture the
// jank) *before* the janky task finishes execution. Notifications are sent on a
// dedicated sequence internal to this class so the observer needs to be careful
// with threading. For example, access to browser-related objects requires
// posting a task to the UI thread.
//
// Internally, a timer (bound to the monitor sequence) is used to perform
// periodic checks to decide the presence of janks. When a jank is detected, the
// monitor notifies its observers that a jank has started (through the
// Observer::OnJankStarted() method). The start of a jank is imprecise w.r.t.
// the jank threshold. When a janky task has finished execution, the monitor
// notifies the observers ASAP (through the Observer::OnJankStopped() method).
//
// Usage example:
//
// class Profiler : public Observer {
// public:
// void OnJankStarted() override; // Start the profiler.
// void OnJankStopped() override; // Stop the profiler.
// }
// Profiler* profiler = ...;
//
// scoped_refptr<JankMonitor> monitor = base::MakeRefCounted<JankMonitor>();
// monitor->SetUp();
// monitor->AddObserver(profiler);
//
// (Then start receiving notifications in Profiler::OnJankStarted() and
// Profiler::OnJankStopped()).
class CONTENT_EXPORT JankMonitor
: public base::RefCountedThreadSafe<JankMonitor>,
public content::responsiveness::MetricSource::Delegate {
public:
// Interface for observing janky tasks from the monitor. Note that the
// callbacks are called *off* the UI thread. Post a task to the UI thread is
// necessary if you need to access browser-related objects.
class CONTENT_EXPORT Observer {
public:
virtual ~Observer();
virtual void OnJankStarted() = 0;
virtual void OnJankStopped() = 0;
};
JankMonitor();
void SetUp(); class CONTENT_EXPORT JankMonitorImpl : public content::JankMonitor,
void Destroy(); public MetricSource::Delegate {
public:
JankMonitorImpl();
// AddObserver() and RemoveObserver() can be called on any sequence, but the // JankMonitor implementation:
// notifications only take place on the monitor sequence. Note: do *not* call void AddObserver(content::JankMonitor::Observer* observer) override;
// AddObserver() or RemoveObserver() synchronously in the observer callbacks, void RemoveObserver(content::JankMonitor::Observer* observer) override;
// or undefined behavior will result. void SetUp() override;
void AddObserver(Observer* observer); void Destroy() override;
void RemoveObserver(Observer* observer);
protected: protected:
friend class base::RefCountedThreadSafe<JankMonitor>; ~JankMonitorImpl() override;
~JankMonitor() override;
// MetricSource::Delegate implementation. // MetricSource::Delegate implementation.
void SetUpOnIOThread() override; void SetUpOnIOThread() override;
...@@ -206,4 +159,4 @@ class CONTENT_EXPORT JankMonitor ...@@ -206,4 +159,4 @@ class CONTENT_EXPORT JankMonitor
} // namespace responsiveness. } // namespace responsiveness.
} // namespace content. } // namespace content.
#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_H_ #endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "content/browser/scheduler/responsiveness/jank_monitor.h" #include "content/browser/scheduler/responsiveness/jank_monitor_impl.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback.h" #include "base/callback.h"
...@@ -33,8 +33,7 @@ class TestObserver : public JankMonitor::Observer { ...@@ -33,8 +33,7 @@ class TestObserver : public JankMonitor::Observer {
class TestMetricSource : public MetricSource { class TestMetricSource : public MetricSource {
public: public:
TestMetricSource(Delegate* delegate) explicit TestMetricSource(Delegate* delegate) : MetricSource(delegate) {}
: MetricSource(delegate) {}
~TestMetricSource() override {} ~TestMetricSource() override {}
std::unique_ptr<NativeEventObserver> CreateNativeEventObserver() override { std::unique_ptr<NativeEventObserver> CreateNativeEventObserver() override {
...@@ -42,7 +41,7 @@ class TestMetricSource : public MetricSource { ...@@ -42,7 +41,7 @@ class TestMetricSource : public MetricSource {
} }
}; };
class TestJankMonitor : public JankMonitor { class TestJankMonitor : public JankMonitorImpl {
public: public:
TestJankMonitor() {} TestJankMonitor() {}
...@@ -54,7 +53,7 @@ class TestJankMonitor : public JankMonitor { ...@@ -54,7 +53,7 @@ class TestJankMonitor : public JankMonitor {
on_destroyed_ = std::move(on_destroyed); on_destroyed_ = std::move(on_destroyed);
} }
using JankMonitor::timer_running; using JankMonitorImpl::timer_running;
protected: protected:
~TestJankMonitor() override { ~TestJankMonitor() override {
...@@ -68,7 +67,7 @@ class TestJankMonitor : public JankMonitor { ...@@ -68,7 +67,7 @@ class TestJankMonitor : public JankMonitor {
void DestroyOnMonitorThread() override { void DestroyOnMonitorThread() override {
destroy_on_monitor_thread_called_ = true; destroy_on_monitor_thread_called_ = true;
JankMonitor::DestroyOnMonitorThread(); JankMonitorImpl::DestroyOnMonitorThread();
} }
private: private:
...@@ -230,7 +229,7 @@ TEST_F(JankMonitorTest, JankUIThreadReentrant) { ...@@ -230,7 +229,7 @@ TEST_F(JankMonitorTest, JankUIThreadReentrant) {
TEST_F(JankMonitorTest, ReentrantResponsive) { TEST_F(JankMonitorTest, ReentrantResponsive) {
auto enclosing_task = [&]() { auto enclosing_task = [&]() {
// Run 5 responsive tasks in the inner runloop. // Run 5 responsive tasks in the inner runloop.
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
auto nested_responsive_task = [&]() { auto nested_responsive_task = [&]() {
task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(999)); task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(999));
...@@ -357,14 +356,14 @@ TEST_F(JankMonitorTest, StartStopTimer) { ...@@ -357,14 +356,14 @@ TEST_F(JankMonitorTest, StartStopTimer) {
EXPECT_FALSE(monitor_->timer_running()); EXPECT_FALSE(monitor_->timer_running());
} }
class TestJankMonitorShutdownRace : public JankMonitor { class TestJankMonitorShutdownRace : public JankMonitorImpl {
public: public:
TestJankMonitorShutdownRace(base::WaitableEvent* shutdown_on_monitor_thread, TestJankMonitorShutdownRace(base::WaitableEvent* shutdown_on_monitor_thread,
base::WaitableEvent* shutdown_on_ui_thread) base::WaitableEvent* shutdown_on_ui_thread)
: shutdown_on_monitor_thread_(shutdown_on_monitor_thread), : shutdown_on_monitor_thread_(shutdown_on_monitor_thread),
shutdown_on_ui_thread_(shutdown_on_ui_thread) {} shutdown_on_ui_thread_(shutdown_on_ui_thread) {}
using JankMonitor::timer_running; using JankMonitorImpl::timer_running;
protected: protected:
~TestJankMonitorShutdownRace() override = default; ~TestJankMonitorShutdownRace() override = default;
...@@ -374,7 +373,7 @@ class TestJankMonitorShutdownRace : public JankMonitor { ...@@ -374,7 +373,7 @@ class TestJankMonitorShutdownRace : public JankMonitor {
} }
void DestroyOnMonitorThread() override { void DestroyOnMonitorThread() override {
JankMonitor::DestroyOnMonitorThread(); JankMonitorImpl::DestroyOnMonitorThread();
// Posts a task to the UI thread. Note that we run concurrently with the // Posts a task to the UI thread. Note that we run concurrently with the
// destruction of MetricSource. Even if MetricSource is still active and // destruction of MetricSource. Even if MetricSource is still active and
...@@ -387,7 +386,7 @@ class TestJankMonitorShutdownRace : public JankMonitor { ...@@ -387,7 +386,7 @@ class TestJankMonitorShutdownRace : public JankMonitor {
} }
void FinishDestroyMetricSource() override { void FinishDestroyMetricSource() override {
JankMonitor::FinishDestroyMetricSource(); JankMonitorImpl::FinishDestroyMetricSource();
shutdown_on_ui_thread_->Signal(); shutdown_on_ui_thread_->Signal();
} }
...@@ -429,7 +428,7 @@ TEST(JankMonitorShutdownTest, ShutdownRace_TimerRestarted) { ...@@ -429,7 +428,7 @@ TEST(JankMonitorShutdownTest, ShutdownRace_TimerRestarted) {
EXPECT_FALSE(jank_monitor->timer_running()); EXPECT_FALSE(jank_monitor->timer_running());
} }
class TestJankMonitorShutdownRaceTimerFired : public JankMonitor { class TestJankMonitorShutdownRaceTimerFired : public JankMonitorImpl {
public: public:
TestJankMonitorShutdownRaceTimerFired( TestJankMonitorShutdownRaceTimerFired(
content::BrowserTaskEnvironment* task_environment) content::BrowserTaskEnvironment* task_environment)
...@@ -449,11 +448,11 @@ class TestJankMonitorShutdownRaceTimerFired : public JankMonitor { ...@@ -449,11 +448,11 @@ class TestJankMonitorShutdownRaceTimerFired : public JankMonitor {
// after MetricSource is destroyed. // after MetricSource is destroyed.
task_environment_->FastForwardBy(base::TimeDelta::FromMilliseconds(1)); task_environment_->FastForwardBy(base::TimeDelta::FromMilliseconds(1));
JankMonitor::FinishDestroyMetricSource(); JankMonitorImpl::FinishDestroyMetricSource();
} }
void OnCheckJankiness() override { void OnCheckJankiness() override {
JankMonitor::OnCheckJankiness(); JankMonitorImpl::OnCheckJankiness();
monitor_timer_fired_ = true; monitor_timer_fired_ = true;
} }
......
...@@ -193,6 +193,7 @@ source_set("browser_sources") { ...@@ -193,6 +193,7 @@ source_set("browser_sources") {
"installed_payment_apps_finder.h", "installed_payment_apps_finder.h",
"invalidate_type.h", "invalidate_type.h",
"is_uvpaa.h", "is_uvpaa.h",
"jank_monitor.h",
"javascript_dialog_manager.cc", "javascript_dialog_manager.cc",
"javascript_dialog_manager.h", "javascript_dialog_manager.h",
"keyboard_event_processing_result.h", "keyboard_event_processing_result.h",
......
...@@ -65,6 +65,11 @@ class CONTENT_EXPORT BrowserAccessibilityState { ...@@ -65,6 +65,11 @@ class CONTENT_EXPORT BrowserAccessibilityState {
// thread, for example something that may block or run slowly. // thread, for example something that may block or run slowly.
virtual void AddOtherThreadHistogramCallback(base::OnceClosure callback) = 0; virtual void AddOtherThreadHistogramCallback(base::OnceClosure callback) = 0;
// Fire frequent metrics signals to ensure users keeping browser open multiple
// days are counted each day, not only at launch. This is necessary, because
// UMA only aggregates uniques on a daily basis,
virtual void UpdateUniqueUserHistograms() = 0;
virtual void UpdateHistogramsForTesting() = 0; virtual void UpdateHistogramsForTesting() = 0;
// Update BrowserAccessibilityState with the current status of caret browsing. // Update BrowserAccessibilityState with the current status of caret browsing.
......
// Copyright 2020 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 CONTENT_PUBLIC_BROWSER_JANK_MONITOR_H_
#define CONTENT_PUBLIC_BROWSER_JANK_MONITOR_H_
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
namespace content {
// This class monitors the responsiveness of the browser to notify the presence
// of janks to its observers. A jank is defined as a task or native event
// running for longer than a threshold on the UI or IO thread. An observer of
// this class is notified through the Observer interface on jank starts/stops so
// the observer can take actions (e.g. gather system-wide profile to capture the
// jank) *before* the janky task finishes execution. Notifications are sent on a
// dedicated sequence internal to this class so the observer needs to be careful
// with threading. For example, access to browser-related objects requires
// posting a task to the UI thread.
//
// Internally, a timer (bound to the monitor sequence) is used to perform
// periodic checks to decide the presence of janks. When a jank is detected, the
// monitor notifies its observers that a jank has started (through the
// Observer::OnJankStarted() method). The start of a jank is imprecise w.r.t.
// the jank threshold. When a janky task has finished execution, the monitor
// notifies the observers ASAP (through the Observer::OnJankStopped() method).
//
// Usage example:
//
// class Profiler : public Observer {
// public:
// void OnJankStarted() override; // Start the profiler.
// void OnJankStopped() override; // Stop the profiler.
// }
// Profiler* profiler = ...;
//
// scoped_refptr<JankMonitor> monitor = JankMonitor::Create();
// monitor->SetUp();
// monitor->AddObserver(profiler);
//
// (Then start receiving notifications in Profiler::OnJankStarted() and
// Profiler::OnJankStopped()).
class CONTENT_EXPORT JankMonitor
: public base::RefCountedThreadSafe<JankMonitor> {
public:
// Interface for observing janky tasks from the monitor. Note that the
// callbacks are called *off* the UI thread. Post a task to the UI thread is
// necessary if you need to access browser-related objects.
class CONTENT_EXPORT Observer {
public:
virtual ~Observer();
virtual void OnJankStarted() = 0;
virtual void OnJankStopped() = 0;
};
static scoped_refptr<JankMonitor> Create();
// AddObserver() and RemoveObserver() can be called on any sequence, but the
// notifications only take place on the monitor sequence. Note: do *not* call
// AddObserver() or RemoveObserver() synchronously in the observer callbacks,
// or undefined behavior will result.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
virtual void SetUp() = 0;
virtual void Destroy() = 0;
protected:
friend class base::RefCountedThreadSafe<JankMonitor>;
virtual ~JankMonitor();
};
} // namespace content.
#endif // CONTENT_PUBLIC_BROWSER_JANK_MONITOR_H_
...@@ -1913,7 +1913,7 @@ test("content_unittests") { ...@@ -1913,7 +1913,7 @@ test("content_unittests") {
"../browser/scheduler/browser_task_queues_unittest.cc", "../browser/scheduler/browser_task_queues_unittest.cc",
"../browser/scheduler/browser_ui_thread_scheduler_unittest.cc", "../browser/scheduler/browser_ui_thread_scheduler_unittest.cc",
"../browser/scheduler/responsiveness/calculator_unittest.cc", "../browser/scheduler/responsiveness/calculator_unittest.cc",
"../browser/scheduler/responsiveness/jank_monitor_unittest.cc", "../browser/scheduler/responsiveness/jank_monitor_impl_unittest.cc",
"../browser/scheduler/responsiveness/metric_source_unittest.cc", "../browser/scheduler/responsiveness/metric_source_unittest.cc",
"../browser/scheduler/responsiveness/watcher_unittest.cc", "../browser/scheduler/responsiveness/watcher_unittest.cc",
"../browser/screen_orientation/screen_orientation_provider_unittest.cc", "../browser/screen_orientation/screen_orientation_provider_unittest.cc",
......
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