// Copyright (c) 2013 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 "content/browser/tracing/tracing_controller_impl.h"

#include "base/bind.h"
#include "base/cpu.h"
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/json/string_escape.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/tracing/common/process_metrics_memory_dump_provider.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_ui.h"
#include "content/common/child_process_messages.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/tracing_delegate.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "gpu/config/gpu_info.h"
#include "net/base/network_change_notifier.h"
#include "v8/include/v8.h"

#if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
    defined(OS_MACOSX)
#define ENABLE_POWER_TRACING
#endif

#if defined(ENABLE_POWER_TRACING)
#include "content/browser/tracing/power_tracing_agent.h"
#endif

#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon_client.h"
#endif

#if defined(OS_WIN)
#include "content/browser/tracing/etw_tracing_agent_win.h"
#endif

using base::trace_event::TraceLog;
using base::trace_event::TraceConfig;

namespace content {

namespace {

base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
    LAZY_INSTANCE_INITIALIZER;

const char kChromeTracingAgentName[] = "chrome";
const char kETWTracingAgentName[] = "etw";
const char kChromeTraceLabel[] = "traceEvents";

const int kStartTracingTimeoutSeconds = 30;
const int kIssueClockSyncTimeoutSeconds = 30;
const int kStopTracingRetryTimeMilliseconds = 100;

std::string GetNetworkTypeString() {
  switch (net::NetworkChangeNotifier::GetConnectionType()) {
    case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
      return "Ethernet";
    case net::NetworkChangeNotifier::CONNECTION_WIFI:
      return "WiFi";
    case net::NetworkChangeNotifier::CONNECTION_2G:
      return "2G";
    case net::NetworkChangeNotifier::CONNECTION_3G:
      return "3G";
    case net::NetworkChangeNotifier::CONNECTION_4G:
      return "4G";
    case net::NetworkChangeNotifier::CONNECTION_NONE:
      return "None";
    case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
      return "Bluetooth";
    case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
    default:
      break;
  }
  return "Unknown";
}

std::string GetClockString() {
  switch (base::TimeTicks::GetClock()) {
    case base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC:
      return "LINUX_CLOCK_MONOTONIC";
    case base::TimeTicks::Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME:
      return "IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME";
    case base::TimeTicks::Clock::MAC_MACH_ABSOLUTE_TIME:
      return "MAC_MACH_ABSOLUTE_TIME";
    case base::TimeTicks::Clock::WIN_QPC:
      return "WIN_QPC";
    case base::TimeTicks::Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:
      return "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME";
  }

  NOTREACHED();
  return std::string();
}

std::unique_ptr<base::DictionaryValue> GenerateTracingMetadataDict() {
  std::unique_ptr<base::DictionaryValue> metadata_dict(
      new base::DictionaryValue());

  metadata_dict->SetString("network-type", GetNetworkTypeString());
  metadata_dict->SetString("product-version", GetContentClient()->GetProduct());
  metadata_dict->SetString("v8-version", v8::V8::GetVersion());
  metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent());

  // OS
  metadata_dict->SetString("os-name", base::SysInfo::OperatingSystemName());
  metadata_dict->SetString("os-version",
                           base::SysInfo::OperatingSystemVersion());
  metadata_dict->SetString("os-arch",
                           base::SysInfo::OperatingSystemArchitecture());

  // CPU
  base::CPU cpu;
  metadata_dict->SetInteger("cpu-family", cpu.family());
  metadata_dict->SetInteger("cpu-model", cpu.model());
  metadata_dict->SetInteger("cpu-stepping", cpu.stepping());
  metadata_dict->SetInteger("num-cpus", base::SysInfo::NumberOfProcessors());
  metadata_dict->SetInteger("physical-memory",
                            base::SysInfo::AmountOfPhysicalMemoryMB());

  std::string cpu_brand = cpu.cpu_brand();
  // Workaround for crbug.com/249713.
  // TODO(oysteine): Remove workaround when bug is fixed.
  size_t null_pos = cpu_brand.find('\0');
  if (null_pos != std::string::npos)
    cpu_brand.erase(null_pos);
  metadata_dict->SetString("cpu-brand", cpu_brand);

  // GPU
  gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();

#if !defined(OS_ANDROID)
  metadata_dict->SetInteger("gpu-venid", gpu_info.gpu.vendor_id);
  metadata_dict->SetInteger("gpu-devid", gpu_info.gpu.device_id);
#endif

  metadata_dict->SetString("gpu-driver", gpu_info.driver_version);
  metadata_dict->SetString("gpu-psver", gpu_info.pixel_shader_version);
  metadata_dict->SetString("gpu-vsver", gpu_info.vertex_shader_version);

#if defined(OS_MACOSX)
  metadata_dict->SetString("gpu-glver", gpu_info.gl_version);
#elif defined(OS_POSIX)
  metadata_dict->SetString("gpu-gl-vendor", gpu_info.gl_vendor);
  metadata_dict->SetString("gpu-gl-renderer", gpu_info.gl_renderer);
#endif

  std::unique_ptr<TracingDelegate> delegate(
      GetContentClient()->browser()->GetTracingDelegate());
  if (delegate)
    delegate->GenerateMetadataDict(metadata_dict.get());

  metadata_dict->SetString("clock-domain", GetClockString());
  metadata_dict->SetBoolean("highres-ticks",
                            base::TimeTicks::IsHighResolution());

  base::Time::Exploded ctime;
  base::Time::Now().UTCExplode(&ctime);
  std::string time_string = base::StringPrintf("%u-%u-%u %d:%d:%d",
      ctime.year, ctime.month, ctime.day_of_month, ctime.hour,
      ctime.minute, ctime.second);
  metadata_dict->SetString("trace-capture-datetime", time_string);

  return metadata_dict;
}

}  // namespace

TracingController* TracingController::GetInstance() {
  return TracingControllerImpl::GetInstance();
}

TracingControllerImpl::TracingControllerImpl()
    : pending_start_tracing_ack_count_(0),
      pending_stop_tracing_ack_count_(0),
      pending_trace_log_status_ack_count_(0),
      maximum_trace_buffer_usage_(0),
      approximate_event_count_(0),
      pending_memory_dump_ack_count_(0),
      failed_memory_dump_count_(0),
      pending_clock_sync_ack_count_(0),
      is_tracing_(false) {
  base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
      this /* delegate */, true /* is_coordinator */);

  // Deliberately leaked, like this class.
  base::FileTracing::SetProvider(new FileTracingProviderImpl);
}

TracingControllerImpl::~TracingControllerImpl() {
  // This is a Leaky instance.
  NOTREACHED();
}

TracingControllerImpl* TracingControllerImpl::GetInstance() {
  return g_controller.Pointer();
}

bool TracingControllerImpl::GetCategories(
    const GetCategoriesDoneCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Known categories come back from child processes with the EndTracingAck
  // message. So to get known categories, just begin and end tracing immediately
  // afterwards. This will ping all the child processes for categories.
  pending_get_categories_done_callback_ = callback;
  if (!StartTracing(TraceConfig("*", ""), StartTracingDoneCallback())) {
    pending_get_categories_done_callback_.Reset();
    return false;
  }

  bool ok = StopTracing(NULL);
  DCHECK(ok);
  return true;
}

void TracingControllerImpl::SetEnabledOnFileThread(
    const TraceConfig& trace_config,
    int mode,
    const base::Closure& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);

  TraceLog::GetInstance()->SetEnabled(
      trace_config, static_cast<TraceLog::Mode>(mode));
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

void TracingControllerImpl::SetDisabledOnFileThread(
    const base::Closure& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);

  TraceLog::GetInstance()->SetDisabled();
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

bool TracingControllerImpl::StartTracing(
    const TraceConfig& trace_config,
    const StartTracingDoneCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(additional_tracing_agents_.empty());

  if (!can_start_tracing())
    return false;
  is_tracing_ = true;
  start_tracing_done_callback_ = callback;
  start_tracing_trace_config_.reset(
      new base::trace_event::TraceConfig(trace_config));
  metadata_.reset(new base::DictionaryValue());
  pending_start_tracing_ack_count_ = 0;

#if defined(OS_ANDROID)
  if (pending_get_categories_done_callback_.is_null())
    TraceLog::GetInstance()->AddClockSyncMetadataEvent();
#endif

  if (trace_config.IsSystraceEnabled()) {
#if defined(ENABLE_POWER_TRACING)
    PowerTracingAgent::GetInstance()->StartAgentTracing(
        trace_config,
        base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
                   base::Unretained(this)));
    ++pending_start_tracing_ack_count_;
#endif

#if defined(OS_CHROMEOS)
    chromeos::DebugDaemonClient* debug_daemon =
        chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
    if (debug_daemon) {
      debug_daemon->StartAgentTracing(
          trace_config,
          base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
                     base::Unretained(this)));
      ++pending_start_tracing_ack_count_;
    }
#elif defined(OS_WIN)
    EtwTracingAgent::GetInstance()->StartAgentTracing(
        trace_config,
        base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
                   base::Unretained(this)));
    ++pending_start_tracing_ack_count_;
#endif
  }

  // TraceLog may have been enabled in startup tracing before threads are ready.
  if (TraceLog::GetInstance()->IsEnabled())
    return true;

  StartAgentTracing(trace_config,
                    base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
                               base::Unretained(this)));
  ++pending_start_tracing_ack_count_;

  // Set a deadline to ensure all agents ack within a reasonable time frame.
  start_tracing_timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds),
      base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted,
                 base::Unretained(this)));

  return true;
}

void TracingControllerImpl::OnAllTracingAgentsStarted() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  TRACE_EVENT_API_ADD_METADATA_EVENT(
      TraceLog::GetCategoryGroupEnabled("__metadata"),
      "IsTimeTicksHighResolution", "value",
      base::TimeTicks::IsHighResolution());
  TRACE_EVENT_API_ADD_METADATA_EVENT(
      TraceLog::GetCategoryGroupEnabled("__metadata"), "TraceConfig", "value",
      start_tracing_trace_config_->AsConvertableToTraceFormat());

  // Notify all child processes.
  for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
      it != trace_message_filters_.end(); ++it) {
    it->get()->SendBeginTracing(*start_tracing_trace_config_);
  }

  if (!start_tracing_done_callback_.is_null())
    start_tracing_done_callback_.Run();

  start_tracing_done_callback_.Reset();
  start_tracing_trace_config_.reset();
}

void TracingControllerImpl::AddMetadata(const base::DictionaryValue& data) {
  if (metadata_)
    metadata_->MergeDictionary(&data);
}

bool TracingControllerImpl::StopTracing(
    const scoped_refptr<TraceDataSink>& trace_data_sink) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!can_stop_tracing())
    return false;

  // If we're still waiting to start tracing, try again after a delay.
  if (start_tracing_timer_.IsRunning()) {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
                   base::Unretained(this), trace_data_sink),
        base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
    return true;
  }

  if (trace_data_sink) {
    MetadataFilterPredicate metadata_filter;
    if (TraceLog::GetInstance()->GetCurrentTraceConfig()
        .IsArgumentFilterEnabled()) {
      std::unique_ptr<TracingDelegate> delegate(
          GetContentClient()->browser()->GetTracingDelegate());
      if (delegate)
        metadata_filter = delegate->GetMetadataFilterPredicate();
    }
    AddFilteredMetadata(trace_data_sink.get(), GenerateTracingMetadataDict(),
                        metadata_filter);
    AddFilteredMetadata(trace_data_sink.get(), std::move(metadata_),
                        metadata_filter);
  } else {
    metadata_.reset();
  }

  trace_data_sink_ = trace_data_sink;

  // Issue clock sync marker before actually stopping tracing.
  // StopTracingAfterClockSync() will be called after clock sync is done.
  IssueClockSyncMarker();

  return true;
}

void TracingControllerImpl::StopTracingAfterClockSync() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // |pending_clock_sync_ack_count_| could be non-zero if clock sync times out.
  pending_clock_sync_ack_count_ = 0;

  // Disable local trace early to avoid traces during end-tracing process from
  // interfering with the process.
  base::Closure on_stop_tracing_done_callback = base::Bind(
      &TracingControllerImpl::OnStopTracingDone, base::Unretained(this));
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
                 base::Unretained(this),
                 on_stop_tracing_done_callback));
}

void TracingControllerImpl::OnStopTracingDone() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

#if defined(OS_ANDROID)
  if (pending_get_categories_done_callback_.is_null())
    TraceLog::GetInstance()->AddClockSyncMetadataEvent();
#endif

  // Count myself (local trace) in pending_stop_tracing_ack_count_,
  // acked below.
  pending_stop_tracing_ack_count_ = trace_message_filters_.size() + 1;
  pending_stop_tracing_filters_ = trace_message_filters_;

  pending_stop_tracing_ack_count_ += additional_tracing_agents_.size();
  for (auto* it : additional_tracing_agents_) {
    it->StopAgentTracing(
        base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked,
                   base::Unretained(this)));
  }
  additional_tracing_agents_.clear();

  StopAgentTracing(StopAgentTracingCallback());
}

bool TracingControllerImpl::GetTraceBufferUsage(
    const GetTraceBufferUsageCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!can_get_trace_buffer_usage() || callback.is_null())
    return false;

  pending_trace_buffer_usage_callback_ = callback;

  // Count myself in pending_trace_log_status_ack_count_, acked below.
  pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
  pending_trace_log_status_filters_ = trace_message_filters_;
  maximum_trace_buffer_usage_ = 0;
  approximate_event_count_ = 0;

  base::trace_event::TraceLogStatus status =
      TraceLog::GetInstance()->GetStatus();
  // Call OnTraceLogStatusReply unconditionally for the browser process.
  // This will result in immediate execution of the callback if there are no
  // child processes.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
                 base::Unretained(this), nullptr, status));

  // Notify all child processes.
  for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
      it != trace_message_filters_.end(); ++it) {
    it->get()->SendGetTraceLogStatus();
  }
  return true;
}

bool TracingControllerImpl::SetWatchEvent(
    const std::string& category_name,
    const std::string& event_name,
    const WatchEventCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (callback.is_null())
    return false;

  watch_category_name_ = category_name;
  watch_event_name_ = event_name;
  watch_event_callback_ = callback;

  TraceLog::GetInstance()->SetWatchEvent(
      category_name, event_name,
      base::Bind(&TracingControllerImpl::OnWatchEventMatched,
                 base::Unretained(this)));

  for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
      it != trace_message_filters_.end(); ++it) {
    it->get()->SendSetWatchEvent(category_name, event_name);
  }
  return true;
}

bool TracingControllerImpl::CancelWatchEvent() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!can_cancel_watch_event())
    return false;

  for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
      it != trace_message_filters_.end(); ++it) {
    it->get()->SendCancelWatchEvent();
  }

  watch_event_callback_.Reset();
  return true;
}

bool TracingControllerImpl::IsTracing() const {
  return is_tracing_;
}

void TracingControllerImpl::AddTraceMessageFilter(
    TraceMessageFilter* trace_message_filter) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
                   base::Unretained(this),
                   base::RetainedRef(trace_message_filter)));
    return;
  }

#if defined(OS_LINUX)
  // On Linux the browser process dumps process metrics for child process due to
  // sandbox.
  tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
      trace_message_filter->peer_pid());
#endif

  trace_message_filters_.insert(trace_message_filter);
  if (can_cancel_watch_event()) {
    trace_message_filter->SendSetWatchEvent(watch_category_name_,
                                            watch_event_name_);
  }
  if (can_stop_tracing()) {
    trace_message_filter->SendBeginTracing(
        TraceLog::GetInstance()->GetCurrentTraceConfig());
  }

  FOR_EACH_OBSERVER(TraceMessageFilterObserver, trace_message_filter_observers_,
                    OnTraceMessageFilterAdded(trace_message_filter));
}

void TracingControllerImpl::RemoveTraceMessageFilter(
    TraceMessageFilter* trace_message_filter) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
                   base::Unretained(this),
                   base::RetainedRef(trace_message_filter)));
    return;
  }

#if defined(OS_LINUX)
  tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess(
      trace_message_filter->peer_pid());
#endif

  // If a filter is removed while a response from that filter is pending then
  // simulate the response. Otherwise the response count will be wrong and the
  // completion callback will never be executed.
  if (pending_stop_tracing_ack_count_ > 0) {
    TraceMessageFilterSet::const_iterator it =
        pending_stop_tracing_filters_.find(trace_message_filter);
    if (it != pending_stop_tracing_filters_.end()) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&TracingControllerImpl::OnStopTracingAcked,
                     base::Unretained(this),
                     base::RetainedRef(trace_message_filter),
                     std::vector<std::string>()));
    }
  }
  if (pending_trace_log_status_ack_count_ > 0) {
    TraceMessageFilterSet::const_iterator it =
        pending_trace_log_status_filters_.find(trace_message_filter);
    if (it != pending_trace_log_status_filters_.end()) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
                     base::Unretained(this),
                     base::RetainedRef(trace_message_filter),
                     base::trace_event::TraceLogStatus()));
    }
  }
  if (pending_memory_dump_ack_count_ > 0) {
    DCHECK(!queued_memory_dump_requests_.empty());
    TraceMessageFilterSet::const_iterator it =
        pending_memory_dump_filters_.find(trace_message_filter);
    if (it != pending_memory_dump_filters_.end()) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
                     base::Unretained(this),
                     base::RetainedRef(trace_message_filter),
                     queued_memory_dump_requests_.front().args.dump_guid,
                     false /* success */));
    }
  }
  trace_message_filters_.erase(trace_message_filter);
}

void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) {
#if defined(OS_CHROMEOS)
  auto* debug_daemon =
      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
  if (agent_name == debug_daemon->GetTracingAgentName()) {
    additional_tracing_agents_.push_back(debug_daemon);
    debug_daemon->SetStopAgentTracingTaskRunner(
        BrowserThread::GetBlockingPool());
    return;
  }
#elif defined(OS_WIN)
  auto* etw_agent = EtwTracingAgent::GetInstance();
  if (agent_name == etw_agent->GetTracingAgentName()) {
    additional_tracing_agents_.push_back(etw_agent);
    return;
  }
#endif

#if defined(ENABLE_POWER_TRACING)
  auto* power_agent = PowerTracingAgent::GetInstance();
  if (agent_name == power_agent->GetTracingAgentName()) {
    additional_tracing_agents_.push_back(power_agent);
    return;
  }
#endif

  DCHECK(agent_name == kChromeTracingAgentName);
}

void TracingControllerImpl::OnStartAgentTracingAcked(
    const std::string& agent_name,
    bool success) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Don't taken any further action if the ack came after the deadline.
  if (!start_tracing_timer_.IsRunning())
    return;

  if (success)
    AddTracingAgent(agent_name);

  if (--pending_start_tracing_ack_count_ == 0) {
    start_tracing_timer_.Stop();
    OnAllTracingAgentsStarted();
  }
}

void TracingControllerImpl::OnStopTracingAcked(
    TraceMessageFilter* trace_message_filter,
    const std::vector<std::string>& known_category_groups) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(
            &TracingControllerImpl::OnStopTracingAcked, base::Unretained(this),
            base::RetainedRef(trace_message_filter), known_category_groups));
    return;
  }

  // Merge known_category_groups with known_category_groups_
  known_category_groups_.insert(known_category_groups.begin(),
                                known_category_groups.end());

  if (pending_stop_tracing_ack_count_ == 0)
    return;

  if (trace_message_filter &&
      !pending_stop_tracing_filters_.erase(trace_message_filter)) {
    // The response from the specified message filter has already been received.
    return;
  }

  if (--pending_stop_tracing_ack_count_ == 1) {
    // All acks from subprocesses have been received. Now flush the local trace.
    // During or after this call, our OnLocalTraceDataCollected will be
    // called with the last of the local trace data.
    if (trace_data_sink_) {
    TraceLog::GetInstance()->Flush(
        base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
                   base::Unretained(this)),
        true);
    } else {
      TraceLog::GetInstance()->CancelTracing(
          base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
                     base::Unretained(this)));
    }
    return;
  }

  if (pending_stop_tracing_ack_count_ != 0)
    return;

  // All acks (including from the subprocesses and the local trace) have been
  // received.
  is_tracing_ = false;

  // Trigger callback if one is set.
  if (!pending_get_categories_done_callback_.is_null()) {
    pending_get_categories_done_callback_.Run(known_category_groups_);
    pending_get_categories_done_callback_.Reset();
  } else if (trace_data_sink_.get()) {
    trace_data_sink_->Close();
    trace_data_sink_ = NULL;
  }
}

void TracingControllerImpl::OnEndAgentTracingAcked(
    const std::string& agent_name,
    const std::string& events_label,
    const scoped_refptr<base::RefCountedString>& events_str_ptr) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (trace_data_sink_.get() && events_str_ptr &&
      !events_str_ptr->data().empty()) {
    std::string json_string;
    if (agent_name == kETWTracingAgentName) {
      // The Windows kernel events are kept into a JSON format stored as string
      // and must not be escaped.
      json_string = events_str_ptr->data();
    } else {
      json_string = base::GetQuotedJSONString(events_str_ptr->data());
    }
    trace_data_sink_->AddAgentTrace(events_label, json_string);
  }
  std::vector<std::string> category_groups;
  OnStopTracingAcked(NULL, category_groups);
}

void TracingControllerImpl::OnTraceDataCollected(
    const scoped_refptr<base::RefCountedString>& events_str_ptr) {
  // OnTraceDataCollected may be called from any browser thread, either by the
  // local event trace system or from child processes via TraceMessageFilter.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::OnTraceDataCollected,
                   base::Unretained(this), events_str_ptr));
    return;
  }

  if (trace_data_sink_.get())
    trace_data_sink_->AddTraceChunk(events_str_ptr->data());
}

void TracingControllerImpl::OnLocalTraceDataCollected(
    const scoped_refptr<base::RefCountedString>& events_str_ptr,
    bool has_more_events) {
  if (events_str_ptr->data().size())
    OnTraceDataCollected(events_str_ptr);

  if (has_more_events)
    return;

  // Simulate an StopTracingAcked for the local trace.
  std::vector<std::string> category_groups;
  TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
  OnStopTracingAcked(NULL, category_groups);
}

void TracingControllerImpl::OnTraceLogStatusReply(
    TraceMessageFilter* trace_message_filter,
    const base::trace_event::TraceLogStatus& status) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
                   base::Unretained(this),
                   base::RetainedRef(trace_message_filter), status));
    return;
  }

  if (pending_trace_log_status_ack_count_ == 0)
    return;

  if (trace_message_filter &&
      !pending_trace_log_status_filters_.erase(trace_message_filter)) {
    // The response from the specified message filter has already been received.
    return;
  }

  float percent_full = static_cast<float>(
      static_cast<double>(status.event_count) / status.event_capacity);
  maximum_trace_buffer_usage_ =
      std::max(maximum_trace_buffer_usage_, percent_full);
  approximate_event_count_ += status.event_count;

  if (--pending_trace_log_status_ack_count_ == 0) {
    // Trigger callback if one is set.
    pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
                                             approximate_event_count_);
    pending_trace_buffer_usage_callback_.Reset();
  }
}

void TracingControllerImpl::OnWatchEventMatched() {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::OnWatchEventMatched,
                   base::Unretained(this)));
    return;
  }

  if (!watch_event_callback_.is_null())
    watch_event_callback_.Run();
}

void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
  DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
  tracing_uis_.insert(tracing_ui);
}

void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
  std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
  DCHECK(it != tracing_uis_.end());
  tracing_uis_.erase(it);
}

std::string TracingControllerImpl::GetTracingAgentName() {
  return kChromeTracingAgentName;
}

std::string TracingControllerImpl::GetTraceEventLabel() {
  return kChromeTraceLabel;
}

void TracingControllerImpl::StartAgentTracing(
    const base::trace_event::TraceConfig& trace_config,
    const StartAgentTracingCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::Closure on_agent_started =
      base::Bind(callback, kChromeTracingAgentName, true);
  if (!BrowserThread::PostTask(
          BrowserThread::FILE, FROM_HERE,
          base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
                     base::Unretained(this), trace_config,
                     base::trace_event::TraceLog::RECORDING_MODE,
                     on_agent_started))) {
    // BrowserThread::PostTask fails if the threads haven't been created yet,
    // so it should be safe to just use TraceLog::SetEnabled directly.
    base::trace_event::TraceLog::GetInstance()->SetEnabled(
        trace_config, base::trace_event::TraceLog::RECORDING_MODE);
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started);
  }
}

void TracingControllerImpl::StopAgentTracing(
    const StopAgentTracingCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // Handle special case of zero child processes by immediately flushing the
  // trace log. Once the flush has completed the caller will be notified that
  // tracing has ended.
  if (pending_stop_tracing_ack_count_ == 1) {
    // Flush/cancel asynchronously now, because we don't have any children to
    // wait for.
    if (trace_data_sink_) {
      TraceLog::GetInstance()->Flush(
          base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
                     base::Unretained(this)),
          true);
    } else {
      TraceLog::GetInstance()->CancelTracing(
          base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
                     base::Unretained(this)));
    }
  }

  // Notify all child processes.
  for (auto it : trace_message_filters_) {
    if (trace_data_sink_)
      it->SendEndTracing();
    else
      it->SendCancelTracing();
  }
}

bool TracingControllerImpl::SupportsExplicitClockSync() {
  return true;
}

void TracingControllerImpl::RecordClockSyncMarker(
    const std::string& sync_id,
    const RecordClockSyncMarkerCallback& callback) {
  DCHECK(SupportsExplicitClockSync());

  TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id);
}

void TracingControllerImpl::IssueClockSyncMarker() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(pending_clock_sync_ack_count_ == 0);

  for (auto* it : additional_tracing_agents_) {
    if (it->SupportsExplicitClockSync()) {
      it->RecordClockSyncMarker(
          base::GenerateGUID(),
          base::Bind(&TracingControllerImpl::OnClockSyncMarkerRecordedByAgent,
                     base::Unretained(this)));
      pending_clock_sync_ack_count_++;
    }
  }

  // If no clock sync is needed, stop tracing right away. Otherwise, schedule
  // to stop tracing after timeout.
  if (pending_clock_sync_ack_count_ == 0) {
    StopTracingAfterClockSync();
  } else {
    clock_sync_timer_.Start(
        FROM_HERE, base::TimeDelta::FromSeconds(kIssueClockSyncTimeoutSeconds),
        this, &TracingControllerImpl::StopTracingAfterClockSync);
  }
}

void TracingControllerImpl::OnClockSyncMarkerRecordedByAgent(
    const std::string& sync_id,
    const base::TimeTicks& issue_ts,
    const base::TimeTicks& issue_end_ts) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(charliea): Change this function so that it can accept a boolean
  // success indicator instead of having to rely on sentinel issue_ts and
  // issue_end_ts values to signal failure.
  if (!(issue_ts == base::TimeTicks() || issue_end_ts == base::TimeTicks()))
    TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts);

  // Timer is not running means that clock sync already timed out.
  if (!clock_sync_timer_.IsRunning())
    return;

  // Stop tracing only if all agents report back.
  if(--pending_clock_sync_ack_count_ == 0) {
    clock_sync_timer_.Stop();
    StopTracingAfterClockSync();
  }
}

void TracingControllerImpl::AddFilteredMetadata(
    TracingController::TraceDataSink* sink,
    std::unique_ptr<base::DictionaryValue> metadata,
    const MetadataFilterPredicate& filter) {
  if (filter.is_null()) {
    sink->AddMetadata(std::move(metadata));
    return;
  }
  std::unique_ptr<base::DictionaryValue> filtered_metadata(
      new base::DictionaryValue);
  for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd();
       it.Advance()) {
    if (filter.Run(it.key()))
      filtered_metadata->Set(it.key(), it.value().DeepCopy());
    else
      filtered_metadata->SetString(it.key(), "__stripped__");
  }
  sink->AddMetadata(std::move(filtered_metadata));
}

void TracingControllerImpl::RequestGlobalMemoryDump(
    const base::trace_event::MemoryDumpRequestArgs& args,
    const base::trace_event::MemoryDumpCallback& callback) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump,
                   base::Unretained(this), args, callback));
    return;
  }

  bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty();

  // If this is a periodic memory dump request and there already is another
  // request in the queue with the same level of detail, there's no point in
  // enqueuing this request.
  if (another_dump_already_in_progress &&
      args.dump_type == base::trace_event::MemoryDumpType::PERIODIC_INTERVAL) {
    for (const auto& request : queued_memory_dump_requests_) {
      if (request.args.level_of_detail == args.level_of_detail) {
        VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " ("
                << base::trace_event::MemoryDumpTypeToString(args.dump_type)
                << ") skipped because another dump request with the same "
                   "level of detail ("
                << base::trace_event::MemoryDumpLevelOfDetailToString(
                       args.level_of_detail)
                << ") is already in the queue";
        if (!callback.is_null())
          callback.Run(args.dump_guid, false /* success */);
        return;
      }
    }
  }

  queued_memory_dump_requests_.emplace_back(args, callback);

  // If another dump is already in progress, this dump will automatically be
  // scheduled when the other dump finishes.
  if (another_dump_already_in_progress)
    return;

  PerformNextQueuedGlobalMemoryDump();
}

void TracingControllerImpl::PerformNextQueuedGlobalMemoryDump() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!queued_memory_dump_requests_.empty());
  const base::trace_event::MemoryDumpRequestArgs& args =
      queued_memory_dump_requests_.front().args;

  // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
  // OnBrowserProcessMemoryDumpDone().
  pending_memory_dump_ack_count_ = trace_message_filters_.size() + 1;
  pending_memory_dump_filters_.clear();
  failed_memory_dump_count_ = 0;

  MemoryDumpManagerDelegate::CreateProcessDump(
      args, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone,
                       base::Unretained(this)));

  // If there are no child processes we are just done.
  if (pending_memory_dump_ack_count_ == 1)
    return;

  pending_memory_dump_filters_ = trace_message_filters_;

  for (const scoped_refptr<TraceMessageFilter>& tmf : trace_message_filters_)
    tmf->SendProcessMemoryDumpRequest(args);
}

TracingControllerImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest(
    const base::trace_event::MemoryDumpRequestArgs& args,
    const base::trace_event::MemoryDumpCallback& callback)
    : args(args), callback(callback) {}

TracingControllerImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {}

uint64_t TracingControllerImpl::GetTracingProcessId() const {
  return ChildProcessHost::kBrowserTracingProcessId;
}

void TracingControllerImpl::AddTraceMessageFilterObserver(
    TraceMessageFilterObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  trace_message_filter_observers_.AddObserver(observer);

  for (auto& filter : trace_message_filters_)
    observer->OnTraceMessageFilterAdded(filter.get());
}

void TracingControllerImpl::RemoveTraceMessageFilterObserver(
    TraceMessageFilterObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  trace_message_filter_observers_.RemoveObserver(observer);

  for (auto& filter : trace_message_filters_)
    observer->OnTraceMessageFilterRemoved(filter.get());
}

void TracingControllerImpl::OnProcessMemoryDumpResponse(
    TraceMessageFilter* trace_message_filter,
    uint64_t dump_guid,
    bool success) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
                   base::Unretained(this),
                   base::RetainedRef(trace_message_filter), dump_guid,
                   success));
    return;
  }

  TraceMessageFilterSet::iterator it =
      pending_memory_dump_filters_.find(trace_message_filter);

  DCHECK(!queued_memory_dump_requests_.empty());
  if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid ||
      it == pending_memory_dump_filters_.end()) {
    DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid;
    return;
  }

  DCHECK_GT(pending_memory_dump_ack_count_, 0);
  --pending_memory_dump_ack_count_;
  pending_memory_dump_filters_.erase(it);
  if (!success) {
    ++failed_memory_dump_count_;
    VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
            << " failed because of NACK from child "
            << trace_message_filter->peer_pid();
  }
  FinalizeGlobalMemoryDumpIfAllProcessesReplied();
}

void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64_t dump_guid,
                                                           bool success) {
  DCHECK_GT(pending_memory_dump_ack_count_, 0);
  --pending_memory_dump_ack_count_;
  if (!success) {
    ++failed_memory_dump_count_;
    VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
            << " aborted on the current process";
  }
  FinalizeGlobalMemoryDumpIfAllProcessesReplied();
}

void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
  if (pending_memory_dump_ack_count_ > 0)
    return;

  DCHECK(!queued_memory_dump_requests_.empty());
  {
    const auto& callback = queued_memory_dump_requests_.front().callback;
    if (!callback.is_null()) {
      const bool global_success = failed_memory_dump_count_ == 0;
      callback.Run(queued_memory_dump_requests_.front().args.dump_guid,
                   global_success);
    }
  }
  queued_memory_dump_requests_.pop_front();

  // Schedule the next queued dump (if applicable).
  if (!queued_memory_dump_requests_.empty()) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&TracingControllerImpl::PerformNextQueuedGlobalMemoryDump,
                   base::Unretained(this)));
  }
}

}  // namespace content
