1// Copyright 2014 The Chromium Authors. All rights reserved.
2// 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
7#include <stddef.h>
8
9#include <vector>
10
11#include "base/bind.h"
12#include "base/lazy_instance.h"
13#include "base/location.h"
14#include "base/macros.h"
15#include "base/threading/thread_checker.h"
16
17namespace base {
18namespace {
19
20LazyInstance<std::vector<ActionCallback>> g_callbacks =
21    LAZY_INSTANCE_INITIALIZER;
22LazyInstance<scoped_refptr<SingleThreadTaskRunner>> g_task_runner =
23    LAZY_INSTANCE_INITIALIZER;
24
25}  // namespace
26
27void RecordAction(const UserMetricsAction& action) {
28  RecordComputedAction(action.str_);
29}
30
31void RecordComputedAction(const std::string& action) {
32  if (!g_task_runner.Get()) {
33    DCHECK(g_callbacks.Get().empty());
34    return;
35  }
36
37  if (!g_task_runner.Get()->BelongsToCurrentThread()) {
38    g_task_runner.Get()->PostTask(FROM_HERE,
39                                  Bind(&RecordComputedAction, action));
40    return;
41  }
42
43  for (const ActionCallback& callback : g_callbacks.Get()) {
44    callback.Run(action);
45  }
46}
47
48void AddActionCallback(const ActionCallback& callback) {
49  // Only allow adding a callback if the task runner is set.
50  DCHECK(g_task_runner.Get());
51  DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
52  g_callbacks.Get().push_back(callback);
53}
54
55void RemoveActionCallback(const ActionCallback& callback) {
56  DCHECK(g_task_runner.Get());
57  DCHECK(g_task_runner.Get()->BelongsToCurrentThread());
58  std::vector<ActionCallback>* callbacks = g_callbacks.Pointer();
59  for (size_t i = 0; i < callbacks->size(); ++i) {
60    if ((*callbacks)[i].Equals(callback)) {
61      callbacks->erase(callbacks->begin() + i);
62      return;
63    }
64  }
65}
66
67void SetRecordActionTaskRunner(
68    scoped_refptr<SingleThreadTaskRunner> task_runner) {
69  DCHECK(task_runner->BelongsToCurrentThread());
70  DCHECK(!g_task_runner.Get() || g_task_runner.Get()->BelongsToCurrentThread());
71  g_task_runner.Get() = task_runner;
72}
73
74}  // namespace base
75