1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/metrics/user_metrics.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <vector>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace base {
20*6777b538SAndroid Build Coastguard Worker namespace {
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker LazyInstance<std::vector<ActionCallback>>::DestructorAtExit g_callbacks =
23*6777b538SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
24*6777b538SAndroid Build Coastguard Worker LazyInstance<scoped_refptr<SingleThreadTaskRunner>>::DestructorAtExit
25*6777b538SAndroid Build Coastguard Worker g_task_runner = LAZY_INSTANCE_INITIALIZER;
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker } // namespace
28*6777b538SAndroid Build Coastguard Worker
RecordAction(const UserMetricsAction & action)29*6777b538SAndroid Build Coastguard Worker void RecordAction(const UserMetricsAction& action) {
30*6777b538SAndroid Build Coastguard Worker RecordComputedAction(action.str_);
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
RecordComputedAction(const std::string & action)33*6777b538SAndroid Build Coastguard Worker void RecordComputedAction(const std::string& action) {
34*6777b538SAndroid Build Coastguard Worker RecordComputedActionAt(action, TimeTicks::Now());
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
RecordComputedActionSince(const std::string & action,TimeDelta time_since)37*6777b538SAndroid Build Coastguard Worker void RecordComputedActionSince(const std::string& action,
38*6777b538SAndroid Build Coastguard Worker TimeDelta time_since) {
39*6777b538SAndroid Build Coastguard Worker RecordComputedActionAt(action, TimeTicks::Now() - time_since);
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker
RecordComputedActionAt(const std::string & action,TimeTicks action_time)42*6777b538SAndroid Build Coastguard Worker void RecordComputedActionAt(const std::string& action, TimeTicks action_time) {
43*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT1("ui", "UserEvent", TRACE_EVENT_SCOPE_GLOBAL, "action",
44*6777b538SAndroid Build Coastguard Worker action);
45*6777b538SAndroid Build Coastguard Worker if (!g_task_runner.Get()) {
46*6777b538SAndroid Build Coastguard Worker DCHECK(g_callbacks.Get().empty());
47*6777b538SAndroid Build Coastguard Worker return;
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker if (!g_task_runner.Get()->BelongsToCurrentThread()) {
51*6777b538SAndroid Build Coastguard Worker g_task_runner.Get()->PostTask(
52*6777b538SAndroid Build Coastguard Worker FROM_HERE, BindOnce(&RecordComputedActionAt, action, action_time));
53*6777b538SAndroid Build Coastguard Worker return;
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker for (const ActionCallback& callback : g_callbacks.Get()) {
57*6777b538SAndroid Build Coastguard Worker callback.Run(action, action_time);
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
AddActionCallback(const ActionCallback & callback)61*6777b538SAndroid Build Coastguard Worker void AddActionCallback(const ActionCallback& callback) {
62*6777b538SAndroid Build Coastguard Worker // Only allow adding a callback if the task runner is set.
63*6777b538SAndroid Build Coastguard Worker DCHECK(g_task_runner.Get());
64*6777b538SAndroid Build Coastguard Worker DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
65*6777b538SAndroid Build Coastguard Worker g_callbacks.Get().push_back(callback);
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker
RemoveActionCallback(const ActionCallback & callback)68*6777b538SAndroid Build Coastguard Worker void RemoveActionCallback(const ActionCallback& callback) {
69*6777b538SAndroid Build Coastguard Worker DCHECK(g_task_runner.Get());
70*6777b538SAndroid Build Coastguard Worker DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
71*6777b538SAndroid Build Coastguard Worker std::vector<ActionCallback>* callbacks = g_callbacks.Pointer();
72*6777b538SAndroid Build Coastguard Worker const auto i = ranges::find(*callbacks, callback);
73*6777b538SAndroid Build Coastguard Worker if (i != callbacks->end())
74*6777b538SAndroid Build Coastguard Worker callbacks->erase(i);
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker
SetRecordActionTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner)77*6777b538SAndroid Build Coastguard Worker void SetRecordActionTaskRunner(
78*6777b538SAndroid Build Coastguard Worker scoped_refptr<SingleThreadTaskRunner> task_runner) {
79*6777b538SAndroid Build Coastguard Worker DCHECK(task_runner->BelongsToCurrentThread());
80*6777b538SAndroid Build Coastguard Worker DCHECK(!g_task_runner.Get() || g_task_runner.Get()->BelongsToCurrentThread());
81*6777b538SAndroid Build Coastguard Worker g_task_runner.Get() = task_runner;
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
GetRecordActionTaskRunner()84*6777b538SAndroid Build Coastguard Worker scoped_refptr<SingleThreadTaskRunner> GetRecordActionTaskRunner() {
85*6777b538SAndroid Build Coastguard Worker if (g_task_runner.IsCreated())
86*6777b538SAndroid Build Coastguard Worker return g_task_runner.Get();
87*6777b538SAndroid Build Coastguard Worker return nullptr;
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker } // namespace base
91