| Index: services/resource_coordinator/public/cpp/tracing/chrome_agent.cc
 | 
| diff --git a/services/resource_coordinator/public/cpp/tracing/chrome_agent.cc b/services/resource_coordinator/public/cpp/tracing/chrome_agent.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..b075335da516c1ed2dd14b944ebadb8e5810ecc5
 | 
| --- /dev/null
 | 
| +++ b/services/resource_coordinator/public/cpp/tracing/chrome_agent.cc
 | 
| @@ -0,0 +1,96 @@
 | 
| +// 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/public/cpp/tracing/chrome_agent.h"
 | 
| +
 | 
| +#include "base/bind.h"
 | 
| +#include "base/memory/ref_counted.h"
 | 
| +#include "base/memory/ref_counted_memory.h"
 | 
| +#include "base/trace_event/trace_log.h"
 | 
| +#include "services/service_manager/public/cpp/connector.h"
 | 
| +
 | 
| +namespace resource_coordinator {
 | 
| +namespace tracing {
 | 
| +
 | 
| +// static
 | 
| +void ChromeAgent::InitializeIfNeeded(mojom::AgentSetPtr agent_set) {
 | 
| +  static ChromeAgent* instance = nullptr;
 | 
| +  if (!instance)
 | 
| +    instance = new ChromeAgent(std::move(agent_set));
 | 
| +}
 | 
| +
 | 
| +ChromeAgent::ChromeAgent(mojom::AgentSetPtr agent_set)
 | 
| +    : agent_set_(std::move(agent_set)), binding_(this) {
 | 
| +  agent_set_->RegisterAgent(binding_.CreateInterfacePtrAndBind(), "traceEvents",
 | 
| +                            mojom::TraceDataType::ARRAY,
 | 
| +                            false /* supports_explicit_clock_sync */);
 | 
| +}
 | 
| +
 | 
| +ChromeAgent::~ChromeAgent() {}
 | 
| +
 | 
| +void ChromeAgent::StartTracing(const std::string& config,
 | 
| +                               mojom::RecorderPtr recorder,
 | 
| +                               bool report_categories_only,
 | 
| +                               const StartTracingCallback& callback) {
 | 
| +  DCHECK(!recorder_);
 | 
| +  recorder_ = std::move(recorder);
 | 
| +  report_categories_only_ = report_categories_only;
 | 
| +  if (!base::trace_event::TraceLog::GetInstance()->IsEnabled()) {
 | 
| +    base::trace_event::TraceLog::GetInstance()->SetEnabled(
 | 
| +        base::trace_event::TraceConfig(config),
 | 
| +        base::trace_event::TraceLog::RECORDING_MODE);
 | 
| +  }
 | 
| +  callback.Run();
 | 
| +}
 | 
| +
 | 
| +void ChromeAgent::StopAndFlush() {
 | 
| +  if (!recorder_)
 | 
| +    return;
 | 
| +  base::trace_event::TraceLog::GetInstance()->SetDisabled();
 | 
| +  if (!report_categories_only_) {
 | 
| +    base::trace_event::TraceLog::GetInstance()->Flush(
 | 
| +        base::Bind(&ChromeAgent::SendChunk, base::Unretained(this)));
 | 
| +  } else {
 | 
| +    base::trace_event::TraceLog::GetInstance()->Flush(
 | 
| +        base::trace_event::TraceLog::OutputCallback());
 | 
| +    std::vector<std::string> category_vector;
 | 
| +    base::trace_event::TraceLog::GetInstance()->GetKnownCategoryGroups(
 | 
| +        &category_vector);
 | 
| +    std::string categories_str;
 | 
| +    bool first = true;
 | 
| +    for (const auto& category : category_vector) {
 | 
| +      if (!first)
 | 
| +        categories_str += ",";
 | 
| +      first = false;
 | 
| +      categories_str += category;
 | 
| +    }
 | 
| +    recorder_->AddCategories(categories_str);
 | 
| +    recorder_.reset();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void ChromeAgent::RequestClockSyncMarker(
 | 
| +    const std::string& sync_id,
 | 
| +    const RequestClockSyncMarkerCallback& callback) {
 | 
| +  NOTREACHED() << "This agent does not support explicit clock sync";
 | 
| +}
 | 
| +
 | 
| +void ChromeAgent::RequestBufferStatus(
 | 
| +    const RequestBufferStatusCallback& callback) {
 | 
| +  auto status = base::trace_event::TraceLog::GetInstance()->GetStatus();
 | 
| +  callback.Run(status.event_capacity, status.event_count);
 | 
| +}
 | 
| +
 | 
| +void ChromeAgent::SendChunk(
 | 
| +    const scoped_refptr<base::RefCountedString>& events_str,
 | 
| +    bool has_more_events) {
 | 
| +  DCHECK(recorder_);
 | 
| +  if (!events_str->data().empty())
 | 
| +    recorder_->AddChunk(events_str->data());
 | 
| +  if (!has_more_events)
 | 
| +    recorder_.reset();
 | 
| +}
 | 
| +
 | 
| +}  // namespace tracing
 | 
| +}
 | 
| 
 |