PM: Start moving performance manager to components/.

This moves the performance manager and the graph implementation
as well as the public API to a new component.

Bug: 953031
Change-Id: Ie96011bbe615e31f183da8aae24a20b6e9c79228
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829911
Commit-Queue: Sébastien Marchand <[email protected]>
Reviewed-by: Robert Kaplow <[email protected]>
Reviewed-by: Scott Violet <[email protected]>
Reviewed-by: Chris Hamilton <[email protected]>
Reviewed-by: Avi Drissman <[email protected]>
Reviewed-by: Cait Phillips <[email protected]>
Cr-Commit-Position: refs/heads/master@{#703442}
diff --git a/components/performance_manager/public/graph/frame_node.h b/components/performance_manager/public/graph/frame_node.h
new file mode 100644
index 0000000..2957a69
--- /dev/null
+++ b/components/performance_manager/public/graph/frame_node.h
@@ -0,0 +1,247 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "components/performance_manager/public/frame_priority/frame_priority.h"
+#include "components/performance_manager/public/graph/node.h"
+#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
+#include "services/resource_coordinator/public/mojom/lifecycle.mojom.h"
+
+class GURL;
+
+namespace base {
+class UnguessableToken;
+}  // namespace base
+
+namespace performance_manager {
+
+class FrameNodeObserver;
+class PageNode;
+class ProcessNode;
+class WorkerNode;
+
+// Frame nodes form a tree structure, each FrameNode at most has one parent that
+// is a FrameNode. Conceptually, a frame corresponds to a
+// content::RenderFrameHost in the browser, and a content::RenderFrameImpl /
+// blink::LocalFrame/blink::Document in a renderer.
+//
+// Note that a frame in a frame tree can be replaced with another, with the
+// continuity of that position represented via the |frame_tree_node_id|. It is
+// possible to have multiple "sibling" nodes that share the same
+// |frame_tree_node_id|. Only one of these may contribute to the content being
+// rendered, and this node is designated the "current" node in content
+// terminology. A swap is effectively atomic but will take place in two steps
+// in the graph: the outgoing frame will first be marked as not current, and the
+// incoming frame will be marked as current. As such, the graph invariant is
+// that there will be 0 or 1 |is_current| frames with a given
+// |frame_tree_node_id|.
+//
+// This occurs when a frame is navigated and the existing frame can't be reused.
+// In that case a "provisional" frame is created to start the navigation. Once
+// the navigation completes (which may actually involve a redirect to another
+// origin meaning the frame has to be destroyed and another one created in
+// another process!) and commits, the frame will be swapped with the previously
+// active frame.
+//
+// It is only valid to access this object on the sequence of the graph that owns
+// it.
+class FrameNode : public Node {
+ public:
+  using LifecycleState = resource_coordinator::mojom::LifecycleState;
+  using InterventionPolicy = resource_coordinator::mojom::InterventionPolicy;
+  using Observer = FrameNodeObserver;
+  using PriorityAndReason = frame_priority::PriorityAndReason;
+
+  class ObserverDefaultImpl;
+
+  FrameNode();
+  ~FrameNode() override;
+
+  // Returns the parent of this frame node. This may be null if this frame node
+  // is the main (root) node of a frame tree. This is a constant over the
+  // lifetime of the frame.
+  virtual const FrameNode* GetParentFrameNode() const = 0;
+
+  // Returns the page node to which this frame belongs. This is a constant over
+  // the lifetime of the frame.
+  virtual const PageNode* GetPageNode() const = 0;
+
+  // Returns the process node with which this frame belongs. This is a constant
+  // over the lifetime of the frame.
+  virtual const ProcessNode* GetProcessNode() const = 0;
+
+  // Gets the FrameTree node ID associated with this node. There may be multiple
+  // sibling nodes with the same frame tree node ID, but at most 1 of them may
+  // be current at a time. This is a constant over the lifetime of the frame.
+  virtual int GetFrameTreeNodeId() const = 0;
+
+  // Gets the devtools token associated with this frame. This is a constant over
+  // the lifetime of the frame.
+  virtual const base::UnguessableToken& GetDevToolsToken() const = 0;
+
+  // Gets the ID of the browsing instance to which this frame belongs. This is a
+  // constant over the lifetime of the frame.
+  virtual int32_t GetBrowsingInstanceId() const = 0;
+
+  // Gets the ID of the site instance to which this frame belongs. This is a
+  // constant over the lifetime of the frame.
+  virtual int32_t GetSiteInstanceId() const = 0;
+
+  // A frame is a main frame if it has no parent FrameNode. This can be
+  // called from any thread.
+  virtual bool IsMainFrame() const = 0;
+
+  // Returns the set of child frame associated with this frame. Note that this
+  // incurs a full container copy of all child nodes. Please use ForEach when
+  // that makes sense.
+  virtual const base::flat_set<const FrameNode*> GetChildFrameNodes() const = 0;
+
+  // Returns the current lifecycle state of this frame. See
+  // FrameNodeObserver::OnFrameLifecycleStateChanged.
+  virtual LifecycleState GetLifecycleState() const = 0;
+
+  // Returns the freeze policy set via origin trial. kDefault when no freeze
+  // policy is set via origin trial.
+  virtual InterventionPolicy GetOriginTrialFreezePolicy() const = 0;
+
+  // Returns true if this frame had a non-empty before-unload handler at the
+  // time of its last transition to the frozen lifecycle state. This is only
+  // meaningful while the object is frozen.
+  virtual bool HasNonemptyBeforeUnload() const = 0;
+
+  // Returns the URL associated with this frame.
+  // See FrameNodeObserver::OnURLChanged.
+  virtual const GURL& GetURL() const = 0;
+
+  // Returns true if this frame is current (is part of a content::FrameTree).
+  // See FrameNodeObserver::OnIsCurrentChanged.
+  virtual bool IsCurrent() const = 0;
+
+  // Returns true if this frames use of the network is "almost idle", indicating
+  // that it is not doing any heavy loading work.
+  virtual bool GetNetworkAlmostIdle() const = 0;
+
+  // Returns true if this frame is ad frame. This can change from false to true
+  // over the lifetime of the frame, but once it is true it will always remain
+  // true.
+  virtual bool IsAdFrame() const = 0;
+
+  // Returns true if this frame holds at least one Web Lock.
+  virtual bool HoldsWebLock() const = 0;
+
+  // Returns true if this frame holds at least one IndexedDB lock. An IndexedDB
+  // lock is held by an active transaction or an active DB open request.
+  virtual bool HoldsIndexedDBLock() const = 0;
+
+  // Returns the child workers of this frame. These are either dedicated workers
+  // or shared workers created by this frame, or a service worker that handles
+  // this frame's network requests.
+  virtual const base::flat_set<const WorkerNode*> GetChildWorkerNodes()
+      const = 0;
+
+  // Returns the current priority of the frame, and the reason for the frame
+  // having that particular priority.
+  virtual const PriorityAndReason& GetPriorityAndReason() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FrameNode);
+};
+
+// Pure virtual observer interface. Derive from this if you want to be forced to
+// implement the entire interface.
+class FrameNodeObserver {
+ public:
+  using InterventionPolicy = resource_coordinator::mojom::InterventionPolicy;
+
+  FrameNodeObserver();
+  virtual ~FrameNodeObserver();
+
+  // Node lifetime notifications.
+
+  // Called when a |frame_node| is added to the graph.
+  virtual void OnFrameNodeAdded(const FrameNode* frame_node) = 0;
+
+  // Called before a |frame_node| is removed from the graph.
+  virtual void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) = 0;
+
+  // Notifications of property changes.
+
+  // Invoked when the IsCurrent property changes.
+  virtual void OnIsCurrentChanged(const FrameNode* frame_node) = 0;
+
+  // Invoked when the NetworkAlmostIdle property changes.
+  virtual void OnNetworkAlmostIdleChanged(const FrameNode* frame_node) = 0;
+
+  // Invoked when the LifecycleState property changes.
+  virtual void OnFrameLifecycleStateChanged(const FrameNode* frame_node) = 0;
+
+  // Invoked when the OriginTrialFreezePolicy changes.
+  virtual void OnOriginTrialFreezePolicyChanged(
+      const FrameNode* frame_node,
+      const InterventionPolicy& previous_value) = 0;
+
+  // Invoked when the URL property changes.
+  virtual void OnURLChanged(const FrameNode* frame_node,
+                            const GURL& previous_value) = 0;
+
+  // Invoked when the IsAdFrame property changes.
+  virtual void OnIsAdFrameChanged(const FrameNode* frame_node) = 0;
+
+  // Invoked when the HoldsWebLock() property changes.
+  virtual void OnFrameHoldsWebLockChanged(const FrameNode* frame_node) = 0;
+
+  // Invoked when the HoldsIndexedDBLock() property changes.
+  virtual void OnFrameHoldsIndexedDBLockChanged(
+      const FrameNode* frame_node) = 0;
+
+  // Invoked when the frame priority and reason changes.
+  virtual void OnPriorityAndReasonChanged(const FrameNode* frame_node) = 0;
+
+  // Events with no property changes.
+
+  // Invoked when a non-persistent notification has been issued by the frame.
+  virtual void OnNonPersistentNotificationCreated(
+      const FrameNode* frame_node) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FrameNodeObserver);
+};
+
+// Default implementation of observer that provides dummy versions of each
+// function. Derive from this if you only need to implement a few of the
+// functions.
+class FrameNode::ObserverDefaultImpl : public FrameNodeObserver {
+ public:
+  ObserverDefaultImpl();
+  ~ObserverDefaultImpl() override;
+
+  // FrameNodeObserver implementation:
+  void OnFrameNodeAdded(const FrameNode* frame_node) override {}
+  void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override {}
+  void OnIsCurrentChanged(const FrameNode* frame_node) override {}
+  void OnNetworkAlmostIdleChanged(const FrameNode* frame_node) override {}
+  void OnFrameLifecycleStateChanged(const FrameNode* frame_node) override {}
+  void OnOriginTrialFreezePolicyChanged(
+      const FrameNode* frame_node,
+      const InterventionPolicy& previous_value) override {}
+  void OnURLChanged(const FrameNode* frame_node,
+                    const GURL& previous_value) override {}
+  void OnIsAdFrameChanged(const FrameNode* frame_node) override {}
+  void OnFrameHoldsWebLockChanged(const FrameNode* frame_node) override {}
+  void OnFrameHoldsIndexedDBLockChanged(const FrameNode* frame_node) override {}
+  void OnNonPersistentNotificationCreated(
+      const FrameNode* frame_node) override {}
+  void OnPriorityAndReasonChanged(const FrameNode* frame_node) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
diff --git a/components/performance_manager/public/graph/graph.h b/components/performance_manager/public/graph/graph.h
new file mode 100644
index 0000000..37cd408
--- /dev/null
+++ b/components/performance_manager/public/graph/graph.h
@@ -0,0 +1,147 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+
+namespace ukm {
+class UkmRecorder;
+}  // namespace ukm
+
+namespace performance_manager {
+
+class GraphObserver;
+class GraphOwned;
+class FrameNode;
+class FrameNodeObserver;
+class PageNode;
+class PageNodeObserver;
+class ProcessNode;
+class ProcessNodeObserver;
+class SystemNode;
+class SystemNodeObserver;
+class WorkerNode;
+class WorkerNodeObserver;
+
+// Represents a graph of the nodes representing a single browser. Maintains a
+// set of nodes that can be retrieved in different ways, some indexed. Keeps
+// a list of observers that are notified of node addition and removal.
+class Graph {
+ public:
+  using Observer = GraphObserver;
+
+  Graph();
+  virtual ~Graph();
+
+  // Adds an |observer| on the graph. It is safe for observers to stay
+  // registered on the graph at the time of its death.
+  virtual void AddGraphObserver(GraphObserver* observer) = 0;
+  virtual void AddFrameNodeObserver(FrameNodeObserver* observer) = 0;
+  virtual void AddPageNodeObserver(PageNodeObserver* observer) = 0;
+  virtual void AddProcessNodeObserver(ProcessNodeObserver* observer) = 0;
+  virtual void AddSystemNodeObserver(SystemNodeObserver* observer) = 0;
+  virtual void AddWorkerNodeObserver(WorkerNodeObserver* observer) = 0;
+
+  // Removes an |observer| from the graph.
+  virtual void RemoveGraphObserver(GraphObserver* observer) = 0;
+  virtual void RemoveFrameNodeObserver(FrameNodeObserver* observer) = 0;
+  virtual void RemovePageNodeObserver(PageNodeObserver* observer) = 0;
+  virtual void RemoveProcessNodeObserver(ProcessNodeObserver* observer) = 0;
+  virtual void RemoveSystemNodeObserver(SystemNodeObserver* observer) = 0;
+  virtual void RemoveWorkerNodeObserver(WorkerNodeObserver* observer) = 0;
+
+  // For convenience, allows you to pass ownership of an object to the graph.
+  // Useful for attaching observers that will live with the graph until it dies.
+  // If you can name the object you can also take it back via "TakeFromGraph".
+  virtual void PassToGraph(std::unique_ptr<GraphOwned> graph_owned) = 0;
+  virtual std::unique_ptr<GraphOwned> TakeFromGraph(
+      GraphOwned* graph_owned) = 0;
+
+  // A TakeFromGraph helper for taking back the ownership of a GraphOwned
+  // subclass.
+  template <typename DerivedType>
+  std::unique_ptr<DerivedType> TakeFromGraphAs(DerivedType* graph_owned) {
+    return base::WrapUnique(
+        static_cast<DerivedType*>(TakeFromGraph(graph_owned).release()));
+  }
+
+  // Returns a collection of all known nodes of the given type.
+  virtual const SystemNode* FindOrCreateSystemNode() = 0;
+  virtual std::vector<const ProcessNode*> GetAllProcessNodes() const = 0;
+  virtual std::vector<const FrameNode*> GetAllFrameNodes() const = 0;
+  virtual std::vector<const PageNode*> GetAllPageNodes() const = 0;
+  virtual std::vector<const WorkerNode*> GetAllWorkerNodes() const = 0;
+
+  // Returns the associated UKM recorder if it is defined.
+  virtual ukm::UkmRecorder* GetUkmRecorder() const = 0;
+
+  // The following functions are implementation detail and should not need to be
+  // used by external clients. They provide the ability to safely downcast to
+  // the underlying implementation.
+  virtual uintptr_t GetImplType() const = 0;
+  virtual const void* GetImpl() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Graph);
+};
+
+// Observer interface for the graph.
+class GraphObserver {
+ public:
+  GraphObserver();
+  virtual ~GraphObserver();
+
+  // Called before the |graph| associated with this observer disappears. This
+  // allows the observer to do any necessary cleanup work. Note that the
+  // observer should remove itself from observing the graph using this
+  // callback.
+  // TODO(chrisha): Make this run before the destructor!
+  // crbug.com/966840
+  virtual void OnBeforeGraphDestroyed(Graph* graph) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GraphObserver);
+};
+
+// Helper class for passing ownership of objects to a graph.
+class GraphOwned {
+ public:
+  GraphOwned();
+  virtual ~GraphOwned();
+
+  // Called when the object is passed into the graph.
+  virtual void OnPassedToGraph(Graph* graph) = 0;
+
+  // Called when the object is removed from the graph, either via an explicit
+  // call to Graph::TakeFromGraph, or prior to the Graph being destroyed.
+  virtual void OnTakenFromGraph(Graph* graph) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GraphOwned);
+};
+
+// A default implementation of GraphOwned.
+class GraphOwnedDefaultImpl : public GraphOwned {
+ public:
+  GraphOwnedDefaultImpl();
+  ~GraphOwnedDefaultImpl() override;
+
+  // GraphOwned implementation:
+  void OnPassedToGraph(Graph* graph) override {}
+  void OnTakenFromGraph(Graph* graph) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GraphOwnedDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_
diff --git a/components/performance_manager/public/graph/graph_operations.h b/components/performance_manager/public/graph/graph_operations.h
new file mode 100644
index 0000000..8f5d549
--- /dev/null
+++ b/components/performance_manager/public/graph/graph_operations.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_OPERATIONS_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_OPERATIONS_H_
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
+
+namespace performance_manager {
+
+class FrameNode;
+class PageNode;
+class ProcessNode;
+
+// A collection of utilities for performing common queries and traversals on a
+// graph.
+struct GraphOperations {
+  using FrameNodeVisitor = base::Callback<bool(const FrameNode*)>;
+
+  // Returns the collection of page nodes that are associated with the given
+  // |process|. A page is associated with a process if the page's frame tree
+  // contains 1 or more frames hosted in the given |process|.
+  static base::flat_set<const PageNode*> GetAssociatedPageNodes(
+      const ProcessNode* process);
+
+  // Returns the collection of process nodes associated with the given |page|.
+  // A |process| is associated with a page if the page's frame tree contains 1
+  // or more frames hosted in that |process|.
+  static base::flat_set<const ProcessNode*> GetAssociatedProcessNodes(
+      const PageNode* page);
+
+  // Returns the collection of frame nodes associated with a page. This is
+  // returned in level order, with main frames first (level 0), main frame
+  // children next (level 1), all the way down to the deepest leaf frames.
+  static std::vector<const FrameNode*> GetFrameNodes(const PageNode* page);
+
+  // Traverse the frame tree of a |page| in the given order, invoking the
+  // provided |callable| for each frame node in the tree. If the visitor returns
+  // false then then the iteration is halted.
+  static void VisitFrameTreePreOrder(const PageNode* page,
+                                     const FrameNodeVisitor& visitor);
+  static void VisitFrameTreePostOrder(const PageNode* page,
+                                      const FrameNodeVisitor& visitor);
+
+  // Returns true if the given |frame| is in the frame tree associated with the
+  // given |page|.
+  static bool HasFrame(const PageNode* page, const FrameNode* frame);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_OPERATIONS_H_
diff --git a/components/performance_manager/public/graph/node.h b/components/performance_manager/public/graph/node.h
new file mode 100644
index 0000000..ae76e363
--- /dev/null
+++ b/components/performance_manager/public/graph/node.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+
+namespace performance_manager {
+
+class Graph;
+
+// Interface that all nodes must implement.
+// TODO(chrisha): Move NodeTypeEnum to the public interface and expose it here,
+// then add FromNode casts on the public node interfaces.
+class Node {
+ public:
+  Node();
+  virtual ~Node();
+
+  // Returns the graph to which this node belongs.
+  virtual Graph* GetGraph() const = 0;
+
+  // The following functions are implementation detail and should not need to be
+  // used by external clients. They provide the ability to safely downcast to
+  // the underlying implementation.
+  virtual uintptr_t GetImplType() const = 0;
+  virtual const void* GetImpl() const = 0;
+
+  // Returns the serialization ID of the given |node|. This is a stable and
+  // opaque value that will always refer only to this node, and never be reused
+  // over the lifetime of the browser.
+  // TODO(chrisha): Deprecate this, and move the logic inside of the only
+  // client using it.
+  static int64_t GetSerializationId(const Node* node);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Node);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_H_
diff --git a/components/performance_manager/public/graph/node_attached_data.h b/components/performance_manager/public/graph/node_attached_data.h
new file mode 100644
index 0000000..88e9561
--- /dev/null
+++ b/components/performance_manager/public/graph/node_attached_data.h
@@ -0,0 +1,137 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace performance_manager {
+
+class Node;
+
+// NodeAttachedData allows external observers of the graph to store data that is
+// associated with a graph node, providing lifetime management as a service.
+//
+// External (to performance_manager) implementations of NodeAttachedData should
+// derive from ExternalNodeAttachedDataImpl. For internal implementations refer
+// to NodeAttachedDataImpl and see node_attached_data_impl.h.
+class NodeAttachedData {
+ public:
+  NodeAttachedData();
+  virtual ~NodeAttachedData();
+
+  // Returns the 'key' associated with this type of NodeAttachedData. This needs
+  // to be unique per data type or bad things happen.
+  virtual const void* GetKey() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NodeAttachedData);
+};
+
+// Implements NodeAttachedData for a given UserDataType.
+//
+// In order for a UserDataType to be attached to a node of type |NodeType| it
+// must have a constructor of the form "UserDataType(const NodeType* node)".
+template <typename UserDataType>
+class ExternalNodeAttachedDataImpl : public NodeAttachedData {
+ public:
+  ExternalNodeAttachedDataImpl() = default;
+  ~ExternalNodeAttachedDataImpl() override = default;
+
+  // NodeAttachedData implementation:
+  const void* GetKey() const override { return &kUserDataKey; }
+
+  // Gets the user data for the given |node|, creating it if it doesn't yet
+  // exist.
+  template <typename NodeType>
+  static UserDataType* GetOrCreate(const NodeType* node);
+
+  // Gets the user data for the given |node|, returning nullptr if it doesn't
+  // exist.
+  template <typename NodeType>
+  static UserDataType* Get(const NodeType* node);
+
+  // Destroys the user data associated with the given node, returning true
+  // on success or false if the user data did not exist to begin with.
+  template <typename NodeType>
+  static bool Destroy(const NodeType* node);
+
+ private:
+  static constexpr int kUserDataKey = 0;
+  static const void* UserDataKey() { return &kUserDataKey; }
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalNodeAttachedDataImpl);
+};
+
+// Everything below this point is pure implementation detail.
+
+// Provides access for setting/getting data in the map based storage. Not
+// intended to be used directly, but rather by (External)NodeAttachedDataImpl.
+class NodeAttachedDataMapHelper {
+ public:
+  // Attaches the provided |data| to the provided |node|. This should only be
+  // called if the data does not exist (GetFromMap returns nullptr), and will
+  // DCHECK otherwise.
+  static void AttachInMap(const Node* node,
+                          std::unique_ptr<NodeAttachedData> data);
+
+  // Retrieves the data associated with the provided |node| and |key|. This
+  // returns nullptr if no data exists.
+  static NodeAttachedData* GetFromMap(const Node* node, const void* key);
+
+  // Detaches the data associated with the provided |node| and |key|. It is
+  // harmless to call this when no data exists.
+  static std::unique_ptr<NodeAttachedData> DetachFromMap(const Node* node,
+                                                         const void* key);
+};
+
+// Implementation of ExternalNodeAttachedDataImpl, which is declared in the
+// corresponding public header. This helps keep the public headers as clean as
+// possible.
+
+// static
+template <typename UserDataType>
+constexpr int ExternalNodeAttachedDataImpl<UserDataType>::kUserDataKey;
+
+template <typename UserDataType>
+template <typename NodeType>
+UserDataType* ExternalNodeAttachedDataImpl<UserDataType>::GetOrCreate(
+    const NodeType* node) {
+  if (auto* data = Get(node))
+    return data;
+  std::unique_ptr<UserDataType> data = std::make_unique<UserDataType>(node);
+  auto* raw_data = data.get();
+  auto* base = static_cast<const Node*>(node);
+  NodeAttachedDataMapHelper::AttachInMap(base, std::move(data));
+  return raw_data;
+}
+
+template <typename UserDataType>
+template <typename NodeType>
+UserDataType* ExternalNodeAttachedDataImpl<UserDataType>::Get(
+    const NodeType* node) {
+  auto* base = static_cast<const Node*>(node);
+  auto* data = NodeAttachedDataMapHelper::GetFromMap(base, UserDataKey());
+  if (!data)
+    return nullptr;
+  DCHECK_EQ(UserDataKey(), data->GetKey());
+  return static_cast<UserDataType*>(data);
+}
+
+template <typename UserDataType>
+template <typename NodeType>
+bool ExternalNodeAttachedDataImpl<UserDataType>::Destroy(const NodeType* node) {
+  auto* base = static_cast<const Node*>(node);
+  std::unique_ptr<NodeAttachedData> data =
+      NodeAttachedDataMapHelper::DetachFromMap(base, UserDataKey());
+  return data.get();
+}
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
new file mode 100644
index 0000000..bc92f77
--- /dev/null
+++ b/components/performance_manager/public/graph/page_node.h
@@ -0,0 +1,198 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
+
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "components/performance_manager/public/graph/node.h"
+#include "components/performance_manager/public/web_contents_proxy.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
+#include "services/resource_coordinator/public/mojom/lifecycle.mojom.h"
+
+class GURL;
+
+namespace performance_manager {
+
+class FrameNode;
+class PageNodeObserver;
+
+// A PageNode represents the root of a FrameTree, or equivalently a WebContents.
+// These may correspond to normal tabs, WebViews, Portals, Chrome Apps or
+// Extensions.
+class PageNode : public Node {
+ public:
+  using InterventionPolicy = resource_coordinator::mojom::InterventionPolicy;
+  using LifecycleState = resource_coordinator::mojom::LifecycleState;
+  using Observer = PageNodeObserver;
+  class ObserverDefaultImpl;
+
+  PageNode();
+  ~PageNode() override;
+
+  // Returns the unique ID of the browser context that this page belongs to.
+  virtual const std::string& GetBrowserContextID() const = 0;
+
+  // Returns the page almost idle state of this page.
+  // See PageNodeObserver::OnPageAlmostIdleChanged.
+  virtual bool IsPageAlmostIdle() const = 0;
+
+  // Returns true if this page is currently visible, false otherwise.
+  // See PageNodeObserver::OnIsVisibleChanged.
+  virtual bool IsVisible() const = 0;
+
+  // Returns the time since the last visibility change. It is always well
+  // defined as the visibility property is set at node creation.
+  virtual base::TimeDelta GetTimeSinceLastVisibilityChange() const = 0;
+
+  // Returns true if this page is currently audible, false otherwise.
+  // See PageNodeObserver::OnIsAudibleChanged.
+  virtual bool IsAudible() const = 0;
+
+  // Returns true if this page is currently loading, false otherwise.
+  // See PageNodeObserver::OnIsLoadingChanged.
+  virtual bool IsLoading() const = 0;
+
+  // Returns the UKM source ID associated with the URL of the main frame of
+  // this page.
+  // See PageNodeObserver::OnUkmSourceIdChanged.
+  virtual ukm::SourceId GetUkmSourceID() const = 0;
+
+  // Returns the lifecycle state of this page. This is aggregated from the
+  // lifecycle state of each frame in the frame tree. See
+  // PageNodeObserver::OnPageLifecycleStateChanged.
+  virtual LifecycleState GetLifecycleState() const = 0;
+
+  // Returns the freeze policy set via origin trial.
+  virtual InterventionPolicy GetOriginTrialFreezePolicy() const = 0;
+
+  // Returns the navigation ID associated with the last committed navigation
+  // event for the main frame of this page.
+  // See PageNodeObserver::OnMainFrameNavigationCommitted.
+  virtual int64_t GetNavigationID() const = 0;
+
+  // Returns "zero" if no navigation has happened, otherwise returns the time
+  // since the last navigation commit.
+  virtual base::TimeDelta GetTimeSinceLastNavigation() const = 0;
+
+  // Returns the current main frame node (if there is one), otherwise returns
+  // any of the potentially multiple main frames that currently exist. If there
+  // are no main frames at the moment, returns nullptr.
+  virtual const FrameNode* GetMainFrameNode() const = 0;
+
+  // Returns all of the main frame nodes, both current and otherwise. If there
+  // are no main frames at the moment, returns the empty set.
+  virtual const base::flat_set<const FrameNode*> GetMainFrameNodes() const = 0;
+
+  // Returns the URL the main frame last committed a navigation to, or the
+  // initial URL of the page before navigation. The latter case is distinguished
+  // by a zero navigation ID.
+  // See PageNodeObserver::OnMainFrameNavigationCommitted.
+  virtual const GURL& GetMainFrameUrl() const = 0;
+
+  // Returns the web contents associated with this page node. It is valid to
+  // call this function on any thread but the weak pointer must only be
+  // dereferenced on the UI thread.
+  virtual const WebContentsProxy& GetContentsProxy() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PageNode);
+};
+
+// Pure virtual observer interface. Derive from this if you want to be forced to
+// implement the entire interface.
+class PageNodeObserver {
+ public:
+  PageNodeObserver();
+  virtual ~PageNodeObserver();
+
+  // Node lifetime notifications.
+
+  // Called when a |page_node| is added to the graph.
+  virtual void OnPageNodeAdded(const PageNode* page_node) = 0;
+
+  // Called before a |page_node| is removed from the graph.
+  virtual void OnBeforePageNodeRemoved(const PageNode* page_node) = 0;
+
+  // Notifications of property changes.
+
+  // Invoked when the IsVisible property changes.
+  virtual void OnIsVisibleChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the IsAudible property changes.
+  virtual void OnIsAudibleChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the IsLoading property changes.
+  virtual void OnIsLoadingChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the UkmSourceId property changes.
+  virtual void OnUkmSourceIdChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the PageLifecycleState property changes.
+  virtual void OnPageLifecycleStateChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the OriginTrialFreezePolicy property changes.
+  virtual void OnPageOriginTrialFreezePolicyChanged(
+      const PageNode* page_node) = 0;
+
+  // Invoked when the MainFrameUrl property changes.
+  virtual void OnMainFrameUrlChanged(const PageNode* page_node) = 0;
+
+  // Invoked when the PageAlmostIdle property changes.
+  virtual void OnPageAlmostIdleChanged(const PageNode* page_node) = 0;
+
+  // This is fired when a non-same document navigation commits in the main
+  // frame. It indicates that the the |NavigationId| property and possibly the
+  // |MainFrameUrl| properties have changed.
+  virtual void OnMainFrameDocumentChanged(const PageNode* page_node) = 0;
+
+  // Events with no property changes.
+
+  // Fired when the tab title associated with a page changes. This property is
+  // not directly reflected on the node.
+  virtual void OnTitleUpdated(const PageNode* page_node) = 0;
+
+  // Fired when the favicon associated with a page is updated. This property is
+  // not directly reflected on the node.
+  virtual void OnFaviconUpdated(const PageNode* page_node) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PageNodeObserver);
+};
+
+// Default implementation of observer that provides dummy versions of each
+// function. Derive from this if you only need to implement a few of the
+// functions.
+class PageNode::ObserverDefaultImpl : public PageNodeObserver {
+ public:
+  ObserverDefaultImpl();
+  ~ObserverDefaultImpl() override;
+
+  // PageNodeObserver implementation:
+  void OnPageNodeAdded(const PageNode* page_node) override {}
+  void OnBeforePageNodeRemoved(const PageNode* page_node) override {}
+  void OnIsVisibleChanged(const PageNode* page_node) override {}
+  void OnIsAudibleChanged(const PageNode* page_node) override {}
+  void OnIsLoadingChanged(const PageNode* page_node) override {}
+  void OnUkmSourceIdChanged(const PageNode* page_node) override {}
+  void OnPageLifecycleStateChanged(const PageNode* page_node) override {}
+  void OnPageOriginTrialFreezePolicyChanged(
+      const PageNode* page_node) override {}
+  void OnPageAlmostIdleChanged(const PageNode* page_node) override {}
+  void OnMainFrameUrlChanged(const PageNode* page_node) override {}
+  void OnMainFrameDocumentChanged(const PageNode* page_node) override {}
+  void OnTitleUpdated(const PageNode* page_node) override {}
+  void OnFaviconUpdated(const PageNode* page_node) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
diff --git a/components/performance_manager/public/graph/process_node.h b/components/performance_manager/public/graph/process_node.h
new file mode 100644
index 0000000..0ae476aa
--- /dev/null
+++ b/components/performance_manager/public/graph/process_node.h
@@ -0,0 +1,170 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PROCESS_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PROCESS_NODE_H_
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "base/process/process.h"
+#include "components/performance_manager/public/graph/node.h"
+
+namespace base {
+class Process;
+}  // namespace base
+
+namespace performance_manager {
+
+class FrameNode;
+class ProcessNodeObserver;
+class RenderProcessHostProxy;
+
+// A process node follows the lifetime of a RenderProcessHost.
+// It may reference zero or one processes at a time, but during its lifetime, it
+// may reference more than one process. This can happen if the associated
+// renderer crashes, and an associated frame is then reloaded or re-navigated.
+// The state of the process node goes through:
+// 1. Created, no PID.
+// 2. Process started, have PID - in the case where the associated render
+//    process fails to start, this state may not occur.
+// 3. Process died or failed to start, have exit status.
+// 4. Back to 2.
+//
+// It is only valid to access this object on the sequence of the graph that owns
+// it.
+class ProcessNode : public Node {
+ public:
+  using FrameNodeVisitor = base::Callback<bool(const FrameNode*)>;
+  using Observer = ProcessNodeObserver;
+  class ObserverDefaultImpl;
+
+  ProcessNode();
+  ~ProcessNode() override;
+
+  // Returns the process ID associated with this process. Use this in preference
+  // to querying GetProcess.Pid(). It's always valid to access, but will return
+  // kNullProcessId if the process has yet started. It will also retain the
+  // process ID for a process that has exited (at least until the underlying
+  // RenderProcessHost gets reused in the case of a crash). Refrain from using
+  // this as a unique identifier as on some platforms PIDs are reused
+  // aggressively. See GetLaunchTime for more information.
+  virtual base::ProcessId GetProcessId() const = 0;
+
+  // Returns the base::Process backing this process. This will be an invalid
+  // process if it has not yet started, or if it has exited.
+  virtual const base::Process& GetProcess() const = 0;
+
+  // Returns the launch time associated with the process. Combined with the
+  // process ID this can be used as a unique identifier for the process.
+  virtual base::Time GetLaunchTime() const = 0;
+
+  // Returns the exit status of this process. This will be empty if the process
+  // has not yet exited.
+  virtual base::Optional<int32_t> GetExitStatus() const = 0;
+
+  // Visits the frame nodes that are hosted in this process. The iteration is
+  // halted if the visitor returns false.
+  virtual void VisitFrameNodes(const FrameNodeVisitor& visitor) const = 0;
+
+  // Returns the set of frame nodes that are hosted in this process. Note that
+  // calling this causes the set of nodes to be generated.
+  virtual base::flat_set<const FrameNode*> GetFrameNodes() const = 0;
+
+  // Returns the current expected task queuing duration in the process. This is
+  // measure of main thread latency. See
+  // ProcessNodeObserver::OnExpectedTaskQueueingDurationSample.
+  virtual base::TimeDelta GetExpectedTaskQueueingDuration() const = 0;
+
+  // Returns true if the main thread task load is low (below some threshold
+  // of usage). See ProcessNodeObserver::OnMainThreadTaskLoadIsLow.
+  virtual bool GetMainThreadTaskLoadIsLow() const = 0;
+
+  // Returns the current renderer process CPU usage. A value of 1.0 can mean 1
+  // core at 100%, or 2 cores at 50% each, for example.
+  virtual double GetCpuUsage() const = 0;
+
+  // Returns the cumulative CPU usage of the renderer process over its entire
+  // lifetime, expressed as CPU seconds.
+  virtual base::TimeDelta GetCumulativeCpuUsage() const = 0;
+
+  // Returns the most recently measured private memory footprint of the process.
+  // This is roughly private, anonymous, non-discardable, resident or swapped
+  // memory in kilobytes. For more details, see https://goo.gl/3kPb9S.
+  virtual uint64_t GetPrivateFootprintKb() const = 0;
+
+  // Returns the most recently measured resident set of the process, in
+  // kilobytes.
+  virtual uint64_t GetResidentSetKb() const = 0;
+
+  // Returns a proxy to the RenderProcessHost associated with this node. The
+  // proxy may only be dereferenced on the UI thread.
+  virtual const RenderProcessHostProxy& GetRenderProcessHostProxy() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProcessNode);
+};
+
+// Pure virtual observer interface. Derive from this if you want to be forced to
+// implement the entire interface.
+class ProcessNodeObserver {
+ public:
+  ProcessNodeObserver();
+  virtual ~ProcessNodeObserver();
+
+  // Node lifetime notifications.
+
+  // Called when a |process_node| is added to the graph.
+  virtual void OnProcessNodeAdded(const ProcessNode* process_node) = 0;
+
+  // The process associated with |process_node| has been started or has exited.
+  // This implies some or all of the process, process_id, launch time and/or
+  // exit status properties have changed.
+  virtual void OnProcessLifetimeChange(const ProcessNode* process_node) = 0;
+
+  // Called before a |process_node| is removed from the graph.
+  virtual void OnBeforeProcessNodeRemoved(const ProcessNode* process_node) = 0;
+
+  // Notifications of property changes.
+
+  // Invoked when a new |expected_task_queueing_duration| sample is available.
+  virtual void OnExpectedTaskQueueingDurationSample(
+      const ProcessNode* process_node) = 0;
+
+  // Invoked when the |main_thread_task_load_is_low| property changes.
+  virtual void OnMainThreadTaskLoadIsLow(const ProcessNode* process_node) = 0;
+
+  // Events with no property changes.
+
+  // Fired when all frames in a process have transitioned to being frozen.
+  virtual void OnAllFramesInProcessFrozen(const ProcessNode* process_node) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProcessNodeObserver);
+};
+
+// Default implementation of observer that provides dummy versions of each
+// function. Derive from this if you only need to implement a few of the
+// functions.
+class ProcessNode::ObserverDefaultImpl : public ProcessNodeObserver {
+ public:
+  ObserverDefaultImpl();
+  ~ObserverDefaultImpl() override;
+
+  // ProcessNodeObserver implementation:
+  void OnProcessNodeAdded(const ProcessNode* process_node) override {}
+  void OnProcessLifetimeChange(const ProcessNode* process_node) override {}
+  void OnBeforeProcessNodeRemoved(const ProcessNode* process_node) override {}
+  void OnExpectedTaskQueueingDurationSample(
+      const ProcessNode* process_node) override {}
+  void OnMainThreadTaskLoadIsLow(const ProcessNode* process_node) override {}
+  void OnAllFramesInProcessFrozen(const ProcessNode* process_node) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PROCESS_NODE_H_
diff --git a/components/performance_manager/public/graph/system_node.h b/components/performance_manager/public/graph/system_node.h
new file mode 100644
index 0000000..dacf1f03
--- /dev/null
+++ b/components/performance_manager/public/graph/system_node.h
@@ -0,0 +1,72 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_SYSTEM_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_SYSTEM_NODE_H_
+
+#include "base/macros.h"
+#include "components/performance_manager/public/graph/node.h"
+
+namespace performance_manager {
+
+class SystemNodeObserver;
+
+// The SystemNode represents system-wide state. There is at most one system node
+// in a graph.
+class SystemNode : public Node {
+ public:
+  using Observer = SystemNodeObserver;
+  class ObserverDefaultImpl;
+
+  SystemNode();
+  ~SystemNode() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SystemNode);
+};
+
+// Pure virtual observer interface. Derive from this if you want to be forced to
+// implement the entire interface.
+class SystemNodeObserver {
+ public:
+  SystemNodeObserver();
+  virtual ~SystemNodeObserver();
+
+  // Node lifetime notifications.
+
+  // Called when the |system_node| is added to the graph.
+  virtual void OnSystemNodeAdded(const SystemNode* system_node) = 0;
+
+  // Called before the |system_node| is removed from the graph.
+  virtual void OnBeforeSystemNodeRemoved(const SystemNode* system_node) = 0;
+
+  // Called when a new set of process memory metrics is available.
+  virtual void OnProcessMemoryMetricsAvailable(
+      const SystemNode* system_node) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SystemNodeObserver);
+};
+
+// Default implementation of observer that provides dummy versions of each
+// function. Derive from this if you only need to implement a few of the
+// functions.
+class SystemNode::ObserverDefaultImpl : public SystemNodeObserver {
+ public:
+  ObserverDefaultImpl();
+  ~ObserverDefaultImpl() override;
+
+  // SystemNodeObserver implementation:
+  void OnSystemNodeAdded(const SystemNode* system_node) override {}
+  void OnBeforeSystemNodeRemoved(const SystemNode* system_node) override {}
+  void OnProcessMemoryMetricsAvailable(const SystemNode* system_node) override {
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_SYSTEM_NODE_H_
diff --git a/components/performance_manager/public/graph/worker_node.h b/components/performance_manager/public/graph/worker_node.h
new file mode 100644
index 0000000..7c7d476
--- /dev/null
+++ b/components/performance_manager/public/graph/worker_node.h
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_WORKER_NODE_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_WORKER_NODE_H_
+
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "components/performance_manager/public/graph/node.h"
+
+class GURL;
+
+namespace base {
+class UnguessableToken;
+}
+
+namespace performance_manager {
+
+class WorkerNodeObserver;
+class FrameNode;
+class ProcessNode;
+
+// Represents a running instance of a WorkerGlobalScope.
+// See https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope.
+//
+// A worker is the equivalent of a thread on the web platform. To do
+// asynchronous work, a frame can create a dedicated worker or a shared worker
+// with Javascript. Those workers can now be used by sending an asynchronous
+// message using the postMessage() method, and replies can be received by
+// registering a message handler on the worker object.
+//
+// One notable special case is that dedicated workers can be nested. That means
+// that a dedicated worker can create another dedicated worker which is then
+// only accessible from the parent worker.
+//
+// Service workers are different. Instead of being created by the javascript
+// when needed, a service worker is registered once and affects all frames and
+// dedicated/shared workers whose URL matches the scope of the service worker.
+// A service worker is mainly used to intercept network requests and optionally
+// serve the responses from a cache, making the web site work offline.
+//
+// A client, from the point of view of the worker, is the frame or worker that
+// caused the worker to start running, either because it explicitly created it,
+// or a service worker is registered to handle their network requests.
+class WorkerNode : public Node {
+ public:
+  // The different possible worker types.
+  enum class WorkerType {
+    kDedicated,
+    kShared,
+    kService,
+  };
+
+  using Observer = WorkerNodeObserver;
+  class ObserverDefaultImpl;
+
+  WorkerNode();
+  ~WorkerNode() override;
+
+  // Returns the worker type. Note that this is different from the NodeTypeEnum.
+  virtual WorkerType GetWorkerType() const = 0;
+
+  // Returns the unique ID of the browser context that this worker belongs to.
+  virtual const std::string& GetBrowserContextID() const = 0;
+
+  // Returns the process node to which this worker belongs. This is a constant
+  // over the lifetime of the frame.
+  virtual const ProcessNode* GetProcessNode() const = 0;
+
+  // Returns the URL of the worker script.
+  virtual const GURL& GetURL() const = 0;
+
+  // Returns the dev tools token for this worker.
+  virtual const base::UnguessableToken& GetDevToolsToken() const = 0;
+
+  // Returns the frames that are clients of this worker.
+  virtual const base::flat_set<const FrameNode*> GetClientFrames() const = 0;
+
+  // Returns the workers that are clients of this worker.
+  // There are 2 cases where this is possible:
+  // - A dedicated worker can create nested workers. The parent worker becomes
+  //   one of its client worker.
+  // - A dedicated worker or a shared worker will become a client of the service
+  //   worker that handles their network requests.
+  virtual const base::flat_set<const WorkerNode*> GetClientWorkers() const = 0;
+
+  // Returns the child workers of this worker.
+  // There are 2 cases where a worker can be the child of another worker:
+  // - A dedicated worker can create nested workers. The nested worker becomes
+  //   a child worker of the parent.
+  // - A service worker will become a child worker of every worker for which
+  //   it handles network requests.
+  virtual const base::flat_set<const WorkerNode*> GetChildWorkers() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WorkerNode);
+};
+
+// Pure virtual observer interface. Derive from this if you want to be forced to
+// implement the entire interface.
+class WorkerNodeObserver {
+ public:
+  WorkerNodeObserver();
+  virtual ~WorkerNodeObserver();
+
+  // Node lifetime notifications.
+
+  // Called when a |worker_node| is added to the graph.
+  virtual void OnWorkerNodeAdded(const WorkerNode* worker_node) = 0;
+
+  // Called before a |worker_node| is removed from the graph.
+  virtual void OnBeforeWorkerNodeRemoved(const WorkerNode* worker_node) = 0;
+
+  // Notifications of property changes.
+
+  // Invoked when |client_frame_node| becomes a client of |worker_node|.
+  virtual void OnClientFrameAdded(const WorkerNode* worker_node,
+                                  const FrameNode* client_frame_node) = 0;
+
+  // Invoked when |client_frame_node| is no longer a client of |worker_node|.
+  virtual void OnBeforeClientFrameRemoved(
+      const WorkerNode* worker_node,
+      const FrameNode* client_frame_node) = 0;
+
+  // Invoked when |client_worker_node| becomes a client of |worker_node|.
+  virtual void OnClientWorkerAdded(const WorkerNode* worker_node,
+                                   const WorkerNode* client_worker_node) = 0;
+
+  // Invoked when |client_worker_node| is no longer a client of |worker_node|.
+  virtual void OnBeforeClientWorkerRemoved(
+      const WorkerNode* worker_node,
+      const WorkerNode* client_worker_node) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WorkerNodeObserver);
+};
+
+// Default implementation of observer that provides dummy versions of each
+// function. Derive from this if you only need to implement a few of the
+// functions.
+class WorkerNode::ObserverDefaultImpl : public WorkerNodeObserver {
+ public:
+  ObserverDefaultImpl();
+  ~ObserverDefaultImpl() override;
+
+  // WorkerNodeObserver implementation:
+
+  // Called when a |worker_node| is added to the graph.
+  void OnWorkerNodeAdded(const WorkerNode* worker_node) override {}
+  void OnBeforeWorkerNodeRemoved(const WorkerNode* worker_node) override {}
+  void OnClientFrameAdded(const WorkerNode* worker_node,
+                          const FrameNode* client_frame_node) override {}
+  void OnBeforeClientFrameRemoved(const WorkerNode* worker_node,
+                                  const FrameNode* client_frame_node) override {
+  }
+  void OnClientWorkerAdded(const WorkerNode* worker_node,
+                           const WorkerNode* client_worker_node) override {}
+  void OnBeforeClientWorkerRemoved(
+      const WorkerNode* worker_node,
+      const WorkerNode* client_worker_node) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_WORKER_NODE_H_