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 COMPONENTS_PERFORMANCE_MANAGER_GRAPH_GRAPH_IMPL_H_
6 #define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_GRAPH_IMPL_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <unordered_map>
13 #include <unordered_set>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/containers/flat_map.h"
18 #include "base/containers/flat_set.h"
19 #include "base/macros.h"
20 #include "base/process/process_handle.h"
21 #include "base/sequence_checker.h"
22 #include "components/performance_manager/owned_objects.h"
23 #include "components/performance_manager/public/graph/graph.h"
24 #include "components/performance_manager/public/graph/graph_registered.h"
25 #include "components/performance_manager/public/graph/node_attached_data.h"
26 #include "components/performance_manager/public/render_process_host_id.h"
27 #include "components/performance_manager/registered_objects.h"
28 #include "services/metrics/public/cpp/ukm_recorder.h"
29 
30 namespace performance_manager {
31 
32 class FrameNodeImpl;
33 class Node;
34 class NodeBase;
35 class PageNodeImpl;
36 class ProcessNodeImpl;
37 class SystemNodeImpl;
38 class WorkerNodeImpl;
39 
40 // Represents a graph of the nodes representing a single browser. Maintains a
41 // set of nodes that can be retrieved in different ways, some indexed. Keeps
42 // a list of observers that are notified of node addition and removal.
43 class GraphImpl : public Graph {
44  public:
45   // Pure virtual observer interface. Derive from this if you want to manually
46   // implement the whole interface, and have the compiler enforce that as new
47   // methods are added.
48   using Observer = GraphObserver;
49 
50   using NodeSet = std::unordered_set<NodeBase*>;
51 
52   GraphImpl();
53   ~GraphImpl() override;
54 
55   // Tear down the graph to prepare for deletion.
56   void TearDown();
57 
58   // Graph implementation:
59   void AddGraphObserver(GraphObserver* observer) override;
60   void AddFrameNodeObserver(FrameNodeObserver* observer) override;
61   void AddPageNodeObserver(PageNodeObserver* observer) override;
62   void AddProcessNodeObserver(ProcessNodeObserver* observer) override;
63   void AddSystemNodeObserver(SystemNodeObserver* observer) override;
64   void AddWorkerNodeObserver(WorkerNodeObserver* observer) override;
65   void RemoveGraphObserver(GraphObserver* observer) override;
66   void RemoveFrameNodeObserver(FrameNodeObserver* observer) override;
67   void RemovePageNodeObserver(PageNodeObserver* observer) override;
68   void RemoveProcessNodeObserver(ProcessNodeObserver* observer) override;
69   void RemoveSystemNodeObserver(SystemNodeObserver* observer) override;
70   void RemoveWorkerNodeObserver(WorkerNodeObserver* observer) override;
71   void PassToGraphImpl(std::unique_ptr<GraphOwned> graph_owned) override;
72   std::unique_ptr<GraphOwned> TakeFromGraph(GraphOwned* graph_owned) override;
73   void RegisterObject(GraphRegistered* object) override;
74   void UnregisterObject(GraphRegistered* object) override;
75   const SystemNode* FindOrCreateSystemNode() override;
76   std::vector<const ProcessNode*> GetAllProcessNodes() const override;
77   std::vector<const FrameNode*> GetAllFrameNodes() const override;
78   std::vector<const PageNode*> GetAllPageNodes() const override;
79   std::vector<const WorkerNode*> GetAllWorkerNodes() const override;
80   bool IsEmpty() const override;
81   ukm::UkmRecorder* GetUkmRecorder() const override;
82   NodeDataDescriberRegistry* GetNodeDataDescriberRegistry() const override;
83   uintptr_t GetImplType() const override;
84   const void* GetImpl() const override;
85 #if DCHECK_IS_ON()
86   bool IsOnGraphSequence() const override;
87 #endif
88   GraphRegistered* GetRegisteredObject(uintptr_t type_id) override;
89 
90   // Helper function for safely downcasting to the implementation. This also
91   // casts away constness. This will CHECK on an invalid cast.
92   static GraphImpl* FromGraph(const Graph* graph);
93 
set_ukm_recorder(ukm::UkmRecorder * ukm_recorder)94   void set_ukm_recorder(ukm::UkmRecorder* ukm_recorder) {
95     ukm_recorder_ = ukm_recorder;
96   }
ukm_recorder()97   ukm::UkmRecorder* ukm_recorder() const { return ukm_recorder_; }
98 
99   SystemNodeImpl* FindOrCreateSystemNodeImpl();
100   std::vector<ProcessNodeImpl*> GetAllProcessNodeImpls() const;
101   std::vector<FrameNodeImpl*> GetAllFrameNodeImpls() const;
102   std::vector<PageNodeImpl*> GetAllPageNodeImpls() const;
103   std::vector<WorkerNodeImpl*> GetAllWorkerNodeImpls() const;
nodes()104   const NodeSet& nodes() { return nodes_; }
105 
106   // Retrieves the process node with PID |pid|, if any.
107   ProcessNodeImpl* GetProcessNodeByPid(base::ProcessId pid) const;
108 
109   // Retrieves the frame node with the routing ids of the process and the frame.
110   FrameNodeImpl* GetFrameNodeById(RenderProcessHostId render_process_id,
111                                   int render_frame_id) const;
112 
113   // Returns true if |node| is in this graph.
114   bool NodeInGraph(const NodeBase* node);
115 
116   // Management functions for node owners, any node added to the graph must be
117   // removed from the graph before it's deleted.
118   void AddNewNode(NodeBase* new_node);
119   void RemoveNode(NodeBase* node);
120 
121   // A |key| of nullptr counts all instances associated with the |node|. A
122   // |node| of null counts all instances associated with the |key|. If both are
123   // null then the entire map size is provided.
124   size_t GetNodeAttachedDataCountForTesting(const Node* node,
125                                             const void* key) const;
126 
127   // Allows explicitly invoking SystemNode destruction for testing.
ReleaseSystemNodeForTesting()128   void ReleaseSystemNodeForTesting() { ReleaseSystemNode(); }
129 
130   // Returns the number of objects in the |graph_owned_| map, for testing.
GraphOwnedCountForTesting()131   size_t GraphOwnedCountForTesting() const { return graph_owned_.size(); }
132 
133  protected:
134   friend class NodeBase;
135 
136   // Provides access to per-node-class typed observers. Exposed to nodes via
137   // TypedNodeBase.
138   template <typename Observer>
139   const std::vector<Observer*>& GetObservers() const;
140 
141  private:
142   struct ProcessAndFrameId {
143     ProcessAndFrameId(RenderProcessHostId render_process_id,
144                       int render_frame_id);
145     ~ProcessAndFrameId();
146 
147     ProcessAndFrameId(const ProcessAndFrameId& other);
148     ProcessAndFrameId& operator=(const ProcessAndFrameId& other);
149 
150     bool operator<(const ProcessAndFrameId& other) const;
151     RenderProcessHostId render_process_id;
152     int render_frame_id;
153   };
154 
155   using ProcessByPidMap = std::map<base::ProcessId, ProcessNodeImpl*>;
156   using FrameById = std::map<ProcessAndFrameId, FrameNodeImpl*>;
157 
158   void OnNodeAdded(NodeBase* node);
159   void OnBeforeNodeRemoved(NodeBase* node);
160 
161   // Returns a new serialization ID.
162   friend class NodeBase;
163   int64_t GetNextNodeSerializationId();
164 
165   // Process PID map for use by ProcessNodeImpl.
166   friend class ProcessNodeImpl;
167   void BeforeProcessPidChange(ProcessNodeImpl* process,
168                               base::ProcessId new_pid);
169 
170   // Frame id map for use by FrameNodeImpl.
171   friend class FrameNodeImpl;
172   void RegisterFrameNodeForId(RenderProcessHostId render_process_id,
173                               int render_frame_id,
174                               FrameNodeImpl* frame_node);
175   void UnregisterFrameNodeForId(RenderProcessHostId render_process_id,
176                                 int render_frame_id,
177                                 FrameNodeImpl* frame_node);
178 
179   template <typename NodeType, typename ReturnNodeType>
180   std::vector<ReturnNodeType> GetAllNodesOfType() const;
181 
182   void ReleaseSystemNode();
183 
184   std::unique_ptr<SystemNodeImpl> system_node_;
185   NodeSet nodes_;
186   ProcessByPidMap processes_by_pid_;
187   FrameById frames_by_id_;
188   ukm::UkmRecorder* ukm_recorder_ = nullptr;
189 
190   // Typed observers.
191   // TODO(chrisha): We should wrap these containers in something that catches
192   // invalid reentrant usage in DCHECK builds.
193   std::vector<GraphObserver*> graph_observers_;
194   std::vector<FrameNodeObserver*> frame_node_observers_;
195   std::vector<PageNodeObserver*> page_node_observers_;
196   std::vector<ProcessNodeObserver*> process_node_observers_;
197   std::vector<SystemNodeObserver*> system_node_observers_;
198   std::vector<WorkerNodeObserver*> worker_node_observers_;
199 
200   // Graph-owned objects. For now we only expect O(10) clients, hence the
201   // flat_map.
202   OwnedObjects<GraphOwned,
203                /* CallbackArgType = */ Graph*,
204                &GraphOwned::OnPassedToGraph,
205                &GraphOwned::OnTakenFromGraph>
206       graph_owned_;
207 
208   // Allocated on first use.
209   mutable std::unique_ptr<NodeDataDescriberRegistry> describer_registry_;
210 
211   // User data storage for the graph.
212   friend class NodeAttachedDataMapHelper;
213   using NodeAttachedDataKey = std::pair<const Node*, const void*>;
214   using NodeAttachedDataMap =
215       std::map<NodeAttachedDataKey, std::unique_ptr<NodeAttachedData>>;
216   NodeAttachedDataMap node_attached_data_map_;
217 
218   // Storage for GraphRegistered objects.
219   RegisteredObjects<GraphRegistered> registered_objects_;
220 
221   // The most recently assigned serialization ID.
222   int64_t current_node_serialization_id_ = 0u;
223 
224   SEQUENCE_CHECKER(sequence_checker_);
225   DISALLOW_COPY_AND_ASSIGN(GraphImpl);
226 };
227 
228 }  // namespace performance_manager
229 
230 #endif  // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_GRAPH_IMPL_H_
231