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_UI_WEBUI_DISCARDS_GRAPH_DUMP_IMPL_H_
6 #define CHROME_BROWSER_UI_WEBUI_DISCARDS_GRAPH_DUMP_IMPL_H_
7 
8 #include <memory>
9 
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/sequence_checker.h"
13 #include "chrome/browser/ui/webui/discards/discards.mojom.h"
14 #include "components/performance_manager/public/graph/frame_node.h"
15 #include "components/performance_manager/public/graph/graph.h"
16 #include "components/performance_manager/public/graph/page_node.h"
17 #include "components/performance_manager/public/graph/process_node.h"
18 #include "components/performance_manager/public/graph/worker_node.h"
19 #include "mojo/public/cpp/bindings/pending_receiver.h"
20 #include "mojo/public/cpp/bindings/pending_remote.h"
21 #include "mojo/public/cpp/bindings/receiver.h"
22 #include "mojo/public/cpp/bindings/remote.h"
23 
24 // TODO(siggi): Add workers to the WebUI graph.
25 class DiscardsGraphDumpImpl : public discards::mojom::GraphDump,
26                               public performance_manager::GraphOwned,
27                               public performance_manager::FrameNodeObserver,
28                               public performance_manager::PageNodeObserver,
29                               public performance_manager::ProcessNodeObserver,
30                               public performance_manager::WorkerNodeObserver {
31  public:
32   DiscardsGraphDumpImpl();
33   ~DiscardsGraphDumpImpl() override;
34 
35   // Creates a new DiscardsGraphDumpImpl to service |receiver| and passes its
36   // ownership to |graph|.
37   static void CreateAndBind(
38       mojo::PendingReceiver<discards::mojom::GraphDump> receiver,
39       performance_manager::Graph* graph);
40 
41   // Exposed for testing.
42   void BindWithGraph(
43       performance_manager::Graph* graph,
44       mojo::PendingReceiver<discards::mojom::GraphDump> receiver);
45 
46  protected:
47   // WebUIGraphDump implementation.
48   void SubscribeToChanges(
49       mojo::PendingRemote<discards::mojom::GraphChangeStream> change_subscriber)
50       override;
51 
52   // GraphOwned implementation.
53   void OnPassedToGraph(performance_manager::Graph* graph) override;
54   void OnTakenFromGraph(performance_manager::Graph* graph) override;
55 
56   // FrameNodeObserver implementation:
57   void OnFrameNodeAdded(
58       const performance_manager::FrameNode* frame_node) override;
59   void OnBeforeFrameNodeRemoved(
60       const performance_manager::FrameNode* frame_node) override;
61   // Ignored.
OnIsCurrentChanged(const performance_manager::FrameNode * frame_node)62   void OnIsCurrentChanged(
63       const performance_manager::FrameNode* frame_node) override {}
64   // Ignored.
OnNetworkAlmostIdleChanged(const performance_manager::FrameNode * frame_node)65   void OnNetworkAlmostIdleChanged(
66       const performance_manager::FrameNode* frame_node) override {}
67   // Ignored.
OnFrameLifecycleStateChanged(const performance_manager::FrameNode * frame_node)68   void OnFrameLifecycleStateChanged(
69       const performance_manager::FrameNode* frame_node) override {}
70   // Ignored.
OnOriginTrialFreezePolicyChanged(const performance_manager::FrameNode * frame_node,const InterventionPolicy & previous_value)71   void OnOriginTrialFreezePolicyChanged(
72       const performance_manager::FrameNode* frame_node,
73       const InterventionPolicy& previous_value) override {}
74   void OnURLChanged(const performance_manager::FrameNode* frame_node,
75                     const GURL& previous_value) override;
76   // Ignored.
OnIsAdFrameChanged(const performance_manager::FrameNode * frame_node)77   void OnIsAdFrameChanged(
78       const performance_manager::FrameNode* frame_node) override {}
79   // Ignored.
OnFrameIsHoldingWebLockChanged(const performance_manager::FrameNode * frame_node)80   void OnFrameIsHoldingWebLockChanged(
81       const performance_manager::FrameNode* frame_node) override {}
82   // Ignored.
OnFrameIsHoldingIndexedDBLockChanged(const performance_manager::FrameNode * frame_node)83   void OnFrameIsHoldingIndexedDBLockChanged(
84       const performance_manager::FrameNode* frame_node) override {}
85   // Ignored.
OnNonPersistentNotificationCreated(const performance_manager::FrameNode * frame_node)86   void OnNonPersistentNotificationCreated(
87       const performance_manager::FrameNode* frame_node) override {}
88   // Ignored.
OnPriorityAndReasonChanged(const performance_manager::FrameNode * frame_node,const PriorityAndReason & previous_value)89   void OnPriorityAndReasonChanged(
90       const performance_manager::FrameNode* frame_node,
91       const PriorityAndReason& previous_value) override {}
92   // Ignored.
OnHadFormInteractionChanged(const performance_manager::FrameNode * frame_node)93   void OnHadFormInteractionChanged(
94       const performance_manager::FrameNode* frame_node) override {}
95 
96   // PageNodeObserver implementation:
97   void OnPageNodeAdded(const performance_manager::PageNode* page_node) override;
98   void OnBeforePageNodeRemoved(
99       const performance_manager::PageNode* page_node) override;
OnIsVisibleChanged(const performance_manager::PageNode * page_node)100   void OnIsVisibleChanged(
101       const performance_manager::PageNode* page_node) override {}  // Ignored.
OnIsAudibleChanged(const performance_manager::PageNode * page_node)102   void OnIsAudibleChanged(
103       const performance_manager::PageNode* page_node) override {}  // Ignored.
OnIsLoadingChanged(const performance_manager::PageNode * page_node)104   void OnIsLoadingChanged(
105       const performance_manager::PageNode* page_node) override {}  // Ignored.
OnUkmSourceIdChanged(const performance_manager::PageNode * page_node)106   void OnUkmSourceIdChanged(
107       const performance_manager::PageNode* page_node) override {}  // Ignored.
108   // Ignored.
OnPageLifecycleStateChanged(const performance_manager::PageNode * page_node)109   void OnPageLifecycleStateChanged(
110       const performance_manager::PageNode* page_node) override {}
111   // Ignored.
OnPageOriginTrialFreezePolicyChanged(const performance_manager::PageNode * page_node)112   void OnPageOriginTrialFreezePolicyChanged(
113       const performance_manager::PageNode* page_node) override {}
114   // Ignored.
OnPageIsHoldingWebLockChanged(const performance_manager::PageNode * page_node)115   void OnPageIsHoldingWebLockChanged(
116       const performance_manager::PageNode* page_node) override {}
117   // Ignored.
OnPageIsHoldingIndexedDBLockChanged(const performance_manager::PageNode * page_node)118   void OnPageIsHoldingIndexedDBLockChanged(
119       const performance_manager::PageNode* page_node) override {}
120   void OnMainFrameUrlChanged(
121       const performance_manager::PageNode* page_node) override;
122   // Ignored.
OnMainFrameDocumentChanged(const performance_manager::PageNode * page_node)123   void OnMainFrameDocumentChanged(
124       const performance_manager::PageNode* page_node) override {}
OnHadFormInteractionChanged(const performance_manager::PageNode * page_node)125   void OnHadFormInteractionChanged(
126       const performance_manager::PageNode* page_node) override {}
OnTitleUpdated(const performance_manager::PageNode * page_node)127   void OnTitleUpdated(const performance_manager::PageNode* page_node) override {
128   }  // Ignored.
129   void OnFaviconUpdated(
130       const performance_manager::PageNode* page_node) override;
131 
132   // ProcessNodeObserver implementation:
133   void OnProcessNodeAdded(
134       const performance_manager::ProcessNode* process_node) override;
135   void OnProcessLifetimeChange(
136       const performance_manager::ProcessNode* process_node) override;
137   void OnBeforeProcessNodeRemoved(
138       const performance_manager::ProcessNode* process_node) override;
OnExpectedTaskQueueingDurationSample(const performance_manager::ProcessNode * process_node)139   void OnExpectedTaskQueueingDurationSample(
140       const performance_manager::ProcessNode* process_node) override {
141   }  // Ignored.
142   // Ignored.
OnMainThreadTaskLoadIsLow(const performance_manager::ProcessNode * process_node)143   void OnMainThreadTaskLoadIsLow(
144       const performance_manager::ProcessNode* process_node) override {}
145   // Ignored.
OnAllFramesInProcessFrozen(const performance_manager::ProcessNode * process_node)146   void OnAllFramesInProcessFrozen(
147       const performance_manager::ProcessNode* process_node) override {}
OnPriorityChanged(const performance_manager::ProcessNode * process_node,base::TaskPriority previous_value)148   void OnPriorityChanged(const performance_manager::ProcessNode* process_node,
149                          base::TaskPriority previous_value) override {}
150 
151   // performance_manager::WorkerNodeObserver implementation:
152   void OnWorkerNodeAdded(
153       const performance_manager::WorkerNode* worker_node) override;
154   void OnBeforeWorkerNodeRemoved(
155       const performance_manager::WorkerNode* worker_node) override;
156   void OnFinalResponseURLDetermined(
157       const performance_manager::WorkerNode* worker_node) override;
158   void OnClientFrameAdded(
159       const performance_manager::WorkerNode* worker_node,
160       const performance_manager::FrameNode* client_frame_node) override;
161   void OnBeforeClientFrameRemoved(
162       const performance_manager::WorkerNode* worker_node,
163       const performance_manager::FrameNode* client_frame_node) override;
164   void OnClientWorkerAdded(
165       const performance_manager::WorkerNode* worker_node,
166       const performance_manager::WorkerNode* client_worker_node) override;
167   void OnBeforeClientWorkerRemoved(
168       const performance_manager::WorkerNode* worker_node,
169       const performance_manager::WorkerNode* client_worker_node) override;
170 
171  private:
172   // The favicon requests happen on the UI thread. This helper class
173   // maintains the state required to do that.
174   class FaviconRequestHelper;
175 
176   FaviconRequestHelper* EnsureFaviconRequestHelper();
177 
178   void StartPageFaviconRequest(const performance_manager::PageNode* page_node);
179   void StartFrameFaviconRequest(
180       const performance_manager::FrameNode* frame_node);
181 
182   void SendFrameNotification(const performance_manager::FrameNode* frame,
183                              bool created);
184   void SendPageNotification(const performance_manager::PageNode* page,
185                             bool created);
186   void SendProcessNotification(const performance_manager::ProcessNode* process,
187                                bool created);
188   void SendWorkerNotification(const performance_manager::WorkerNode* worker,
189                               bool created);
190   void SendDeletionNotification(const performance_manager::Node* node);
191   void SendFaviconNotification(
192       int64_t serialization_id,
193       scoped_refptr<base::RefCountedMemory> bitmap_data);
194 
195   static void BindOnPMSequence(
196       mojo::PendingReceiver<discards::mojom::GraphDump> receiver,
197       performance_manager::Graph* graph);
198   static void OnConnectionError(DiscardsGraphDumpImpl* impl);
199 
200   performance_manager::Graph* graph_ = nullptr;
201 
202   std::unique_ptr<FaviconRequestHelper> favicon_request_helper_;
203 
204   // The current change subscriber to this dumper. This instance is subscribed
205   // to every node in |graph_| save for the system node, so long as there is a
206   // subscriber.
207   mojo::Remote<discards::mojom::GraphChangeStream> change_subscriber_;
208   mojo::Receiver<discards::mojom::GraphDump> receiver_{this};
209 
210   SEQUENCE_CHECKER(sequence_checker_);
211 
212   base::WeakPtrFactory<DiscardsGraphDumpImpl> weak_factory_{this};
213 
214   DISALLOW_COPY_AND_ASSIGN(DiscardsGraphDumpImpl);
215 };
216 
217 #endif  // CHROME_BROWSER_UI_WEBUI_DISCARDS_GRAPH_DUMP_IMPL_H_
218