1 // Copyright 2017 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 #ifndef CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_TRACING_BRIDGE_H_
6 #define CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_TRACING_BRIDGE_H_
7 
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include "base/callback_forward.h"
14 #include "base/containers/ring_buffer.h"
15 #include "base/files/file_descriptor_watcher_posix.h"
16 #include "base/files/scoped_file.h"
17 #include "base/macros.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/synchronization/lock.h"
20 #include "base/thread_annotations.h"
21 #include "components/arc/mojom/tracing.mojom-forward.h"
22 #include "components/arc/session/connection_observer.h"
23 #include "components/keyed_service/core/keyed_service.h"
24 #include "services/tracing/public/cpp/base_agent.h"
25 
26 namespace content {
27 class BrowserContext;
28 }  // namespace content
29 
30 namespace arc {
31 
32 class ArcBridgeService;
33 
34 // This class provides the interface to trigger tracing in the container.
35 class ArcTracingBridge : public KeyedService,
36                          public ConnectionObserver<mojom::TracingInstance> {
37  public:
38   // Returns singleton instance for the given BrowserContext,
39   // or nullptr if the browser |context| is not allowed to use ARC.
40   static ArcTracingBridge* GetForBrowserContext(
41       content::BrowserContext* context);
42 
43   ArcTracingBridge(content::BrowserContext* context,
44                    ArcBridgeService* bridge_service);
45   ~ArcTracingBridge() override;
46 
47   void GetCategories(std::set<std::string>* category_set);
48 
49   // ConnectionObserver<mojom::TracingInstance> overrides:
50   void OnConnectionReady() override;
51 
52   // State of the tracing activity of the bridge.
53   enum class State { kDisabled, kStarting, kEnabled, kStopping };
state()54   State state() const { return state_; }
55 
56   using SuccessCallback = base::OnceCallback<void(bool)>;
57   using TraceDataCallback = base::OnceCallback<void(const std::string& data)>;
58 
59   // Starts tracing and calls |callback| when started indicating whether tracing
60   // was started successfully via its parameter.
61   void StartTracing(const std::string& config, SuccessCallback callback);
62 
63   // Stops tracing and calls |callback| with the recorded trace data once
64   // stopped. If unsuccessful, calls |callback| with an empty data string.
65   void StopAndFlush(TraceDataCallback callback);
66 
67  private:
68   // TODO(crbug.com/839086): Remove once we have replaced the legacy tracing
69   // service with perfetto.
70   class ArcTracingAgent : public tracing::BaseAgent {
71    public:
72     explicit ArcTracingAgent(ArcTracingBridge* bridge);
73     ~ArcTracingAgent() override;
74 
75    private:
76     // tracing::BaseAgent.
77     void GetCategories(std::set<std::string>* category_set) override;
78 
79     ArcTracingBridge* const bridge_;
80 
81     DISALLOW_COPY_AND_ASSIGN(ArcTracingAgent);
82   };
83 
84   // A helper class for reading trace data from the client side. We separate
85   // this from |ArcTracingAgentImpl| to isolate the logic that runs on browser's
86   // IO thread. All the functions in this class except for constructor are
87   // expected to be run on browser's IO thread.
88   class ArcTracingReader {
89    public:
90     ArcTracingReader();
91     ~ArcTracingReader();
92 
93     // Starts reading trace data from the given file descriptor.
94     void StartTracing(base::ScopedFD read_fd);
95     // Stops reading and returns the collected trace data.
96     std::string StopTracing();
97 
98    private:
99     void OnTraceDataAvailable();
100 
101     // Number of events for the ring buffer.
102     static constexpr size_t kTraceEventBufferSize = 64000;
103 
104     base::ScopedFD read_fd_;
105     std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
106     base::RingBuffer<std::string, kTraceEventBufferSize> ring_buffer_;
107 
108     DISALLOW_COPY_AND_ASSIGN(ArcTracingReader);
109   };
110 
111   struct Category;
112 
113   // Callback for QueryAvailableCategories.
114   void OnCategoriesReady(const std::vector<std::string>& categories);
115 
116   void OnArcTracingStarted(SuccessCallback callback, bool success);
117   void OnArcTracingStopped(TraceDataCallback tracing_stopped_callback,
118                            bool success);
119   void OnTracingReaderStopped(TraceDataCallback tracing_stopped_callback,
120                               const std::string& data);
121 
122   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
123 
124   // List of available categories.
125   base::Lock categories_lock_;
126   std::vector<Category> categories_ GUARDED_BY(categories_lock_);
127 
128   ArcTracingAgent agent_;
129 
130   std::unique_ptr<ArcTracingReader> reader_;
131 
132   State state_ = State::kDisabled;
133 
134   // NOTE: Weak pointers must be invalidated before all other member variables
135   // so it must be the last member.
136   base::WeakPtrFactory<ArcTracingBridge> weak_ptr_factory_{this};
137 
138   DISALLOW_COPY_AND_ASSIGN(ArcTracingBridge);
139 };
140 
141 }  // namespace arc
142 
143 #endif  // CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_TRACING_BRIDGE_H_
144