blob: 545035103ee574a9b239b711481d67188e67cbfc [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2014 The Chromium Authors
[email protected]e6e30ac2014-01-13 21:24:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/metrics/user_metrics.h"
6
avi9b6f42932015-12-26 22:15:147#include <stddef.h>
8
Peter Kasting025a94252025-01-29 21:28:379#include <algorithm>
[email protected]e6e30ac2014-01-13 21:24:3910#include <vector>
11
Avi Drissman63e1f992023-01-13 18:54:4312#include "base/functional/bind.h"
[email protected]e6e30ac2014-01-13 21:24:3913#include "base/lazy_instance.h"
beaudoind5c435e2016-04-22 14:17:1014#include "base/location.h"
[email protected]abca0982014-04-10 01:12:3615#include "base/threading/thread_checker.h"
bttkc8a31b702020-02-25 02:55:1716#include "base/time/time.h"
Etienne Pierre-dorayf0096f082025-06-12 22:35:1017#include "base/trace_event/user_action.h"
[email protected]e6e30ac2014-01-13 21:24:3918
19namespace base {
20namespace {
21
scottmg5e65e3a2017-03-08 08:48:4622LazyInstance<std::vector<ActionCallback>>::DestructorAtExit g_callbacks =
beaudoind5c435e2016-04-22 14:17:1023 LAZY_INSTANCE_INITIALIZER;
scottmg5e65e3a2017-03-08 08:48:4624LazyInstance<scoped_refptr<SingleThreadTaskRunner>>::DestructorAtExit
25 g_task_runner = LAZY_INSTANCE_INITIALIZER;
[email protected]e6e30ac2014-01-13 21:24:3926
Etienne Pierre-dorayf0096f082025-06-12 22:35:1027void DispatchAction(const std::string& action, TimeTicks action_time) {
28 for (const ActionCallback& callback : g_callbacks.Get()) {
29 callback.Run(action, action_time);
30 }
31}
32
[email protected]e6e30ac2014-01-13 21:24:3933} // namespace
34
35void RecordAction(const UserMetricsAction& action) {
beaudoind5c435e2016-04-22 14:17:1036 RecordComputedAction(action.str_);
[email protected]e6e30ac2014-01-13 21:24:3937}
38
39void RecordComputedAction(const std::string& action) {
bttkc8a31b702020-02-25 02:55:1740 RecordComputedActionAt(action, TimeTicks::Now());
41}
42
bttk211b8512020-03-18 04:24:0143void RecordComputedActionSince(const std::string& action,
44 TimeDelta time_since) {
45 RecordComputedActionAt(action, TimeTicks::Now() - time_since);
46}
47
bttkc8a31b702020-02-25 02:55:1748void RecordComputedActionAt(const std::string& action, TimeTicks action_time) {
Etienne Pierre-dorayf0096f082025-06-12 22:35:1049 trace_event::EmitUserActionEvent(action, action_time);
50
beaudoind5c435e2016-04-22 14:17:1051 if (!g_task_runner.Get()) {
52 DCHECK(g_callbacks.Get().empty());
53 return;
54 }
55
56 if (!g_task_runner.Get()->BelongsToCurrentThread()) {
bttkc8a31b702020-02-25 02:55:1757 g_task_runner.Get()->PostTask(
Etienne Pierre-dorayf0096f082025-06-12 22:35:1058 FROM_HERE, BindOnce(&DispatchAction, action, action_time));
beaudoind5c435e2016-04-22 14:17:1059 return;
60 }
61
Etienne Pierre-dorayf0096f082025-06-12 22:35:1062 DispatchAction(action, action_time);
[email protected]e6e30ac2014-01-13 21:24:3963}
64
65void AddActionCallback(const ActionCallback& callback) {
beaudoind5c435e2016-04-22 14:17:1066 // Only allow adding a callback if the task runner is set.
67 DCHECK(g_task_runner.Get());
68 DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
69 g_callbacks.Get().push_back(callback);
[email protected]e6e30ac2014-01-13 21:24:3970}
71
72void RemoveActionCallback(const ActionCallback& callback) {
beaudoind5c435e2016-04-22 14:17:1073 DCHECK(g_task_runner.Get());
74 DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
75 std::vector<ActionCallback>* callbacks = g_callbacks.Pointer();
Peter Kasting025a94252025-01-29 21:28:3776 const auto i = std::ranges::find(*callbacks, callback);
Peter Kasting134ef9af2024-12-28 02:30:0977 if (i != callbacks->end()) {
Peter Kastingfc94f5062022-06-08 16:41:4578 callbacks->erase(i);
Peter Kasting134ef9af2024-12-28 02:30:0979 }
beaudoind5c435e2016-04-22 14:17:1080}
[email protected]abca0982014-04-10 01:12:3681
beaudoind5c435e2016-04-22 14:17:1082void SetRecordActionTaskRunner(
83 scoped_refptr<SingleThreadTaskRunner> task_runner) {
84 DCHECK(task_runner->BelongsToCurrentThread());
85 DCHECK(!g_task_runner.Get() || g_task_runner.Get()->BelongsToCurrentThread());
86 g_task_runner.Get() = task_runner;
[email protected]e6e30ac2014-01-13 21:24:3987}
88
ssid70aefba42020-02-04 19:34:0389scoped_refptr<SingleThreadTaskRunner> GetRecordActionTaskRunner() {
Peter Kasting134ef9af2024-12-28 02:30:0990 if (g_task_runner.IsCreated()) {
ssid70aefba42020-02-04 19:34:0391 return g_task_runner.Get();
Peter Kasting134ef9af2024-12-28 02:30:0992 }
ssid70aefba42020-02-04 19:34:0393 return nullptr;
94}
95
[email protected]e6e30ac2014-01-13 21:24:3996} // namespace base