1 // Copyright 2019 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 "services/tracing/public/cpp/traced_process_impl.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/no_destructor.h"
11 #include "base/task/thread_pool/thread_pool_instance.h"
12 #include "services/tracing/public/cpp/base_agent.h"
13 #include "services/tracing/public/cpp/perfetto/producer_client.h"
14 #include "services/tracing/public/cpp/trace_event_agent.h"
15 #include "services/tracing/public/mojom/constants.mojom.h"
16 
17 namespace tracing {
18 
19 // static
GetInstance()20 TracedProcessImpl* TracedProcessImpl::GetInstance() {
21   static base::NoDestructor<TracedProcessImpl> traced_process;
22   return traced_process.get();
23 }
24 
TracedProcessImpl()25 TracedProcessImpl::TracedProcessImpl() {
26   DETACH_FROM_SEQUENCE(sequence_checker_);
27 }
28 
29 TracedProcessImpl::~TracedProcessImpl() = default;
30 
ResetTracedProcessReceiver()31 void TracedProcessImpl::ResetTracedProcessReceiver() {
32   if (task_runner_ && !task_runner_->RunsTasksInCurrentSequence()) {
33     task_runner_->PostTask(
34         FROM_HERE,
35         base::BindOnce(&TracedProcessImpl::ResetTracedProcessReceiver,
36                        base::Unretained(this)));
37     return;
38   }
39 
40   receiver_.reset();
41 }
42 
OnTracedProcessRequest(mojo::PendingReceiver<mojom::TracedProcess> receiver)43 void TracedProcessImpl::OnTracedProcessRequest(
44     mojo::PendingReceiver<mojom::TracedProcess> receiver) {
45   if (task_runner_ && !task_runner_->RunsTasksInCurrentSequence()) {
46     task_runner_->PostTask(
47         FROM_HERE, base::BindOnce(&TracedProcessImpl::OnTracedProcessRequest,
48                                   base::Unretained(this), std::move(receiver)));
49     return;
50   }
51 
52   // We only need one binding per process. If a new binding request is made,
53   // ignore it.
54   if (receiver_.is_bound())
55     return;
56 
57   receiver_.Bind(std::move(receiver));
58 }
59 
60 // SetTaskRunner must be called before we start receiving
61 // any OnTracedProcessRequest calls.
SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner)62 void TracedProcessImpl::SetTaskRunner(
63     scoped_refptr<base::SequencedTaskRunner> task_runner) {
64   DCHECK(!receiver_.is_bound());
65   DCHECK(!task_runner_);
66   task_runner_ = task_runner;
67 }
68 
RegisterAgent(BaseAgent * agent)69 void TracedProcessImpl::RegisterAgent(BaseAgent* agent) {
70   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
71 
72   agents_.insert(agent);
73 }
74 
UnregisterAgent(BaseAgent * agent)75 void TracedProcessImpl::UnregisterAgent(BaseAgent* agent) {
76   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
77   agents_.erase(agent);
78 }
79 
ConnectToTracingService(mojom::ConnectToTracingRequestPtr request,ConnectToTracingServiceCallback callback)80 void TracedProcessImpl::ConnectToTracingService(
81     mojom::ConnectToTracingRequestPtr request,
82     ConnectToTracingServiceCallback callback) {
83   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
84 
85   // Acknowledge this message so the tracing service knows it was dispatched in
86   // this process.
87   std::move(callback).Run();
88 
89   // Tracing requires a running ThreadPool; disable tracing
90   // for processes without it.
91   if (!base::ThreadPoolInstance::Get()) {
92     return;
93   }
94 
95   // Ensure the TraceEventAgent has been created.
96   TraceEventAgent::GetInstance();
97 
98   PerfettoTracedProcess::Get()->ConnectProducer(
99       std::move(request->perfetto_service));
100 }
101 
GetCategories(std::set<std::string> * category_set)102 void TracedProcessImpl::GetCategories(std::set<std::string>* category_set) {
103   for (auto* agent : agents_) {
104     agent->GetCategories(category_set);
105   }
106 }
107 
108 }  // namespace tracing
109