| Index: trace_event/memory_dump_manager.cc | 
| diff --git a/trace_event/memory_dump_manager.cc b/trace_event/memory_dump_manager.cc | 
| index 71a9daee3ff60b5e4a10c0524a1c9af78122301b..1c10d1c097b5e16e9c9c3feabc932b8538da5613 100644 | 
| --- a/trace_event/memory_dump_manager.cc | 
| +++ b/trace_event/memory_dump_manager.cc | 
| @@ -48,21 +48,20 @@ uint32 g_heavy_dumps_rate = 0; | 
| MemoryDumpManager* g_instance_for_testing = nullptr; | 
|  | 
| void RequestPeriodicGlobalDump() { | 
| -  MemoryDumpArgs::LevelOfDetail dump_level_of_detail; | 
| +  MemoryDumpLevelOfDetail level_of_detail; | 
| if (g_heavy_dumps_rate == 0) { | 
| -    dump_level_of_detail = MemoryDumpArgs::LevelOfDetail::LOW; | 
| +    level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | 
| } else { | 
| -    dump_level_of_detail = g_periodic_dumps_count == 0 | 
| -                               ? MemoryDumpArgs::LevelOfDetail::HIGH | 
| -                               : MemoryDumpArgs::LevelOfDetail::LOW; | 
| +    level_of_detail = g_periodic_dumps_count == 0 | 
| +                          ? MemoryDumpLevelOfDetail::DETAILED | 
| +                          : MemoryDumpLevelOfDetail::LIGHT; | 
|  | 
| if (++g_periodic_dumps_count == g_heavy_dumps_rate) | 
| g_periodic_dumps_count = 0; | 
| } | 
|  | 
| -  MemoryDumpArgs dump_args = {dump_level_of_detail}; | 
| MemoryDumpManager::GetInstance()->RequestGlobalDump( | 
| -      MemoryDumpType::PERIODIC_INTERVAL, dump_args); | 
| +      MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 
| } | 
|  | 
| }  // namespace | 
| @@ -78,6 +77,16 @@ const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 
| const uint64 MemoryDumpManager::kInvalidTracingProcessId = 0; | 
|  | 
| // static | 
| +const char* const MemoryDumpManager::kSystemAllocatorPoolName = | 
| +#if defined(OS_LINUX) || defined(OS_ANDROID) | 
| +    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; | 
| @@ -95,50 +104,54 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 
|  | 
| MemoryDumpManager::MemoryDumpManager() | 
| : delegate_(nullptr), | 
| +      is_coordinator_(false), | 
| memory_tracing_enabled_(0), | 
| tracing_process_id_(kInvalidTracingProcessId), | 
| -      system_allocator_pool_name_(nullptr), | 
| -      skip_core_dumpers_auto_registration_for_testing_(false), | 
| -      disable_periodic_dumps_for_testing_(false) { | 
| +      skip_core_dumpers_auto_registration_for_testing_(false) { | 
| g_next_guid.GetNext();  // Make sure that first guid is not zero. | 
| } | 
|  | 
| MemoryDumpManager::~MemoryDumpManager() { | 
| -  base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); | 
| +  TraceLog::GetInstance()->RemoveEnabledStateObserver(this); | 
| } | 
|  | 
| -void MemoryDumpManager::Initialize() { | 
| -  TRACE_EVENT0(kTraceCategory, "init");  // Add to trace-viewer category list. | 
| -  trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); | 
| - | 
| -  if (skip_core_dumpers_auto_registration_for_testing_) | 
| -    return; | 
| +void MemoryDumpManager::Initialize(MemoryDumpManagerDelegate* delegate, | 
| +                                   bool is_coordinator) { | 
| +  { | 
| +    AutoLock lock(lock_); | 
| +    DCHECK(delegate); | 
| +    DCHECK(!delegate_); | 
| +    delegate_ = delegate; | 
| +    is_coordinator_ = is_coordinator; | 
| +  } | 
|  | 
| // Enable the core dump providers. | 
| +  if (!skip_core_dumpers_auto_registration_for_testing_) { | 
| #if !defined(OS_NACL) | 
| -  RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); | 
| +    RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); | 
| #endif | 
|  | 
| #if (defined(OS_LINUX) && !defined(FNL_MUSL)) || defined(OS_ANDROID) | 
| -  RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); | 
| -  RegisterDumpProvider(MallocDumpProvider::GetInstance()); | 
| -  system_allocator_pool_name_ = MallocDumpProvider::kAllocatedObjects; | 
| +    RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); | 
| +    RegisterDumpProvider(MallocDumpProvider::GetInstance()); | 
| #endif | 
|  | 
| #if defined(OS_ANDROID) | 
| -  RegisterDumpProvider(JavaHeapDumpProvider::GetInstance()); | 
| +    RegisterDumpProvider(JavaHeapDumpProvider::GetInstance()); | 
| #endif | 
|  | 
| #if defined(OS_WIN) | 
| -  RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); | 
| -  system_allocator_pool_name_ = WinHeapDumpProvider::kAllocatedObjects; | 
| +    RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); | 
| #endif | 
| -} | 
| +  }  // !skip_core_dumpers_auto_registration_for_testing_ | 
|  | 
| -void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) { | 
| -  AutoLock lock(lock_); | 
| -  DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_); | 
| -  delegate_ = delegate; | 
| +  // 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( | 
| @@ -189,9 +202,10 @@ void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { | 
| mdp_iter->unregistered = true; | 
| } | 
|  | 
| -void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, | 
| -                                          const MemoryDumpArgs& dump_args, | 
| -                                          const MemoryDumpCallback& callback) { | 
| +void MemoryDumpManager::RequestGlobalDump( | 
| +    MemoryDumpType dump_type, | 
| +    MemoryDumpLevelOfDetail level_of_detail, | 
| +    const MemoryDumpCallback& callback) { | 
| // Bail out immediately if tracing is not enabled at all. | 
| if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { | 
| if (!callback.is_null()) | 
| @@ -202,27 +216,27 @@ void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, | 
| const uint64 guid = | 
| TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 
|  | 
| -  // The delegate_ is supposed to be thread safe, immutable and long lived. | 
| -  // No need to keep the lock after we ensure that a delegate has been set. | 
| +  // 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_; | 
| } | 
|  | 
| -  if (delegate) { | 
| -    // The delegate is in charge to coordinate the request among all the | 
| -    // processes and call the CreateLocalDumpPoint on the local process. | 
| -    MemoryDumpRequestArgs args = {guid, dump_type, dump_args}; | 
| -    delegate->RequestGlobalMemoryDump(args, callback); | 
| -  } else if (!callback.is_null()) { | 
| -    callback.Run(guid, false /* success */); | 
| -  } | 
| +  // 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, callback); | 
| } | 
|  | 
| -void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, | 
| -                                          const MemoryDumpArgs& dump_args) { | 
| -  RequestGlobalDump(dump_type, dump_args, MemoryDumpCallback()); | 
| +void MemoryDumpManager::RequestGlobalDump( | 
| +    MemoryDumpType dump_type, | 
| +    MemoryDumpLevelOfDetail level_of_detail) { | 
| +  RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); | 
| } | 
|  | 
| void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 
| @@ -305,8 +319,9 @@ void MemoryDumpManager::ContinueAsyncProcessDump( | 
| bool dump_successful = false; | 
|  | 
| if (!skip_dump) { | 
| -    dump_successful = mdp->OnMemoryDump(pmd_async_state->req_args.dump_args, | 
| -                                        &pmd_async_state->process_memory_dump); | 
| +    MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail}; | 
| +    dump_successful = | 
| +        mdp->OnMemoryDump(args, &pmd_async_state->process_memory_dump); | 
| } | 
|  | 
| { | 
| @@ -386,11 +401,10 @@ void MemoryDumpManager::AbortDumpLocked( | 
| } | 
|  | 
| void MemoryDumpManager::OnTraceLogEnabled() { | 
| -  // TODO(primiano): at this point we query  TraceLog::GetCurrentCategoryFilter | 
| -  // to figure out (and cache) which dumpers should be enabled or not. | 
| -  // For the moment piggy back everything on the generic "memory" category. | 
| 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 | 
| @@ -399,13 +413,7 @@ void MemoryDumpManager::OnTraceLogEnabled() { | 
|  | 
| AutoLock lock(lock_); | 
|  | 
| -  // There is no point starting the tracing without a delegate. | 
| -  if (!enabled || !delegate_) { | 
| -    // Disable all the providers. | 
| -    for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) | 
| -      it->disabled = true; | 
| -    return; | 
| -  } | 
| +  DCHECK(delegate_);  // At this point we must have a delegate. | 
|  | 
| session_state_ = new MemoryDumpSessionState(); | 
| for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { | 
| @@ -417,12 +425,10 @@ void MemoryDumpManager::OnTraceLogEnabled() { | 
|  | 
| // 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. | 
| -  // The same mechanism should be used to disable periodic dumps in tests. | 
| -  if (!delegate_->IsCoordinatorProcess() || | 
| +  // enable/disable periodic dumps. See crbug.com/529184 . | 
| +  if (!is_coordinator_ || | 
| CommandLine::ForCurrentProcess()->HasSwitch( | 
| -          "enable-memory-benchmarking") || | 
| -      disable_periodic_dumps_for_testing_) { | 
| +          "enable-memory-benchmarking")) { | 
| return; | 
| } | 
|  | 
| @@ -443,7 +449,7 @@ void MemoryDumpManager::OnTraceLogEnabled() { | 
| DCHECK_LE(config_list.size(), 2u); | 
| for (const TraceConfig::MemoryDumpTriggerConfig& config : config_list) { | 
| DCHECK(config.periodic_interval_ms); | 
| -    if (config.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH) | 
| +    if (config.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) | 
| heavy_dump_period_ms = config.periodic_interval_ms; | 
| min_timer_period_ms = | 
| std::min(min_timer_period_ms, config.periodic_interval_ms); | 
|  |