// Copyright 2015 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 "base/trace_event/memory_dump_manager.h"

#include <algorithm>
#include <utility>

#include "base/atomic_sequence_num.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/debugging_flags.h"
#include "base/debug/stack_trace.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
#include "base/trace_event/malloc_dump_provider.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/memory_infra_background_whitelist.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"

#if defined(OS_ANDROID)
#include "base/trace_event/java_heap_dump_provider_android.h"
#endif

#if defined(OS_WIN)
#include "base/trace_event/winheap_dump_provider_win.h"
#endif

namespace base {
namespace trace_event {

namespace {

const int kTraceEventNumArgs = 1;
const char* kTraceEventArgNames[] = {"dumps"};
const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};

StaticAtomicSequenceNumber g_next_guid;
MemoryDumpManager* g_instance_for_testing = nullptr;

// Callback wrapper to hook upon the completion of RequestGlobalDump() and
// inject trace markers.
void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback,
                      uint64_t dump_guid,
                      bool success) {
  TRACE_EVENT_NESTABLE_ASYNC_END1(
      MemoryDumpManager::kTraceCategory, "GlobalMemoryDump",
      TRACE_ID_MANGLE(dump_guid), "success", success);

  if (!wrapped_callback.is_null()) {
    wrapped_callback.Run(dump_guid, success);
    wrapped_callback.Reset();
  }
}

// Proxy class which wraps a ConvertableToTraceFormat owned by the
// |session_state| into a proxy object that can be added to the trace event log.
// This is to solve the problem that the MemoryDumpSessionState is refcounted
// but the tracing subsystem wants a std::unique_ptr<ConvertableToTraceFormat>.
template <typename T>
struct SessionStateConvertableProxy : public ConvertableToTraceFormat {
  using GetterFunctPtr = T* (MemoryDumpSessionState::*)() const;

  SessionStateConvertableProxy(
      scoped_refptr<MemoryDumpSessionState> session_state,
      GetterFunctPtr getter_function)
      : session_state(session_state), getter_function(getter_function) {}

  void AppendAsTraceFormat(std::string* out) const override {
    return (session_state.get()->*getter_function)()->AppendAsTraceFormat(out);
  }

  void EstimateTraceMemoryOverhead(
      TraceEventMemoryOverhead* overhead) override {
    return (session_state.get()->*getter_function)()
        ->EstimateTraceMemoryOverhead(overhead);
  }

  scoped_refptr<MemoryDumpSessionState> session_state;
  GetterFunctPtr const getter_function;
};

}  // namespace

// static
const char* const MemoryDumpManager::kTraceCategory =
    TRACE_DISABLED_BY_DEFAULT("memory-infra");

// static
const char* const MemoryDumpManager::kLogPrefix = "Memory-infra dump";

// static
const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3;

// static
const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0;

// static
const char* const MemoryDumpManager::kSystemAllocatorPoolName =
#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
    MallocDumpProvider::kAllocatedObjects;
#elif defined(OS_WIN)
    WinHeapDumpProvider::kAllocatedObjects;
#else
    nullptr;
#endif

// static
MemoryDumpManager* MemoryDumpManager::GetInstance() {
  if (g_instance_for_testing)
    return g_instance_for_testing;

  return Singleton<MemoryDumpManager,
                   LeakySingletonTraits<MemoryDumpManager>>::get();
}

// static
void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
  g_instance_for_testing = instance;
}

MemoryDumpManager::MemoryDumpManager()
    : delegate_(nullptr),
      is_coordinator_(false),
      memory_tracing_enabled_(0),
      tracing_process_id_(kInvalidTracingProcessId),
      dumper_registrations_ignored_for_testing_(false),
      heap_profiling_enabled_(false) {
  g_next_guid.GetNext();  // Make sure that first guid is not zero.

  // At this point the command line may not be initialized but we try to
  // enable the heap profiler to capture allocations as soon as possible.
  EnableHeapProfilingIfNeeded();
}

MemoryDumpManager::~MemoryDumpManager() {
  TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
}

void MemoryDumpManager::EnableHeapProfilingIfNeeded() {
  if (heap_profiling_enabled_)
    return;

  if (!CommandLine::InitializedForCurrentProcess() ||
      !CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableHeapProfiling))
    return;

  std::string profiling_mode = CommandLine::ForCurrentProcess()
      ->GetSwitchValueASCII(switches::kEnableHeapProfiling);
  if (profiling_mode == "") {
    AllocationContextTracker::SetCaptureMode(
        AllocationContextTracker::CaptureMode::PSEUDO_STACK);
  }
  else if (profiling_mode == switches::kEnableHeapProfilingModeNative) {
#if HAVE_TRACE_STACK_FRAME_POINTERS && \
    (BUILDFLAG(ENABLE_PROFILING) || !defined(NDEBUG))
    // We need frame pointers for native tracing to work, and they are
    // enabled in profiling and debug builds.
    AllocationContextTracker::SetCaptureMode(
        AllocationContextTracker::CaptureMode::NATIVE_STACK);
#else
    CHECK(false) << "'" << profiling_mode << "' mode for "
                 << switches::kEnableHeapProfiling << " flag is not supported "
                 << "for this platform / build type.";
#endif
  } else {
    CHECK(false) << "Invalid mode '" << profiling_mode << "' for "
               << switches::kEnableHeapProfiling << " flag.";
  }

  for (auto mdp : dump_providers_)
    mdp->dump_provider->OnHeapProfilingEnabled(true);
  heap_profiling_enabled_ = true;
}

void MemoryDumpManager::Initialize(MemoryDumpManagerDelegate* delegate,
                                   bool is_coordinator) {
  {
    AutoLock lock(lock_);
    DCHECK(delegate);
    DCHECK(!delegate_);
    delegate_ = delegate;
    is_coordinator_ = is_coordinator;
    EnableHeapProfilingIfNeeded();
  }

// Enable the core dump providers.
#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
  RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr);
#endif

#if defined(OS_ANDROID)
  RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap",
                       nullptr);
#endif

#if defined(OS_WIN)
  RegisterDumpProvider(WinHeapDumpProvider::GetInstance(), "WinHeap", nullptr);
#endif

  // If tracing was enabled before initializing MemoryDumpManager, we missed the
  // OnTraceLogEnabled() event. Synthetize it so we can late-join the party.
  bool is_tracing_already_enabled = TraceLog::GetInstance()->IsEnabled();
  TRACE_EVENT0(kTraceCategory, "init");  // Add to trace-viewer category list.
  TraceLog::GetInstance()->AddEnabledStateObserver(this);
  if (is_tracing_already_enabled)
    OnTraceLogEnabled();
}

void MemoryDumpManager::RegisterDumpProvider(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SingleThreadTaskRunner> task_runner,
    MemoryDumpProvider::Options options) {
  options.dumps_on_single_thread_task_runner = true;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProvider(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SingleThreadTaskRunner> task_runner) {
  // Set |dumps_on_single_thread_task_runner| to true because all providers
  // without task runner are run on dump thread.
  MemoryDumpProvider::Options options;
  options.dumps_on_single_thread_task_runner = true;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProviderWithSequencedTaskRunner(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SequencedTaskRunner> task_runner,
    MemoryDumpProvider::Options options) {
  DCHECK(task_runner);
  options.dumps_on_single_thread_task_runner = false;
  RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
}

void MemoryDumpManager::RegisterDumpProviderInternal(
    MemoryDumpProvider* mdp,
    const char* name,
    scoped_refptr<SequencedTaskRunner> task_runner,
    const MemoryDumpProvider::Options& options) {
  if (dumper_registrations_ignored_for_testing_)
    return;

  bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name);
  scoped_refptr<MemoryDumpProviderInfo> mdpinfo =
      new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options,
                                 whitelisted_for_background_mode);

  {
    AutoLock lock(lock_);
    bool already_registered = !dump_providers_.insert(mdpinfo).second;
    // This actually happens in some tests which don't have a clean tear-down
    // path for RenderThreadImpl::Init().
    if (already_registered)
      return;
  }

  if (heap_profiling_enabled_)
    mdp->OnHeapProfilingEnabled(true);
}

void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
  UnregisterDumpProviderInternal(mdp, false /* delete_async */);
}

void MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon(
    std::unique_ptr<MemoryDumpProvider> mdp) {
  UnregisterDumpProviderInternal(mdp.release(), true /* delete_async */);
}

void MemoryDumpManager::UnregisterDumpProviderInternal(
    MemoryDumpProvider* mdp,
    bool take_mdp_ownership_and_delete_async) {
  std::unique_ptr<MemoryDumpProvider> owned_mdp;
  if (take_mdp_ownership_and_delete_async)
    owned_mdp.reset(mdp);

  AutoLock lock(lock_);

  auto mdp_iter = dump_providers_.begin();
  for (; mdp_iter != dump_providers_.end(); ++mdp_iter) {
    if ((*mdp_iter)->dump_provider == mdp)
      break;
  }

  if (mdp_iter == dump_providers_.end())
    return;  // Not registered / already unregistered.

  if (take_mdp_ownership_and_delete_async) {
    // The MDP will be deleted whenever the MDPInfo struct will, that is either:
    // - At the end of this function, if no dump is in progress.
    // - Either in SetupNextMemoryDump() or InvokeOnMemoryDump() when MDPInfo is
    //   removed from |pending_dump_providers|.
    DCHECK(!(*mdp_iter)->owned_dump_provider);
    (*mdp_iter)->owned_dump_provider = std::move(owned_mdp);
  } else if (subtle::NoBarrier_Load(&memory_tracing_enabled_)) {
    // If you hit this DCHECK, your dump provider has a bug.
    // Unregistration of a MemoryDumpProvider is safe only if:
    // - The MDP has specified a sequenced task runner affinity AND the
    //   unregistration happens on the same task runner. So that the MDP cannot
    //   unregister and be in the middle of a OnMemoryDump() at the same time.
    // - The MDP has NOT specified a task runner affinity and its ownership is
    //   transferred via UnregisterAndDeleteDumpProviderSoon().
    // In all the other cases, it is not possible to guarantee that the
    // unregistration will not race with OnMemoryDump() calls.
    DCHECK((*mdp_iter)->task_runner &&
           (*mdp_iter)->task_runner->RunsTasksOnCurrentThread())
        << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to "
        << "unregister itself in a racy way. Please file a crbug.";
  }

  // The MDPInfo instance can still be referenced by the
  // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason
  // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump()
  // to just skip it, without actually invoking the |mdp|, which might be
  // destroyed by the caller soon after this method returns.
  (*mdp_iter)->disabled = true;
  dump_providers_.erase(mdp_iter);
}

void MemoryDumpManager::RequestGlobalDump(
    MemoryDumpType dump_type,
    MemoryDumpLevelOfDetail level_of_detail,
    const MemoryDumpCallback& callback) {
  // Bail out immediately if tracing is not enabled at all or if the dump mode
  // is not allowed.
  if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) ||
      !IsDumpModeAllowed(level_of_detail)) {
    VLOG(1) << kLogPrefix << " failed because " << kTraceCategory
            << " tracing category is not enabled or the requested dump mode is "
               "not allowed by trace config.";
    if (!callback.is_null())
      callback.Run(0u /* guid */, false /* success */);
    return;
  }

  const uint64_t guid =
      TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());

  // Creates an async event to keep track of the global dump evolution.
  // The |wrapped_callback| will generate the ASYNC_END event and then invoke
  // the real |callback| provided by the caller.
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "GlobalMemoryDump",
                                    TRACE_ID_MANGLE(guid));
  MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback);

  // Technically there is no need to grab the |lock_| here as the delegate is
  // long-lived and can only be set by Initialize(), which is locked and
  // necessarily happens before memory_tracing_enabled_ == true.
  // Not taking the |lock_|, though, is lakely make TSan barf and, at this point
  // (memory-infra is enabled) we're not in the fast-path anymore.
  MemoryDumpManagerDelegate* delegate;
  {
    AutoLock lock(lock_);
    delegate = delegate_;
  }

  // The delegate will coordinate the IPC broadcast and at some point invoke
  // CreateProcessDump() to get a dump for the current process.
  MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail};
  delegate->RequestGlobalMemoryDump(args, wrapped_callback);
}

void MemoryDumpManager::RequestGlobalDump(
    MemoryDumpType dump_type,
    MemoryDumpLevelOfDetail level_of_detail) {
  RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback());
}

void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
                                          const MemoryDumpCallback& callback) {
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "ProcessMemoryDump",
                                    TRACE_ID_MANGLE(args.dump_guid));

  // If argument filter is enabled then only background mode dumps should be
  // allowed. In case the trace config passed for background tracing session
  // missed the allowed modes argument, it crashes here instead of creating
  // unexpected dumps.
  if (TraceLog::GetInstance()
          ->GetCurrentTraceConfig()
          .IsArgumentFilterEnabled()) {
    CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail);
  }

  std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
  {
    AutoLock lock(lock_);

    // |dump_thread_| can be nullptr is tracing was disabled before reaching
    // here. SetupNextMemoryDump() is robust enough to tolerate it and will
    // NACK the dump.
    pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
        args, dump_providers_, session_state_, callback,
        dump_thread_ ? dump_thread_->task_runner() : nullptr));

    // Safety check to prevent reaching here without calling RequestGlobalDump,
    // with disallowed modes. If |session_state_| is null then tracing is
    // disabled.
    CHECK(!session_state_ ||
          session_state_->memory_dump_config().allowed_dump_modes.count(
              args.level_of_detail));
  }

  TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump",
                         TRACE_ID_MANGLE(args.dump_guid),
                         TRACE_EVENT_FLAG_FLOW_OUT);

  // Start the process dump. This involves task runner hops as specified by the
  // MemoryDumpProvider(s) in RegisterDumpProvider()).
  SetupNextMemoryDump(std::move(pmd_async_state));
}

// PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A
// PostTask is always required for a generic SequencedTaskRunner to ensure that
// no other task is running on it concurrently. SetupNextMemoryDump() and
// InvokeOnMemoryDump() are called alternatively which linearizes the dump
// provider's OnMemoryDump invocations.
// At most one of either SetupNextMemoryDump() or InvokeOnMemoryDump() can be
// active at any time for a given PMD, regardless of status of the |lock_|.
// |lock_| is used in these functions purely to ensure consistency w.r.t.
// (un)registrations of |dump_providers_|.
void MemoryDumpManager::SetupNextMemoryDump(
    std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
  HEAP_PROFILER_SCOPED_IGNORE;
  // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs
  // in the PostTask below don't end up registering their own dump providers
  // (for discounting trace memory overhead) while holding the |lock_|.
  TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();

  // |dump_thread_| might be destroyed before getting this point.
  // It means that tracing was disabled right before starting this dump.
  // Anyway either tracing is stopped or this was the last hop, create a trace
  // event, add it to the trace and finalize process dump invoking the callback.
  if (!pmd_async_state->dump_thread_task_runner.get()) {
    if (pmd_async_state->pending_dump_providers.empty()) {
      VLOG(1) << kLogPrefix << " failed because dump thread was destroyed"
              << " before finalizing the dump";
    } else {
      VLOG(1) << kLogPrefix << " failed because dump thread was destroyed"
              << " before dumping "
              << pmd_async_state->pending_dump_providers.back().get()->name;
    }
    pmd_async_state->dump_successful = false;
    pmd_async_state->pending_dump_providers.clear();
  }
  if (pmd_async_state->pending_dump_providers.empty())
    return FinalizeDumpAndAddToTrace(std::move(pmd_async_state));

  // Read MemoryDumpProviderInfo thread safety considerations in
  // memory_dump_manager.h when accessing |mdpinfo| fields.
  MemoryDumpProviderInfo* mdpinfo =
      pmd_async_state->pending_dump_providers.back().get();

  // If we are in background tracing, we should invoke only the whitelisted
  // providers. Ignore other providers and continue.
  if (pmd_async_state->req_args.level_of_detail ==
          MemoryDumpLevelOfDetail::BACKGROUND &&
      !mdpinfo->whitelisted_for_background_mode) {
    pmd_async_state->pending_dump_providers.pop_back();
    return SetupNextMemoryDump(std::move(pmd_async_state));
  }

  // If the dump provider did not specify a task runner affinity, dump on
  // |dump_thread_| which is already checked above for presence.
  SequencedTaskRunner* task_runner = mdpinfo->task_runner.get();
  if (!task_runner) {
    DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner);
    task_runner = pmd_async_state->dump_thread_task_runner.get();
    DCHECK(task_runner);
  }

  if (mdpinfo->options.dumps_on_single_thread_task_runner &&
      task_runner->RunsTasksOnCurrentThread()) {
    // If |dumps_on_single_thread_task_runner| is true then no PostTask is
    // required if we are on the right thread.
    return InvokeOnMemoryDump(pmd_async_state.release());
  }

  bool did_post_task = task_runner->PostTask(
      FROM_HERE, Bind(&MemoryDumpManager::InvokeOnMemoryDump, Unretained(this),
                      Unretained(pmd_async_state.get())));

  if (did_post_task) {
    // Ownership is tranferred to InvokeOnMemoryDump().
    ignore_result(pmd_async_state.release());
    return;
  }

  // PostTask usually fails only if the process or thread is shut down. So, the
  // dump provider is disabled here. But, don't disable unbound dump providers.
  // The utility thread is normally shutdown when disabling the trace and
  // getting here in this case is expected.
  if (mdpinfo->task_runner) {
    LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name
               << "\". Failed to post task on the task runner provided.";

    // A locked access is required to R/W |disabled| (for the
    // UnregisterAndDeleteDumpProviderSoon() case).
    AutoLock lock(lock_);
    mdpinfo->disabled = true;
  }

  // PostTask failed. Ignore the dump provider and continue.
  pmd_async_state->pending_dump_providers.pop_back();
  SetupNextMemoryDump(std::move(pmd_async_state));
}

// This function is called on the right task runner for current MDP. It is
// either the task runner specified by MDP or |dump_thread_task_runner| if the
// MDP did not specify task runner. Invokes the dump provider's OnMemoryDump()
// (unless disabled).
void MemoryDumpManager::InvokeOnMemoryDump(
    ProcessMemoryDumpAsyncState* owned_pmd_async_state) {
  HEAP_PROFILER_SCOPED_IGNORE;
  // In theory |owned_pmd_async_state| should be a scoped_ptr. The only reason
  // why it isn't is because of the corner case logic of |did_post_task|
  // above, which needs to take back the ownership of the |pmd_async_state| when
  // the PostTask() fails.
  // Unfortunately, PostTask() destroys the scoped_ptr arguments upon failure
  // to prevent accidental leaks. Using a scoped_ptr would prevent us to to
  // skip the hop and move on. Hence the manual naked -> scoped ptr juggling.
  auto pmd_async_state = WrapUnique(owned_pmd_async_state);
  owned_pmd_async_state = nullptr;

  // Read MemoryDumpProviderInfo thread safety considerations in
  // memory_dump_manager.h when accessing |mdpinfo| fields.
  MemoryDumpProviderInfo* mdpinfo =
      pmd_async_state->pending_dump_providers.back().get();

  DCHECK(!mdpinfo->task_runner ||
         mdpinfo->task_runner->RunsTasksOnCurrentThread());

  bool should_dump;
  {
    // A locked access is required to R/W |disabled| (for the
    // UnregisterAndDeleteDumpProviderSoon() case).
    AutoLock lock(lock_);

    // Unregister the dump provider if it failed too many times consecutively.
    if (!mdpinfo->disabled &&
        mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) {
      mdpinfo->disabled = true;
      LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name
                 << "\". Dump failed multiple times consecutively.";
    }
    should_dump = !mdpinfo->disabled;
  }  // AutoLock lock(lock_);

  if (should_dump) {
    // Invoke the dump provider.
    TRACE_EVENT_WITH_FLOW1(kTraceCategory,
                           "MemoryDumpManager::InvokeOnMemoryDump",
                           TRACE_ID_MANGLE(pmd_async_state->req_args.dump_guid),
                           TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                           "dump_provider.name", mdpinfo->name);

    // Pid of the target process being dumped. Often kNullProcessId (= current
    // process), non-zero when the coordinator process creates dumps on behalf
    // of child processes (see crbug.com/461788).
    ProcessId target_pid = mdpinfo->options.target_pid;
    MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail};
    ProcessMemoryDump* pmd =
        pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(target_pid,
                                                                  args);
    bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd);
    mdpinfo->consecutive_failures =
        dump_successful ? 0 : mdpinfo->consecutive_failures + 1;
  }

  pmd_async_state->pending_dump_providers.pop_back();
  SetupNextMemoryDump(std::move(pmd_async_state));
}

// static
void MemoryDumpManager::FinalizeDumpAndAddToTrace(
    std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
  HEAP_PROFILER_SCOPED_IGNORE;
  DCHECK(pmd_async_state->pending_dump_providers.empty());
  const uint64_t dump_guid = pmd_async_state->req_args.dump_guid;
  if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) {
    scoped_refptr<SingleThreadTaskRunner> callback_task_runner =
        pmd_async_state->callback_task_runner;
    callback_task_runner->PostTask(
        FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace,
                        Passed(&pmd_async_state)));
    return;
  }

  TRACE_EVENT_WITH_FLOW0(kTraceCategory,
                         "MemoryDumpManager::FinalizeDumpAndAddToTrace",
                         TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN);

  for (const auto& kv : pmd_async_state->process_dumps) {
    ProcessId pid = kv.first;  // kNullProcessId for the current process.
    ProcessMemoryDump* process_memory_dump = kv.second.get();
    std::unique_ptr<TracedValue> traced_value(new TracedValue);
    process_memory_dump->AsValueInto(traced_value.get());
    traced_value->SetString("level_of_detail",
                            MemoryDumpLevelOfDetailToString(
                                pmd_async_state->req_args.level_of_detail));
    const char* const event_name =
        MemoryDumpTypeToString(pmd_async_state->req_args.dump_type);

    std::unique_ptr<ConvertableToTraceFormat> event_value(
        std::move(traced_value));
    TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
        TRACE_EVENT_PHASE_MEMORY_DUMP,
        TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
        trace_event_internal::kGlobalScope, dump_guid, pid,
        kTraceEventNumArgs, kTraceEventArgNames,
        kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
        TRACE_EVENT_FLAG_HAS_ID);
  }

  bool tracing_still_enabled;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &tracing_still_enabled);
  if (!tracing_still_enabled) {
    pmd_async_state->dump_successful = false;
    VLOG(1) << kLogPrefix << " failed because tracing was disabled before"
            << " the dump was completed";
  }

  if (!pmd_async_state->callback.is_null()) {
    pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful);
    pmd_async_state->callback.Reset();
  }

  TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump",
                                  TRACE_ID_MANGLE(dump_guid));
}

void MemoryDumpManager::OnTraceLogEnabled() {
  bool enabled;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
  if (!enabled)
    return;

  // Initialize the TraceLog for the current thread. This is to avoid that the
  // TraceLog memory dump provider is registered lazily in the PostTask() below
  // while the |lock_| is taken;
  TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();

  // Spin-up the thread used to invoke unbound dump providers.
  std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra"));
  if (!dump_thread->Start()) {
    LOG(ERROR) << "Failed to start the memory-infra thread for tracing";
    return;
  }

  const TraceConfig trace_config =
      TraceLog::GetInstance()->GetCurrentTraceConfig();
  scoped_refptr<MemoryDumpSessionState> session_state =
      new MemoryDumpSessionState;
  session_state->SetMemoryDumpConfig(trace_config.memory_dump_config());
  if (heap_profiling_enabled_) {
    // If heap profiling is enabled, the stack frame deduplicator and type name
    // deduplicator will be in use. Add a metadata events to write the frames
    // and type IDs.
    session_state->SetStackFrameDeduplicator(
        WrapUnique(new StackFrameDeduplicator));

    session_state->SetTypeNameDeduplicator(
        WrapUnique(new TypeNameDeduplicator));

    TRACE_EVENT_API_ADD_METADATA_EVENT(
        TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames",
        "stackFrames",
        WrapUnique(new SessionStateConvertableProxy<StackFrameDeduplicator>(
            session_state, &MemoryDumpSessionState::stack_frame_deduplicator)));

    TRACE_EVENT_API_ADD_METADATA_EVENT(
        TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames",
        "typeNames",
        WrapUnique(new SessionStateConvertableProxy<TypeNameDeduplicator>(
            session_state, &MemoryDumpSessionState::type_name_deduplicator)));
  }

  {
    AutoLock lock(lock_);

    DCHECK(delegate_);  // At this point we must have a delegate.
    session_state_ = session_state;

    DCHECK(!dump_thread_);
    dump_thread_ = std::move(dump_thread);

    subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);

    // TODO(primiano): This is a temporary hack to disable periodic memory dumps
    // when running memory benchmarks until telemetry uses TraceConfig to
    // enable/disable periodic dumps. See crbug.com/529184 .
    if (!is_coordinator_ ||
        CommandLine::ForCurrentProcess()->HasSwitch(
            "enable-memory-benchmarking")) {
      return;
    }
  }

  // Enable periodic dumps if necessary.
  periodic_dump_timer_.Start(trace_config.memory_dump_config().triggers);
}

void MemoryDumpManager::OnTraceLogDisabled() {
  // There might be a memory dump in progress while this happens. Therefore,
  // ensure that the MDM state which depends on the tracing enabled / disabled
  // state is always accessed by the dumping methods holding the |lock_|.
  subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
  std::unique_ptr<Thread> dump_thread;
  {
    AutoLock lock(lock_);
    dump_thread = std::move(dump_thread_);
    session_state_ = nullptr;
  }

  // Thread stops are blocking and must be performed outside of the |lock_|
  // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it).
  periodic_dump_timer_.Stop();
  if (dump_thread)
    dump_thread->Stop();
}

bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) {
  AutoLock lock(lock_);
  if (!session_state_)
    return false;
  return session_state_->memory_dump_config().allowed_dump_modes.count(
             dump_mode) != 0;
}

uint64_t MemoryDumpManager::GetTracingProcessId() const {
  return delegate_->GetTracingProcessId();
}

MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
    MemoryDumpProvider* dump_provider,
    const char* name,
    scoped_refptr<SequencedTaskRunner> task_runner,
    const MemoryDumpProvider::Options& options,
    bool whitelisted_for_background_mode)
    : dump_provider(dump_provider),
      name(name),
      task_runner(std::move(task_runner)),
      options(options),
      consecutive_failures(0),
      disabled(false),
      whitelisted_for_background_mode(whitelisted_for_background_mode) {}

MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {}

bool MemoryDumpManager::MemoryDumpProviderInfo::Comparator::operator()(
    const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& a,
    const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& b) const {
  if (!a || !b)
    return a.get() < b.get();
  // Ensure that unbound providers (task_runner == nullptr) always run last.
  // Rationale: some unbound dump providers are known to be slow, keep them last
  // to avoid skewing timings of the other dump providers.
  return std::tie(a->task_runner, a->dump_provider) >
         std::tie(b->task_runner, b->dump_provider);
}

MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
    MemoryDumpRequestArgs req_args,
    const MemoryDumpProviderInfo::OrderedSet& dump_providers,
    scoped_refptr<MemoryDumpSessionState> session_state,
    MemoryDumpCallback callback,
    scoped_refptr<SingleThreadTaskRunner> dump_thread_task_runner)
    : req_args(req_args),
      session_state(std::move(session_state)),
      callback(callback),
      dump_successful(true),
      callback_task_runner(ThreadTaskRunnerHandle::Get()),
      dump_thread_task_runner(std::move(dump_thread_task_runner)) {
  pending_dump_providers.reserve(dump_providers.size());
  pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend());
}

MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() {
}

ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState::
    GetOrCreateMemoryDumpContainerForProcess(ProcessId pid,
                                             const MemoryDumpArgs& dump_args) {
  auto iter = process_dumps.find(pid);
  if (iter == process_dumps.end()) {
    std::unique_ptr<ProcessMemoryDump> new_pmd(
        new ProcessMemoryDump(session_state, dump_args));
    iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first;
  }
  return iter->second.get();
}

MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {}

MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() {
  Stop();
}

void MemoryDumpManager::PeriodicGlobalDumpTimer::Start(
    const std::vector<TraceConfig::MemoryDumpConfig::Trigger>& triggers_list) {
  if (triggers_list.empty())
    return;

  // At the moment the periodic support is limited to at most one periodic
  // trigger per dump mode. All intervals should be an integer multiple of the
  // smallest interval specified.
  periodic_dumps_count_ = 0;
  uint32_t min_timer_period_ms = std::numeric_limits<uint32_t>::max();
  uint32_t light_dump_period_ms = 0;
  uint32_t heavy_dump_period_ms = 0;
  DCHECK_LE(triggers_list.size(), 3u);
  auto* mdm = MemoryDumpManager::GetInstance();
  for (const TraceConfig::MemoryDumpConfig::Trigger& config : triggers_list) {
    DCHECK_NE(0u, config.periodic_interval_ms);
    switch (config.level_of_detail) {
      case MemoryDumpLevelOfDetail::BACKGROUND:
        DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::BACKGROUND));
        break;
      case MemoryDumpLevelOfDetail::LIGHT:
        DCHECK_EQ(0u, light_dump_period_ms);
        DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::LIGHT));
        light_dump_period_ms = config.periodic_interval_ms;
        break;
      case MemoryDumpLevelOfDetail::DETAILED:
        DCHECK_EQ(0u, heavy_dump_period_ms);
        DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::DETAILED));
        heavy_dump_period_ms = config.periodic_interval_ms;
        break;
    }
    min_timer_period_ms =
        std::min(min_timer_period_ms, config.periodic_interval_ms);
  }

  DCHECK_EQ(0u, light_dump_period_ms % min_timer_period_ms);
  light_dump_rate_ = light_dump_period_ms / min_timer_period_ms;
  DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms);
  heavy_dump_rate_ = heavy_dump_period_ms / min_timer_period_ms;

  timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(min_timer_period_ms),
               base::Bind(&PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump,
                          base::Unretained(this)));
}

void MemoryDumpManager::PeriodicGlobalDumpTimer::Stop() {
  if (IsRunning()) {
    timer_.Stop();
  }
}

bool MemoryDumpManager::PeriodicGlobalDumpTimer::IsRunning() {
  return timer_.IsRunning();
}

void MemoryDumpManager::PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump() {
  MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND;
  if (light_dump_rate_ > 0 && periodic_dumps_count_ % light_dump_rate_ == 0)
    level_of_detail = MemoryDumpLevelOfDetail::LIGHT;
  if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0)
    level_of_detail = MemoryDumpLevelOfDetail::DETAILED;
  ++periodic_dumps_count_;

  MemoryDumpManager::GetInstance()->RequestGlobalDump(
      MemoryDumpType::PERIODIC_INTERVAL, level_of_detail);
}

}  // namespace trace_event
}  // namespace base
