// Copyright 2017 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.

#include "services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h"

#include <inttypes.h>
#include <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
#include "services/resource_coordinator/memory_instrumentation/aggregate_metrics_processor.h"
#include "services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h"
#include "services/resource_coordinator/memory_instrumentation/switches.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"

#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif

using base::trace_event::TracedValue;
using perfetto::trace_processor::GlobalNodeGraph;
using perfetto::trace_processor::LevelOfDetail;
using perfetto::trace_processor::RawMemoryGraphNode;
using Node = perfetto::trace_processor::GlobalNodeGraph::Node;
using perfetto::trace_processor::GraphProcessor;

namespace memory_instrumentation {

namespace {

// Returns the private memory footprint calculated from given |os_dump|.
//
// See design docs linked in the bugs for the rationale of the computation:
// - Linux/Android: https://crbug.com/707019 .
// - Mac OS: https://crbug.com/707021 .
// - Win: https://crbug.com/707022 .
uint32_t CalculatePrivateFootprintKb(const mojom::RawOSMemDump& os_dump,
                                     uint32_t shared_resident_kb) {
  DCHECK(os_dump.platform_private_footprint);
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
    defined(OS_FUCHSIA)
  uint64_t rss_anon_bytes = os_dump.platform_private_footprint->rss_anon_bytes;
  uint64_t vm_swap_bytes = os_dump.platform_private_footprint->vm_swap_bytes;
  return (rss_anon_bytes + vm_swap_bytes) / 1024;
#elif defined(OS_MAC)
  if (base::mac::IsAtLeastOS10_12()) {
    uint64_t phys_footprint_bytes =
        os_dump.platform_private_footprint->phys_footprint_bytes;
    return base::saturated_cast<uint32_t>(
        base::saturated_cast<int32_t>(phys_footprint_bytes / 1024) -
        base::saturated_cast<int32_t>(shared_resident_kb));
  } else {
    uint64_t internal_bytes =
        os_dump.platform_private_footprint->internal_bytes;
    uint64_t compressed_bytes =
        os_dump.platform_private_footprint->compressed_bytes;
    return base::saturated_cast<uint32_t>(
        base::saturated_cast<int32_t>((internal_bytes + compressed_bytes) /
                                      1024) -
        base::saturated_cast<int32_t>(shared_resident_kb));
  }
#elif defined(OS_WIN)
  return base::saturated_cast<int32_t>(
      os_dump.platform_private_footprint->private_bytes / 1024);
#else
  return 0;
#endif
}

memory_instrumentation::mojom::OSMemDumpPtr CreatePublicOSDump(
    const mojom::RawOSMemDump& internal_os_dump,
    uint32_t shared_resident_kb) {
  mojom::OSMemDumpPtr os_dump = mojom::OSMemDump::New();

  os_dump->resident_set_kb = internal_os_dump.resident_set_kb;
  os_dump->peak_resident_set_kb = internal_os_dump.peak_resident_set_kb;
  os_dump->is_peak_rss_resettable = internal_os_dump.is_peak_rss_resettable;
  os_dump->private_footprint_kb =
      CalculatePrivateFootprintKb(internal_os_dump, shared_resident_kb);
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
  os_dump->private_footprint_swap_kb =
      internal_os_dump.platform_private_footprint->vm_swap_bytes / 1024;
#endif
  return os_dump;
}

void NodeAsValueIntoRecursively(const GlobalNodeGraph::Node& node,
                                TracedValue* value,
                                std::vector<base::StringPiece>* path) {
  // Don't dump the root node.
  if (!path->empty()) {
    std::string string_conversion_buffer;

    std::string name = base::JoinString(*path, "/");
    value->BeginDictionaryWithCopiedName(name);

    if (!node.id().empty())
      value->SetString("id", node.id().ToString());

    value->BeginDictionary("attrs");
    for (const auto& name_to_entry : node.const_entries()) {
      const auto& entry = name_to_entry.second;
      value->BeginDictionaryWithCopiedName(name_to_entry.first);
      switch (entry.type) {
        case GlobalNodeGraph::Node::Entry::kUInt64:
          base::SStringPrintf(&string_conversion_buffer, "%" PRIx64,
                              entry.value_uint64);
          value->SetString("type", RawMemoryGraphNode::kTypeScalar);
          value->SetString("value", string_conversion_buffer);
          break;
        case GlobalNodeGraph::Node::Entry::kString:
          value->SetString("type", RawMemoryGraphNode::kTypeString);
          value->SetString("value", entry.value_string);
          break;
      }
      switch (entry.units) {
        case GlobalNodeGraph::Node::Entry::ScalarUnits::kBytes:
          value->SetString("units", RawMemoryGraphNode::kUnitsBytes);
          break;
        case GlobalNodeGraph::Node::Entry::ScalarUnits::kObjects:
          value->SetString("units", RawMemoryGraphNode::kUnitsObjects);
          break;
      }
      value->EndDictionary();
    }
    value->EndDictionary();  // "attrs": { ... }

    if (node.is_weak())
      value->SetInteger("flags", RawMemoryGraphNode::Flags::kWeak);

    value->EndDictionary();  // "allocator_name/heap_subheap": { ... }
  }

  for (const auto& name_to_child : node.const_children()) {
    path->push_back(name_to_child.first);
    NodeAsValueIntoRecursively(*name_to_child.second, value, path);
    path->pop_back();
  }
}

std::unique_ptr<TracedValue> GetChromeDumpTracedValue(
    const GlobalNodeGraph::Process& process) {
  std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
  if (!process.root()->const_children().empty()) {
    traced_value->BeginDictionary("allocators");
    std::vector<base::StringPiece> path;
    NodeAsValueIntoRecursively(*process.root(), traced_value.get(), &path);
    traced_value->EndDictionary();
  }
  return traced_value;
}

std::unique_ptr<TracedValue> GetChromeDumpAndGlobalAndEdgesTracedValue(
    const GlobalNodeGraph::Process& process,
    const GlobalNodeGraph::Process& global_process,
    const std::forward_list<GlobalNodeGraph::Edge>& edges) {
  std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
  bool suppress_graphs = process.root()->const_children().empty() &&
                         global_process.root()->const_children().empty();

  if (!suppress_graphs) {
    traced_value->BeginDictionary("allocators");
    std::vector<base::StringPiece> path;
    NodeAsValueIntoRecursively(*process.root(), traced_value.get(), &path);
    NodeAsValueIntoRecursively(*global_process.root(), traced_value.get(),
                               &path);
    traced_value->EndDictionary();
  }
  traced_value->BeginArray("allocators_graph");
  for (const auto& edge : edges) {
    traced_value->BeginDictionary();
    traced_value->SetString("source", edge.source()->id().ToString());
    traced_value->SetString("target", edge.target()->id().ToString());
    traced_value->SetInteger("importance", edge.priority());
    traced_value->EndDictionary();
  }
  traced_value->EndArray();
  return traced_value;
}

}  // namespace

// static
void QueuedRequestDispatcher::SetUpAndDispatch(
    QueuedRequest* request,
    const std::vector<ClientInfo>& clients,
    const ChromeCallback& chrome_callback,
    const OsCallback& os_callback) {
  using ResponseType = QueuedRequest::PendingResponse::Type;
  DCHECK(!request->dump_in_progress);
  request->dump_in_progress = true;

  request->start_time = base::TimeTicks::Now();

  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
      base::trace_event::MemoryDumpManager::kTraceCategory, "GlobalMemoryDump",
      TRACE_ID_LOCAL(request->dump_guid), "dump_type",
      base::trace_event::MemoryDumpTypeToString(request->args.dump_type),
      "level_of_detail",
      base::trace_event::MemoryDumpLevelOfDetailToString(
          request->args.level_of_detail));

  request->failed_memory_dump_count = 0;

  // Note: the service process itself is registered as a ClientProcess and
  // will be treated like any other process for the sake of memory dumps.
  request->pending_responses.clear();

  for (const auto& client_info : clients) {
    mojom::ClientProcess* client = client_info.client;

    // If we're only looking for a single pid process, then ignore clients
    // with different pid.
    if (request->args.pid != base::kNullProcessId &&
        request->args.pid != client_info.pid) {
      continue;
    }

    request->responses[client_info.pid].process_id = client_info.pid;
    request->responses[client_info.pid].process_type = client_info.process_type;
    request->responses[client_info.pid].service_name = client_info.service_name;

    // Don't request a chrome memory dump at all if the client only wants the
    // a memory footprint.
    //
    // This must occur before the call to RequestOSMemoryDump, as
    // ClientProcessImpl will [for macOS], delay the calculations for the
    // OSMemoryDump until the Chrome memory dump is finished. See
    // https://bugs.chromium.org/p/chromium/issues/detail?id=812346#c16 for more
    // details.
    if (!request->args.memory_footprint_only) {
      request->pending_responses.insert(
          {client_info.pid, ResponseType::kChromeDump});
      client->RequestChromeMemoryDump(
          request->GetRequestArgs(),
          base::BindOnce(chrome_callback, client_info.pid));
    }

// On most platforms each process can dump data about their own process
// so ask each process to do so Linux is special see below.
#if !defined(OS_LINUX) && !defined(OS_CHROMEOS)
    request->pending_responses.insert({client_info.pid, ResponseType::kOSDump});
    client->RequestOSMemoryDump(request->memory_map_option(),
                                {base::kNullProcessId},
                                base::BindOnce(os_callback, client_info.pid));
#endif  // !defined(OS_LINUX) && !defined(OS_CHROMEOS)

    // If we are in the single pid case, then we've already found the only
    // process we're looking for.
    if (request->args.pid != base::kNullProcessId)
      break;
  }

// In some cases, OS stats can only be dumped from a privileged process to
// get around to sandboxing/selinux restrictions (see crbug.com/461788).
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
  std::vector<base::ProcessId> pids;
  mojom::ClientProcess* browser_client = nullptr;
  base::ProcessId browser_client_pid = base::kNullProcessId;
  pids.reserve(request->args.pid == base::kNullProcessId ? clients.size() : 1);
  for (const auto& client_info : clients) {
    if (request->args.pid == base::kNullProcessId ||
        client_info.pid == request->args.pid) {
      pids.push_back(client_info.pid);
    }
    if (client_info.process_type == mojom::ProcessType::BROWSER) {
      browser_client = client_info.client;
      browser_client_pid = client_info.pid;
    }
  }
  if (clients.size() > 0) {
    DCHECK(browser_client);
  }
  if (browser_client && pids.size() > 0) {
    request->pending_responses.insert(
        {browser_client_pid, ResponseType::kOSDump});
    auto callback = base::BindOnce(os_callback, browser_client_pid);
    browser_client->RequestOSMemoryDump(request->memory_map_option(), pids,
                                        std::move(callback));
  }
#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)

  // In this case, we have not found the pid we are looking for so increment
  // the failed dump count and exit.
  if (request->args.pid != base::kNullProcessId &&
      request->pending_responses.empty()) {
    DLOG(ERROR) << "Memory dump request failed due to missing pid "
                << request->args.pid;
    request->failed_memory_dump_count++;
    return;
  }
}

// static
void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
    QueuedVmRegionRequest* request,
    const std::vector<ClientInfo>& clients,
    const std::vector<base::ProcessId>& desired_pids,
    const OsCallback& os_callback) {
// On Linux, OS stats can only be dumped from a privileged process to
// get around to sandboxing/selinux restrictions (see crbug.com/461788).
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
  mojom::ClientProcess* browser_client = nullptr;
  base::ProcessId browser_client_pid = 0;
  for (const auto& client_info : clients) {
    if (client_info.process_type == mojom::ProcessType::BROWSER) {
      browser_client = client_info.client;
      browser_client_pid = client_info.pid;
      break;
    }
  }

  if (!browser_client) {
    DLOG(ERROR) << "Missing browser client.";
    return;
  }

  request->pending_responses.insert(browser_client_pid);
  request->responses[browser_client_pid].process_id = browser_client_pid;
  auto callback = base::BindOnce(os_callback, browser_client_pid);
  browser_client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
                                      desired_pids, std::move(callback));
#else
  for (const auto& client_info : clients) {
    if (std::find(desired_pids.begin(), desired_pids.end(), client_info.pid) !=
        desired_pids.end()) {
      mojom::ClientProcess* client = client_info.client;
      request->pending_responses.insert(client_info.pid);
      request->responses[client_info.pid].process_id = client_info.pid;
      request->responses[client_info.pid].service_name =
          client_info.service_name;
      client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
                                  {base::kNullProcessId},
                                  base::BindOnce(os_callback, client_info.pid));
    }
  }
#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
}

// static
QueuedRequestDispatcher::VmRegions
QueuedRequestDispatcher::FinalizeVmRegionRequest(
    QueuedVmRegionRequest* request) {
  VmRegions results;
  for (auto& response : request->responses) {
    const base::ProcessId& original_pid = response.second.process_id;

    // |response| accumulates the replies received by each client process.
    // On Linux, the browser process will provide all OS dumps. On non-Linux,
    // each client process provides 1 OS dump, % the case where the client is
    // disconnected mid dump.
    OSMemDumpMap& extra_os_dumps = response.second.os_dumps;
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
    for (auto& kv : extra_os_dumps) {
      auto pid = kv.first == base::kNullProcessId ? original_pid : kv.first;
      DCHECK(results.find(pid) == results.end());
      results.emplace(pid, std::move(kv.second->memory_maps));
    }
#else
    // This can be empty if the client disconnects before providing both
    // dumps. See UnregisterClientProcess().
    DCHECK_LE(extra_os_dumps.size(), 1u);
    for (auto& kv : extra_os_dumps) {
      // When the OS dump comes from child processes, the pid is supposed to be
      // not used. We know the child process pid at the time of the request and
      // also wouldn't trust pids coming from child processes.
      DCHECK_EQ(base::kNullProcessId, kv.first);

      // Check we don't receive duplicate OS dumps for the same process.
      DCHECK(results.find(original_pid) == results.end());

      results.emplace(original_pid, std::move(kv.second->memory_maps));
    }
#endif
  }
  return results;
}

void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
                                       TracingObserver* tracing_observer,
                                       bool use_proto_writer) {
  DCHECK(request->dump_in_progress);
  DCHECK(request->pending_responses.empty());

  // Reconstruct a map of pid -> ProcessMemoryDump by reassembling the responses
  // received by the clients for this dump. In some cases the response coming
  // from one client can also provide the dump of OS counters for other
  // processes. A concrete case is Linux, where the browser process provides
  // details for the child processes to get around sandbox restrictions on
  // opening /proc pseudo files.

  // All the pointers in the maps will continue to be owned by |request|
  // which outlives these containers.
  std::map<base::ProcessId, mojom::ProcessType> pid_to_process_type;
  std::map<base::ProcessId, const base::trace_event::ProcessMemoryDump*>
      pid_to_pmd;
  std::map<base::ProcessId, mojom::RawOSMemDump*> pid_to_os_dump;
  for (auto& response : request->responses) {
    const base::ProcessId& original_pid = response.second.process_id;
    pid_to_process_type[original_pid] = response.second.process_type;

    // |chrome_dump| can be nullptr if this was a OS-counters only response.
    pid_to_pmd[original_pid] = response.second.chrome_dump.get();

    // |response| accumulates the replies received by each client process.
    // Depending on the OS each client process might return 1 chrome + 1 OS
    // dump each or, in the case of Linux, only 1 chrome dump each % the
    // browser process which will provide all the OS dumps.
    // In the former case (!OS_LINUX) we expect client processes to have
    // exactly one OS dump in their |response|, % the case when they
    // unexpectedly disconnect in the middle of a dump (e.g. because they
    // crash). In the latter case (OS_LINUX) we expect the full map to come
    // from the browser process response.
    OSMemDumpMap& extra_os_dumps = response.second.os_dumps;
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
    for (const auto& kv : extra_os_dumps) {
      auto pid = kv.first == base::kNullProcessId ? original_pid : kv.first;
      DCHECK_EQ(pid_to_os_dump[pid], nullptr);
      pid_to_os_dump[pid] = kv.second.get();
    }
#else
    // This can be empty if the client disconnects before providing both
    // dumps. See UnregisterClientProcess().
    DCHECK_LE(extra_os_dumps.size(), 1u);
    for (const auto& kv : extra_os_dumps) {
      // When the OS dump comes from child processes, the pid is supposed to be
      // not used. We know the child process pid at the time of the request and
      // also wouldn't trust pids coming from child processes.
      DCHECK_EQ(base::kNullProcessId, kv.first);

      // Check we don't receive duplicate OS dumps for the same process.
      DCHECK_EQ(pid_to_os_dump[original_pid], nullptr);

      pid_to_os_dump[original_pid] = kv.second.get();
    }
#endif
  }

  MemoryDumpMapConverter converter;
  perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap perfettoNodeMap =
      converter.Convert(pid_to_pmd);

  // Generate the global memory graph from the map of pids to dumps, removing
  // weak nodes.
  // TODO (crbug.com/1112671): We should avoid graph processing once we moved
  // the shared footprint computation to perfetto.
  std::unique_ptr<GlobalNodeGraph> global_graph =
      GraphProcessor::CreateMemoryGraph(perfettoNodeMap);
  GraphProcessor::RemoveWeakNodesFromGraph(global_graph.get());

  // Compute the shared memory footprint for each process from the graph.
  auto original =
      GraphProcessor::ComputeSharedFootprintFromGraph(*global_graph);
  std::map<base::ProcessId, uint64_t> shared_footprints;
  for (const auto& item : original) {
    shared_footprints.emplace(static_cast<base::ProcessId>(item.first),
                              item.second);
  }
  // Perform the rest of the computation on the graph.
  GraphProcessor::AddOverheadsAndPropagateEntries(global_graph.get());
  GraphProcessor::CalculateSizesForGraph(global_graph.get());

  // The same timestamp needs to be set for all dumps in the memory snapshot.
  base::TimeTicks timestamp = TRACE_TIME_TICKS_NOW();

  // Build up the global dump by iterating on the |valid| process dumps.
  mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New());
  global_dump->start_time = request->start_time;
  global_dump->process_dumps.reserve(request->responses.size());
  for (const auto& response : request->responses) {
    base::ProcessId pid = response.second.process_id;

    // On Linux, we may also have the browser process as a response.
    // Just ignore it if we are looking for the single pid case.
    if (request->args.pid != base::kNullProcessId && pid != request->args.pid)
      continue;

    // These pointers are owned by |request|.
    mojom::RawOSMemDump* raw_os_dump = pid_to_os_dump[pid];
    auto* raw_chrome_dump = pid_to_pmd[pid];

    // If we have the OS dump we should have the platform private footprint.
    DCHECK(!raw_os_dump || raw_os_dump->platform_private_footprint);

    // If the raw dump exists, create a summarised version of it.
    mojom::OSMemDumpPtr os_dump = nullptr;
    if (raw_os_dump) {
      uint64_t shared_resident_kb = 0;
#if defined(OS_MAC)
      // The resident, anonymous shared memory for each process is only
      // relevant on macOS.
      const auto process_graph_it =
          global_graph->process_node_graphs().find(pid);
      if (process_graph_it != global_graph->process_node_graphs().end()) {
        const auto& process_graph = process_graph_it->second;
        auto* node = process_graph->FindNode("shared_memory");
        if (node) {
          const auto& entry =
              node->entries()->find(RawMemoryGraphNode::kNameSize);
          if (entry != node->entries()->end())
            shared_resident_kb = entry->second.value_uint64 / 1024;
        }
      }
#endif
      os_dump = CreatePublicOSDump(
          *raw_os_dump, base::saturated_cast<uint32_t>(shared_resident_kb));
      os_dump->shared_footprint_kb =
          base::saturated_cast<uint32_t>(shared_footprints[pid] / 1024);
    }

    // Trace the OS and Chrome dumps if they exist.
    if (request->args.add_to_trace) {
      if (raw_os_dump) {
        bool trace_os_success = tracing_observer->AddOsDumpToTraceIfEnabled(
            request->GetRequestArgs(), pid, *os_dump, raw_os_dump->memory_maps,
            timestamp);
        if (!trace_os_success) {
          DLOG(ERROR) << "Tracing is disabled or not setup yet while receiving "
                         "OS dump for pid "
                      << pid;
          request->failed_memory_dump_count++;
        }
      }

      if (raw_chrome_dump) {
        bool trace_chrome_success = AddChromeMemoryDumpToTrace(
            request->GetRequestArgs(), pid, *raw_chrome_dump, *global_graph,
            pid_to_process_type, tracing_observer, use_proto_writer, timestamp);
        if (!trace_chrome_success) {
          DLOG(ERROR) << "Tracing is disabled or not setup yet while receiving "
                         "Chrome dump for pid "
                      << pid;
          request->failed_memory_dump_count++;
        }
      }
    }

    bool valid = false;
    if (request->args.memory_footprint_only) {
      valid = raw_os_dump;
    } else {
      // Ignore incomplete results (can happen if the client
      // crashes/disconnects).
      valid = raw_os_dump && raw_chrome_dump &&
              (request->memory_map_option() == mojom::MemoryMapOption::NONE ||
               (raw_os_dump && !raw_os_dump->memory_maps.empty()));
    }

    if (!valid)
      continue;

    mojom::ProcessMemoryDumpPtr pmd = mojom::ProcessMemoryDump::New();
    pmd->pid = pid;
    pmd->process_type = pid_to_process_type[pid];
    pmd->os_dump = std::move(os_dump);
    pmd->service_name = response.second.service_name;

    // If we have to return a summary, add all entries for the requested
    // allocator dumps.
    if (request->should_return_summaries() &&
        !request->args.memory_footprint_only) {
      const auto& process_graph =
          global_graph->process_node_graphs().find(pid)->second;
      for (const std::string& name : request->args.allocator_dump_names) {
        auto* node = process_graph->FindNode(name);
        // Silently ignore any missing node in the process graph.
        if (!node)
          continue;
        base::flat_map<std::string, uint64_t> numeric_entries;
        for (const auto& entry : *node->entries()) {
          if (entry.second.type == Node::Entry::Type::kUInt64)
            numeric_entries.emplace(entry.first, entry.second.value_uint64);
        }
        pmd->chrome_allocator_dumps.emplace(
            name, mojom::AllocatorMemDump::New(std::move(numeric_entries)));
      }
    }

    global_dump->process_dumps.push_back(std::move(pmd));
  }
  global_dump->aggregated_metrics =
      ComputeGlobalNativeCodeResidentMemoryKb(pid_to_os_dump);

  const bool global_success = request->failed_memory_dump_count == 0;

  // In the single process-case, we want to ensure that global_success
  // is true if and only if global_dump is not nullptr.
  if (request->args.pid != base::kNullProcessId && !global_success) {
    global_dump = nullptr;
  }
  auto& callback = request->callback;
  std::move(callback).Run(global_success, request->dump_guid,
                          std::move(global_dump));
  UMA_HISTOGRAM_MEDIUM_TIMES("Memory.Experimental.Debug.GlobalDumpDuration",
                             base::TimeTicks::Now() - request->start_time);
  UMA_HISTOGRAM_COUNTS_1000(
      "Memory.Experimental.Debug.FailedProcessDumpsPerGlobalDump",
      request->failed_memory_dump_count);

  char guid_str[20];
  sprintf(guid_str, "0x%" PRIx64, request->dump_guid);
  TRACE_EVENT_NESTABLE_ASYNC_END2(
      base::trace_event::MemoryDumpManager::kTraceCategory, "GlobalMemoryDump",
      TRACE_ID_LOCAL(request->dump_guid), "dump_guid", TRACE_STR_COPY(guid_str),
      "success", global_success);
}

bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace(
    const base::trace_event::MemoryDumpRequestArgs& args,
    base::ProcessId pid,
    const base::trace_event::ProcessMemoryDump& raw_chrome_dump,
    const GlobalNodeGraph& global_graph,
    const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type,
    TracingObserver* tracing_observer,
    bool use_proto_writer,
    const base::TimeTicks& timestamp) {
  bool is_chrome_tracing_enabled =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableChromeTracingComputation);
  if (!is_chrome_tracing_enabled) {
    return tracing_observer->AddChromeDumpToTraceIfEnabled(
        args, pid, &raw_chrome_dump, timestamp);
  }
  if (!tracing_observer->ShouldAddToTrace(args))
    return false;

  if (use_proto_writer) {
    return tracing_observer->AddChromeDumpToTraceIfEnabled(
        args, pid, &raw_chrome_dump, timestamp);
  }

  const GlobalNodeGraph::Process& process =
      *global_graph.process_node_graphs().find(pid)->second;

  std::unique_ptr<TracedValue> traced_value;
  if (pid_to_process_type.find(pid)->second == mojom::ProcessType::BROWSER) {
    traced_value = GetChromeDumpAndGlobalAndEdgesTracedValue(
        process, *global_graph.shared_memory_graph(), global_graph.edges());
  } else {
    traced_value = GetChromeDumpTracedValue(process);
  }
  TracingObserverTracedValue::AddToTrace(args, pid, std::move(traced_value));

  return true;
}

QueuedRequestDispatcher::ClientInfo::ClientInfo(
    mojom::ClientProcess* client,
    base::ProcessId pid,
    mojom::ProcessType process_type,
    absl::optional<std::string> service_name)
    : client(client),
      pid(pid),
      process_type(process_type),
      service_name(std::move(service_name)) {}

QueuedRequestDispatcher::ClientInfo::ClientInfo(ClientInfo&& other) = default;

QueuedRequestDispatcher::ClientInfo::~ClientInfo() = default;

}  // namespace memory_instrumentation
