// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/performance_manager/graph/graph_impl.h"

#include <string_view>
#include <utility>

#include "base/check_op.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/map_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/node_base.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/graph/process_node_impl.h"
#include "components/performance_manager/graph/system_node_impl.h"
#include "components/performance_manager/graph/worker_node_impl.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/node_data_describer_registry.h"

namespace ukm {
class UkmEntryBuilder;
}  // namespace ukm

namespace performance_manager {

namespace {

// A unique type ID for this implementation.
const uintptr_t kGraphImplType = reinterpret_cast<uintptr_t>(&kGraphImplType);

base::Value::Dict DescribeNodeWithDescriber(const NodeDataDescriber& describer,
                                            const Node* node) {
  switch (node->GetNodeType()) {
    case NodeTypeEnum::kFrame:
      return describer.DescribeNodeData(FrameNodeImpl::FromNode(node));
    case NodeTypeEnum::kPage:
      return describer.DescribeNodeData(PageNodeImpl::FromNode(node));
    case NodeTypeEnum::kProcess:
      return describer.DescribeNodeData(ProcessNodeImpl::FromNode(node));
    case NodeTypeEnum::kSystem:
      return describer.DescribeNodeData(SystemNodeImpl::FromNode(node));
    case NodeTypeEnum::kWorker:
      return describer.DescribeNodeData(WorkerNodeImpl::FromNode(node));
  }
  NOTREACHED();
}

class NodeDataDescriberRegistryImpl : public NodeDataDescriberRegistry {
 public:
  ~NodeDataDescriberRegistryImpl() override;

  // NodeDataDescriberRegistry impl:
  void RegisterDescriber(const NodeDataDescriber* describer,
                         std::string_view name) override;
  void UnregisterDescriber(const NodeDataDescriber* describer) override;
  base::Value::Dict DescribeNodeData(const Node* node) const override;

  size_t size() const {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    return describers_.size();
  }

 private:
  base::flat_map<const NodeDataDescriber*, std::string> describers_
      GUARDED_BY_CONTEXT(sequence_checker_);
  SEQUENCE_CHECKER(sequence_checker_);
};

NodeDataDescriberRegistryImpl::~NodeDataDescriberRegistryImpl() {
  // All describers should have unregistered before the graph is destroyed.
  DCHECK(describers_.empty());
}

void NodeDataDescriberRegistryImpl::RegisterDescriber(
    const NodeDataDescriber* describer,
    std::string_view name) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if DCHECK_IS_ON()
  for (const auto& kv : describers_) {
    DCHECK_NE(kv.second, name) << "Name must be unique";
  }
#endif
  bool inserted =
      describers_.insert(std::make_pair(describer, std::string(name))).second;
  DCHECK(inserted);
}

void NodeDataDescriberRegistryImpl::UnregisterDescriber(
    const NodeDataDescriber* describer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  size_t erased = describers_.erase(describer);
  DCHECK_EQ(1u, erased);
}

base::Value::Dict NodeDataDescriberRegistryImpl::DescribeNodeData(
    const Node* node) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  base::Value::Dict result;
  for (const auto& [describer, describer_name] : describers_) {
    base::Value::Dict description = DescribeNodeWithDescriber(*describer, node);
    if (!description.empty()) {
      DCHECK_EQ(nullptr, result.FindDict(describer_name));
      result.Set(describer_name, std::move(description));
    }
  }
  return result;
}

}  // namespace

GraphImpl::GraphImpl() {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

GraphImpl::~GraphImpl() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK_EQ(lifecycle_state_, LifecycleState::kTearDownCalled);

  // All graph registered and owned objects should have been cleaned up.
  DCHECK(graph_owned_.empty());
  DCHECK(registered_objects_.empty());

  // All process and frame nodes should have been removed already.
  DCHECK(processes_by_pid_.empty());
  DCHECK(frames_by_id_.empty());

  // All nodes should have been removed.
  for (const NodeSet& nodes : nodes_) {
    DCHECK(nodes.empty());
  }
}

void GraphImpl::SetUp() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CreateSystemNode();

  execution_context_registry_impl_.SetUp(this);

  CHECK_EQ(lifecycle_state_, LifecycleState::kBeforeSetUp);
  lifecycle_state_ = LifecycleState::kSetUpCalled;
}

void GraphImpl::TearDown() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Clean up graph owned objects. This causes their TakeFromGraph callbacks to
  // be invoked, and ideally they clean up any observers they may have, etc.
  graph_owned_.ReleaseObjects(this);

  execution_context_registry_impl_.TearDown(this);

  // At this point, all typed observers should be empty.
  DCHECK(frame_node_observers_.empty());
  DCHECK(page_node_observers_.empty());
  DCHECK(process_node_observers_.empty());
  DCHECK(system_node_observers_.empty());

  // Remove the system node from the graph, this should be the only node left.
  ReleaseSystemNode();

  for (const NodeSet& nodes : nodes_) {
    DCHECK(nodes.empty());
  }

  CHECK_EQ(lifecycle_state_, LifecycleState::kSetUpCalled);
  lifecycle_state_ = LifecycleState::kTearDownCalled;
}

void GraphImpl::AddFrameNodeObserver(FrameNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  frame_node_observers_.AddObserver(observer);
}

void GraphImpl::AddPageNodeObserver(PageNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  page_node_observers_.AddObserver(observer);
}

void GraphImpl::AddProcessNodeObserver(ProcessNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  process_node_observers_.AddObserver(observer);
}

void GraphImpl::AddSystemNodeObserver(SystemNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  system_node_observers_.AddObserver(observer);
}

void GraphImpl::AddWorkerNodeObserver(WorkerNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  worker_node_observers_.AddObserver(observer);
}

void GraphImpl::RemoveFrameNodeObserver(FrameNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  frame_node_observers_.RemoveObserver(observer);
}

void GraphImpl::RemovePageNodeObserver(PageNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  page_node_observers_.RemoveObserver(observer);
}

void GraphImpl::RemoveProcessNodeObserver(ProcessNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  process_node_observers_.RemoveObserver(observer);
}

void GraphImpl::RemoveSystemNodeObserver(SystemNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  system_node_observers_.RemoveObserver(observer);
}

void GraphImpl::RemoveWorkerNodeObserver(WorkerNodeObserver* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  worker_node_observers_.RemoveObserver(observer);
}

void GraphImpl::PassToGraphImpl(std::unique_ptr<GraphOwned> graph_owned) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  graph_owned_.PassObject(std::move(graph_owned), this);
}

std::unique_ptr<GraphOwned> GraphImpl::TakeFromGraph(GraphOwned* graph_owned) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return graph_owned_.TakeObject(graph_owned, this);
}

void GraphImpl::RegisterObject(GraphRegistered* object) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  registered_objects_.RegisterObject(object);
}

void GraphImpl::UnregisterObject(GraphRegistered* object) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  registered_objects_.UnregisterObject(object);
}

const SystemNode* GraphImpl::GetSystemNode() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(system_node_.get());
  return system_node_.get();
}

Graph::NodeSetView<const ProcessNode*> GraphImpl::GetAllProcessNodes() const {
  return NodeSetView<const ProcessNode*>(
      GetNodesOfType(NodeTypeEnum::kProcess));
}

Graph::NodeSetView<const FrameNode*> GraphImpl::GetAllFrameNodes() const {
  return NodeSetView<const FrameNode*>(GetNodesOfType(NodeTypeEnum::kFrame));
}

Graph::NodeSetView<const PageNode*> GraphImpl::GetAllPageNodes() const {
  return NodeSetView<const PageNode*>(GetNodesOfType(NodeTypeEnum::kPage));
}

Graph::NodeSetView<const WorkerNode*> GraphImpl::GetAllWorkerNodes() const {
  return NodeSetView<const WorkerNode*>(GetNodesOfType(NodeTypeEnum::kWorker));
}

bool GraphImpl::HasOnlySystemNode() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!GetNodesOfType(NodeTypeEnum::kProcess).empty() ||
      !GetNodesOfType(NodeTypeEnum::kPage).empty() ||
      !GetNodesOfType(NodeTypeEnum::kFrame).empty() ||
      !GetNodesOfType(NodeTypeEnum::kWorker).empty()) {
    return false;
  }

  const NodeSet& system_nodes = GetNodesOfType(NodeTypeEnum::kSystem);
  return system_nodes.size() == 1 &&
         *system_nodes.begin() == GetSystemNodeImpl();
}

ukm::UkmRecorder* GraphImpl::GetUkmRecorder() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return ukm_recorder();
}

NodeDataDescriberRegistry* GraphImpl::GetNodeDataDescriberRegistry() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!describer_registry_) {
    describer_registry_ = std::make_unique<NodeDataDescriberRegistryImpl>();
  }

  return describer_registry_.get();
}

uintptr_t GraphImpl::GetImplType() const {
  return kGraphImplType;
}

const void* GraphImpl::GetImpl() const {
  return this;
}

#if DCHECK_IS_ON()
bool GraphImpl::IsOnGraphSequence() const {
  return sequence_checker_.CalledOnValidSequence();
}
#endif

GraphRegistered* GraphImpl::GetRegisteredObject(uintptr_t type_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return registered_objects_.GetRegisteredObject(type_id);
}

// static
GraphImpl* GraphImpl::FromGraph(const Graph* graph) {
  CHECK_EQ(kGraphImplType, graph->GetImplType());
  return reinterpret_cast<GraphImpl*>(const_cast<void*>(graph->GetImpl()));
}

bool GraphImpl::NodeInGraph(const NodeBase* node) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  const NodeSet& nodes = GetNodesOfType(node->GetNodeType());
  return base::Contains(nodes, node->ToNode());
}

bool GraphImpl::NodeEdgesArePublic(const NodeBase* node) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  switch (GetNodeState(node)) {
    case NodeState::kNotInGraph:
    case NodeState::kInitializingNotInGraph:
      // Hide node connections until edges are initialized.
      return false;
    case NodeState::kInitializingEdges:
    case NodeState::kUninitializingEdges:
      // InitializingFrameNodeObservers are called during this state, and must
      // see the edges.
      return true;
    case NodeState::kJoiningGraph:
    case NodeState::kActiveInGraph:
    case NodeState::kLeavingGraph:
      return true;
    case NodeState::kLeftGraph:
      // Hide node connections during teardown.
      return false;
  }
  NOTREACHED();
}

ProcessNodeImpl* GraphImpl::GetProcessNodeByPid(base::ProcessId pid) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FindPtrOrNull(processes_by_pid_, pid);
}

FrameNodeImpl* GraphImpl::GetFrameNodeById(
    RenderProcessHostId render_process_id,
    int render_frame_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FindPtrOrNull(
      frames_by_id_, ProcessAndFrameId(render_process_id, render_frame_id));
}

Graph::NodeSetView<ProcessNodeImpl*> GraphImpl::GetAllProcessNodeImpls() const {
  return NodeSetView<ProcessNodeImpl*>(GetNodesOfType(NodeTypeEnum::kProcess));
}

Graph::NodeSetView<FrameNodeImpl*> GraphImpl::GetAllFrameNodeImpls() const {
  return NodeSetView<FrameNodeImpl*>(GetNodesOfType(NodeTypeEnum::kFrame));
}

Graph::NodeSetView<PageNodeImpl*> GraphImpl::GetAllPageNodeImpls() const {
  return NodeSetView<PageNodeImpl*>(GetNodesOfType(NodeTypeEnum::kPage));
}

Graph::NodeSetView<WorkerNodeImpl*> GraphImpl::GetAllWorkerNodeImpls() const {
  return NodeSetView<WorkerNodeImpl*>(GetNodesOfType(NodeTypeEnum::kWorker));
}

void GraphImpl::AddNewNode(NodeBase* new_node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!node_in_transition_);

  // Add the node to the graph.
  NodeSet& nodes = GetNodesOfType(new_node->GetNodeType());
  auto it = nodes.insert(new_node->ToNode());
  DCHECK(it.second);  // Inserted successfully

  // Advance the node through its lifecycle until it is active in the graph. See
  // NodeBase and NodeState for full details of the lifecycle.
  node_in_transition_ = new_node;
  node_in_transition_state_ = NodeState::kNotInGraph;
  new_node->SetGraphPointer(this);
  node_in_transition_state_ = NodeState::kInitializingNotInGraph;
  new_node->OnInitializingProperties();
  DispatchBeforeNodeAddedNotifications(new_node);
  node_in_transition_state_ = NodeState::kInitializingEdges;
  new_node->OnInitializingEdges();
  node_in_transition_state_ = NodeState::kJoiningGraph;
  DispatchNodeAddedNotifications(new_node);
  node_in_transition_ = nullptr;
  node_in_transition_state_ = NodeState::kNotInGraph;
  new_node->OnAfterJoiningGraph();
}

void GraphImpl::RemoveNode(NodeBase* node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(NodeInGraph(node));
  DCHECK_EQ(this, node->graph());
  DCHECK(!node_in_transition_);

  // Walk the node through the latter half of its lifecycle. See NodeBase and
  // NodeState for full details of the lifecycle.
  node->OnBeforeLeavingGraph();
  node_in_transition_ = node;
  node_in_transition_state_ = NodeState::kLeavingGraph;
  DispatchBeforeNodeRemovedNotifications(node);
  node_in_transition_state_ = NodeState::kUninitializingEdges;
  node->OnUninitializingEdges();
  node_in_transition_state_ = NodeState::kLeftGraph;
  DispatchNodeRemovedNotifications(node);
  node->CleanUpNodeState();
  node->ClearGraphPointer();
  node_in_transition_ = nullptr;
  node_in_transition_state_ = NodeState::kNotInGraph;

  // Remove the node itself.
  NodeSet& nodes = GetNodesOfType(node->GetNodeType());
  size_t erased = nodes.erase(node->ToNode());
  DCHECK_EQ(1u, erased);
}

size_t GraphImpl::NodeDataDescriberCountForTesting() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!describer_registry_) {
    return 0;
  }
  auto* registry = static_cast<const NodeDataDescriberRegistryImpl*>(
      describer_registry_.get());
  return registry->size();
}

Graph::NodeSet& GraphImpl::GetNodesOfType(NodeTypeEnum node_type) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return nodes_.at(base::strict_cast<size_t>(node_type));
}

const Graph::NodeSet& GraphImpl::GetNodesOfType(NodeTypeEnum node_type) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return nodes_.at(base::strict_cast<size_t>(node_type));
}

NodeState GraphImpl::GetNodeState(const NodeBase* node) const {
  DCHECK_EQ(this, node->graph());
  // If this is a transitioning node (being added to or removed from the graph)
  // then return the appropriate state.
  if (node == node_in_transition_) {
    return node_in_transition_state_;
  }
  // Otherwise, this is a node at steady state.
  return NodeState::kActiveInGraph;
}

template <>
const GraphImpl::ObserverList<FrameNodeObserver>& GraphImpl::GetObservers()
    const {
  return frame_node_observers_;
}

template <>
const GraphImpl::ObserverList<PageNodeObserver>& GraphImpl::GetObservers()
    const {
  return page_node_observers_;
}

template <>
const GraphImpl::ObserverList<ProcessNodeObserver>& GraphImpl::GetObservers()
    const {
  return process_node_observers_;
}

template <>
const GraphImpl::ObserverList<SystemNodeObserver>& GraphImpl::GetObservers()
    const {
  return system_node_observers_;
}

template <>
const GraphImpl::ObserverList<WorkerNodeObserver>& GraphImpl::GetObservers()
    const {
  return worker_node_observers_;
}

GraphImpl::ProcessAndFrameId::ProcessAndFrameId(
    RenderProcessHostId render_process_id,
    int render_frame_id)
    : render_process_id(render_process_id), render_frame_id(render_frame_id) {}

bool GraphImpl::ProcessAndFrameId::operator<(
    const ProcessAndFrameId& other) const {
  return std::tie(render_process_id, render_frame_id) <
         std::tie(other.render_process_id, other.render_frame_id);
}

GraphImpl::ProcessAndFrameId::~ProcessAndFrameId() = default;

GraphImpl::ProcessAndFrameId::ProcessAndFrameId(
    const GraphImpl::ProcessAndFrameId& other) = default;

GraphImpl::ProcessAndFrameId& GraphImpl::ProcessAndFrameId::operator=(
    const GraphImpl::ProcessAndFrameId& other) = default;

void GraphImpl::DispatchBeforeNodeAddedNotifications(NodeBase* node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK_EQ(node->GetNodeState(), NodeState::kInitializingNotInGraph);

  // This handles the strongly typed observer notifications.
  switch (node->GetNodeType()) {
    case NodeTypeEnum::kFrame: {
      auto* frame_node = FrameNodeImpl::FromNodeBase(node);
      for (auto& observer : frame_node_observers_) {
        observer.OnBeforeFrameNodeAdded(
            frame_node, frame_node->parent_frame_node(),
            frame_node->page_node(), frame_node->process_node(),
            frame_node->parent_or_outer_document_or_embedder());
      }
      return;
    }
    case NodeTypeEnum::kPage: {
      auto* page_node = PageNodeImpl::FromNodeBase(node);
      for (auto& observer : page_node_observers_) {
        observer.OnBeforePageNodeAdded(page_node);
      }
      return;
    }
    case NodeTypeEnum::kProcess: {
      auto* process_node = ProcessNodeImpl::FromNodeBase(node);
      for (auto& observer : process_node_observers_) {
        observer.OnBeforeProcessNodeAdded(process_node);
      }
      return;
    }
    case NodeTypeEnum::kSystem:
      // Do nothing.
      return;
    case NodeTypeEnum::kWorker: {
      auto* worker_node = WorkerNodeImpl::FromNodeBase(node);
      for (auto& observer : worker_node_observers_) {
        observer.OnBeforeWorkerNodeAdded(worker_node,
                                         worker_node->process_node());
      }
      return;
    }
  }
  NOTREACHED();
}

void GraphImpl::DispatchNodeAddedNotifications(NodeBase* node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK_EQ(node->GetNodeState(), NodeState::kJoiningGraph);

  // This handles the strongly typed observer notifications.
  switch (node->GetNodeType()) {
    case NodeTypeEnum::kFrame: {
      auto* frame_node = FrameNodeImpl::FromNodeBase(node);
      for (auto& observer : frame_node_observers_) {
        observer.OnFrameNodeAdded(frame_node);
      }
      return;
    }
    case NodeTypeEnum::kPage: {
      auto* page_node = PageNodeImpl::FromNodeBase(node);
      for (auto& observer : page_node_observers_) {
        observer.OnPageNodeAdded(page_node);
      }
      return;
    }
    case NodeTypeEnum::kProcess: {
      auto* process_node = ProcessNodeImpl::FromNodeBase(node);
      for (auto& observer : process_node_observers_) {
        observer.OnProcessNodeAdded(process_node);
      }
      return;
    }
    case NodeTypeEnum::kSystem:
      // Do nothing.
      return;
    case NodeTypeEnum::kWorker: {
      auto* worker_node = WorkerNodeImpl::FromNodeBase(node);
      for (auto& observer : worker_node_observers_) {
        observer.OnWorkerNodeAdded(worker_node);
      }
      return;
    }
  }
  NOTREACHED();
}

void GraphImpl::DispatchBeforeNodeRemovedNotifications(NodeBase* node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK_EQ(node->GetNodeState(), NodeState::kLeavingGraph);

  switch (node->GetNodeType()) {
    case NodeTypeEnum::kFrame: {
      auto* frame_node = FrameNodeImpl::FromNodeBase(node);
      for (auto& observer : frame_node_observers_) {
        observer.OnBeforeFrameNodeRemoved(frame_node);
      }
      return;
    }
    case NodeTypeEnum::kPage: {
      auto* page_node = PageNodeImpl::FromNodeBase(node);
      for (auto& observer : page_node_observers_) {
        observer.OnBeforePageNodeRemoved(page_node);
      }
      return;
    }
    case NodeTypeEnum::kProcess: {
      auto* process_node = ProcessNodeImpl::FromNodeBase(node);
      for (auto& observer : process_node_observers_) {
        observer.OnBeforeProcessNodeRemoved(process_node);
      }
      return;
    }
    case NodeTypeEnum::kSystem:
      // Do nothing.
      return;
    case NodeTypeEnum::kWorker: {
      auto* worker_node = WorkerNodeImpl::FromNodeBase(node);
      for (auto& observer : worker_node_observers_) {
        observer.OnBeforeWorkerNodeRemoved(worker_node);
      }
      return;
    }
  }
  NOTREACHED();
}

void GraphImpl::DispatchNodeRemovedNotifications(NodeBase* node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK_EQ(node->GetNodeState(), NodeState::kLeftGraph);

  // This handles the strongly typed observer notifications.
  switch (node->GetNodeType()) {
    case NodeTypeEnum::kFrame: {
      auto* frame_node = FrameNodeImpl::FromNodeBase(node);
      for (auto& observer : frame_node_observers_) {
        observer.OnFrameNodeRemoved(
            frame_node, frame_node->parent_frame_node(),
            frame_node->page_node(), frame_node->process_node(),
            frame_node->parent_or_outer_document_or_embedder());
      }
      return;
    }
    case NodeTypeEnum::kPage: {
      auto* page_node = PageNodeImpl::FromNodeBase(node);
      for (auto& observer : page_node_observers_) {
        observer.OnPageNodeRemoved(page_node);
      }
      return;
    }
    case NodeTypeEnum::kProcess: {
      auto* process_node = ProcessNodeImpl::FromNodeBase(node);
      for (auto& observer : process_node_observers_) {
        observer.OnProcessNodeRemoved(process_node);
      }
      return;
    }
    case NodeTypeEnum::kSystem:
      // Do nothing.
      return;
    case NodeTypeEnum::kWorker: {
      auto* worker_node = WorkerNodeImpl::FromNodeBase(node);
      for (auto& observer : worker_node_observers_) {
        observer.OnWorkerNodeRemoved(worker_node, worker_node->process_node());
      }
      return;
    }
  }
  NOTREACHED();
}

int64_t GraphImpl::GetNextNodeSerializationId() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return ++current_node_serialization_id_;
}

void GraphImpl::BeforeProcessPidChange(ProcessNodeImpl* process,
                                       base::ProcessId new_pid) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // On Windows, PIDs are aggressively reused, and because not all process
  // creation/death notifications are synchronized, it's possible for more than
  // one process node to have the same PID. To handle this, the second and
  // subsequent registration override earlier registrations, while
  // unregistration will only unregister the current holder of the PID.
  if (process->GetProcessId() != base::kNullProcessId) {
    auto it = processes_by_pid_.find(process->GetProcessId());
    if (it != processes_by_pid_.end() && it->second == process) {
      processes_by_pid_.erase(it);
    }
  }
  if (new_pid != base::kNullProcessId) {
    processes_by_pid_[new_pid] = process;
  }
}

void GraphImpl::RegisterFrameNodeForId(RenderProcessHostId render_process_id,
                                       int render_frame_id,
                                       FrameNodeImpl* frame_node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto insert_result = frames_by_id_.insert(
      {ProcessAndFrameId(render_process_id, render_frame_id), frame_node});
  DCHECK(insert_result.second);
}

void GraphImpl::UnregisterFrameNodeForId(RenderProcessHostId render_process_id,
                                         int render_frame_id,
                                         FrameNodeImpl* frame_node) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  const ProcessAndFrameId process_and_frame_id(render_process_id,
                                               render_frame_id);
  DCHECK_EQ(frames_by_id_.find(process_and_frame_id)->second, frame_node);
  frames_by_id_.erase(process_and_frame_id);
}

void GraphImpl::CreateSystemNode() {
  CHECK(!system_node_);
  // Create the singleton system node instance. Ownership is taken by the
  // graph.
  system_node_ = std::make_unique<SystemNodeImpl>();
  AddNewNode(system_node_.get());
}

void GraphImpl::ReleaseSystemNode() {
  CHECK(system_node_);
  RemoveNode(system_node_.get());
  system_node_.reset();
}

}  // namespace performance_manager
