// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/devtools/protocol/tracing_handler.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/json/json_writer.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/trace_event/traced_value.h"
#include "base/trace_event/tracing_agent.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_stream_file.h"
#include "content/browser/devtools/devtools_traceable_screenshot.h"
#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/browser/devtools/tracing_process_set_monitor.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_service.h"
#include "content/public/browser/web_contents.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom-data-view.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
#include "services/tracing/public/cpp/perfetto/perfetto_session.h"
#include "services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h"
#include "services/tracing/public/cpp/trace_startup_config.h"
#include "services/tracing/public/cpp/tracing_features.h"
#include "services/tracing/public/mojom/constants.mojom-forward.h"
#include "third_party/abseil-cpp/absl/strings/ascii.h"
#include "third_party/inspector_protocol/crdtp/json.h"

#if BUILDFLAG(IS_ANDROID)
#include "content/browser/renderer_host/compositor_impl_android.h"
#endif

namespace content::protocol {

namespace {

const double kMinimumReportingInterval = 250.0;

const char kRecordModeParam[] = "record_mode";
const char kTraceBufferSizeInKb[] = "trace_buffer_size_in_kb";

const char kTrackEventDataSourceName[] = "track_event";

// Frames need to be at least 1x1, otherwise nothing would be captured.
constexpr gfx::Size kMinFrameSize = gfx::Size(1, 1);

// Frames do not need to be greater than 500x500 for tracing.
constexpr gfx::Size kMaxFrameSize = gfx::Size(500, 500);

// Convert from camel case to separator + lowercase.
std::string ConvertFromCamelCase(const std::string& in_str, char separator) {
  std::string out_str;
  out_str.reserve(in_str.size());
  for (char c : in_str) {
    if (absl::ascii_isupper(static_cast<unsigned char>(c))) {
      out_str.push_back(separator);
      out_str.push_back(absl::ascii_tolower(static_cast<unsigned char>(c)));
    } else {
      out_str.push_back(c);
    }
  }
  return out_str;
}

base::Value ConvertDictKeyStyle(const base::Value& value) {
  const base::Value::Dict* dict = value.GetIfDict();
  if (dict) {
    base::Value::Dict out;
    for (auto kv : *dict) {
      out.Set(ConvertFromCamelCase(kv.first, '_'),
              ConvertDictKeyStyle(kv.second));
    }
    return base::Value(std::move(out));
  }

  const base::Value::List* list = value.GetIfList();
  if (list) {
    base::Value::List out;
    for (const auto& v : *list) {
      out.Append(ConvertDictKeyStyle(v));
    }
    return base::Value(std::move(out));
  }

  return value.Clone();
}

class DevToolsTraceEndpointProxy : public TracingController::TraceDataEndpoint {
 public:
  explicit DevToolsTraceEndpointProxy(base::WeakPtr<TracingHandler> handler)
      : tracing_handler_(handler) {}

  void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
    if (TracingHandler* h = tracing_handler_.get())
      h->OnTraceDataCollected(std::move(chunk));
  }

  void ReceivedTraceFinalContents() override {
    if (TracingHandler* h = tracing_handler_.get())
      h->OnTraceComplete();
  }

 private:
  ~DevToolsTraceEndpointProxy() override = default;

  base::WeakPtr<TracingHandler> tracing_handler_;
};

class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint {
 public:
  explicit DevToolsStreamEndpoint(
      base::WeakPtr<TracingHandler> handler,
      const scoped_refptr<DevToolsStreamFile>& stream)
      : stream_(stream), tracing_handler_(handler) {}

  // CompressedStringEndpoint calls these methods on a background thread.
  void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
      GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE, base::BindOnce(&DevToolsStreamEndpoint::ReceiveTraceChunk,
                                    this, std::move(chunk)));
      return;
    }
    stream_->Append(std::move(chunk));
  }

  void ReceivedTraceFinalContents() override {
    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
      GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(&DevToolsStreamEndpoint::ReceivedTraceFinalContents,
                         this));
      return;
    }
    if (TracingHandler* h = tracing_handler_.get())
      h->OnTraceToStreamComplete(stream_->handle());
  }

 private:
  ~DevToolsStreamEndpoint() override = default;

  scoped_refptr<DevToolsStreamFile> stream_;
  base::WeakPtr<TracingHandler> tracing_handler_;
};

std::string GetProcessHostHex(RenderProcessHost* host) {
  return base::StringPrintf("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(host));
}

void SendProcessReadyInBrowserEvent(const base::UnguessableToken& frame_token,
                                    RenderProcessHost* host) {
  auto data = std::make_unique<base::trace_event::TracedValue>();
  data->SetString("frame", frame_token.ToString());
  data->SetString("processPseudoId", GetProcessHostHex(host));
  data->SetInteger("processId", static_cast<int>(host->GetProcess().Pid()));
  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "ProcessReadyInBrowser", TRACE_EVENT_SCOPE_THREAD,
                       "data", std::move(data));
}

void FillFrameData(base::trace_event::TracedValue* data,
                   RenderFrameHostImpl* frame_host,
                   const GURL& url) {
  CHECK(frame_host);
  GURL::Replacements strip_fragment;
  strip_fragment.ClearRef();
  std::string trimmed_url = url.ReplaceComponents(strip_fragment).spec();
  data->SetString("frame", frame_host->devtools_frame_token().ToString());
  data->SetString("url", std::move(trimmed_url));
  data->SetString("name", frame_host->GetFrameName());
  data->SetBoolean("isOutermostMainFrame", frame_host->IsOutermostMainFrame());
  // Use FrameTree's primary status since the `frame_host` itself might not be
  // the primary main RenderFrameHost yet, if this function is called when
  // `frame_host` is still speculative / pending commit.
  data->SetBoolean("isInPrimaryMainFrame",
                   frame_host->IsOutermostMainFrame() &&
                       frame_host->frame_tree()->is_primary());
  if (frame_host->GetParent()) {
    data->SetString(
        "parent", frame_host->GetParent()->GetDevToolsFrameToken().ToString());
  }
  RenderProcessHost* process_host = frame_host->GetProcess();
  const base::Process& process_handle = process_host->GetProcess();
  if (!process_handle.IsValid()) {
    data->SetString("processPseudoId", GetProcessHostHex(process_host));
    frame_host->GetProcess()->PostTaskWhenProcessIsReady(
        base::BindOnce(&SendProcessReadyInBrowserEvent,
                       frame_host->devtools_frame_token(), process_host));
  } else {
    // Cast process id to int to be compatible with tracing.
    data->SetInteger("processId", static_cast<int>(process_handle.Pid()));
  }
}

std::optional<base::trace_event::MemoryDumpLevelOfDetail>
StringToMemoryDumpLevelOfDetail(const std::string& str) {
  if (str == Tracing::MemoryDumpLevelOfDetailEnum::Detailed)
    return {base::trace_event::MemoryDumpLevelOfDetail::kDetailed};
  if (str == Tracing::MemoryDumpLevelOfDetailEnum::Background)
    return {base::trace_event::MemoryDumpLevelOfDetail::kBackground};
  if (str == Tracing::MemoryDumpLevelOfDetailEnum::Light)
    return {base::trace_event::MemoryDumpLevelOfDetail::kLight};
  return {};
}

void AddPidsToProcessFilter(
    const std::unordered_set<base::ProcessId>& included_process_ids,
    perfetto::TraceConfig& trace_config) {
  const std::string kDataSourceName = kTrackEventDataSourceName;
  for (auto& data_source : *(trace_config.mutable_data_sources())) {
    auto* source_config = data_source.mutable_config();
    if (source_config->name() == kDataSourceName) {
      for (auto& enabled_pid : included_process_ids) {
        *data_source.add_producer_name_filter() = base::StrCat(
            {tracing::mojom::kPerfettoProducerNamePrefix,
             base::NumberToString(static_cast<uint32_t>(enabled_pid))});
      }
      break;
    }
  }
}

bool IsChromeDataSource(const std::string& data_source_name) {
  return base::StartsWith(data_source_name, "org.chromium.") ||
         data_source_name == "track_event";
}

std::optional<perfetto::BackendType> GetBackendTypeFromParameters(
    const std::string& tracing_backend,
    perfetto::TraceConfig& perfetto_config) {
  if (tracing_backend == Tracing::TracingBackendEnum::Chrome)
    return perfetto::BackendType::kCustomBackend;
  if (tracing_backend == Tracing::TracingBackendEnum::System)
    return perfetto::BackendType::kSystemBackend;
  if (tracing_backend == Tracing::TracingBackendEnum::Auto) {
    // Use the Chrome backend by default, unless there are non-Chrome data
    // sources specified in the config.
    for (auto& data_source : *(perfetto_config.mutable_data_sources())) {
      auto* source_config = data_source.mutable_config();
      if (!IsChromeDataSource(source_config->name()))
        return perfetto::BackendType::kSystemBackend;
    }
    return perfetto::BackendType::kCustomBackend;
  }
  return std::nullopt;
}

// Perfetto SDK build expects track_event data source to be configured via
// track_event_config. But some devtools users (e.g. Perfetto UI) send
// a chrome_config instead. We build a track_event_config based on the
// chrome_config if no other track_event data sources have been configured.
void ConvertToTrackEventConfigIfNeeded(perfetto::TraceConfig& trace_config) {
  for (const auto& data_source : trace_config.data_sources()) {
    if (!data_source.config().track_event_config_raw().empty()) {
      return;
    }
  }
  for (auto& data_source : *trace_config.mutable_data_sources()) {
    if (data_source.config().name() ==
            tracing::mojom::kTraceEventDataSourceName &&
        data_source.config().has_chrome_config()) {
      data_source.mutable_config()->set_name(kTrackEventDataSourceName);
      base::trace_event::TraceConfig base_config(
          data_source.config().chrome_config().trace_config());
      bool privacy_filtering_enabled =
          data_source.config().chrome_config().privacy_filtering_enabled();
      data_source.mutable_config()->set_track_event_config_raw(
          base_config.ToPerfettoTrackEventConfigRaw(privacy_filtering_enabled));
      return;
    }
  }
}

// We currently don't support concurrent tracing sessions, but are planning to.
// For the time being, we're using this flag as a workaround to prevent devtools
// users from accidentally starting two concurrent sessions.
// TODO(eseckler): Remove once we add support for concurrent sessions to the
// perfetto backend.
static bool g_any_agent_tracing = false;

}  // namespace

class TracingHandler::PerfettoTracingSession {
 public:
  PerfettoTracingSession(bool use_proto, perfetto::BackendType backend_type)
      : use_proto_format_(use_proto), backend_type_(backend_type) {}

  ~PerfettoTracingSession() { g_any_agent_tracing = false; }

  void EnableTracing(const perfetto::TraceConfig& perfetto_config,
                     base::OnceCallback<void(const std::string& /*error_msg*/)>
                         start_callback) {
    DCHECK(!tracing_session_);
    DCHECK(!tracing_active_);

    g_any_agent_tracing = true;
    tracing_active_ = true;
    start_callback_ = std::move(start_callback);

#if DCHECK_IS_ON()
    last_perfetto_config_ = perfetto_config;
    for (auto& data_source : *(last_perfetto_config_.mutable_data_sources())) {
      data_source.clear_producer_name_filter();
    }
#endif

    tracing_session_ = perfetto::Tracing::NewTrace(backend_type_);
    tracing_session_->Setup(perfetto_config);

    auto weak_ptr = weak_factory_.GetWeakPtr();

    tracing_session_->SetOnStartCallback([weak_ptr] {
      GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(&PerfettoTracingSession::OnTracingSessionStarted,
                         weak_ptr));
    });

    tracing_session_->SetOnErrorCallback(
        [weak_ptr](perfetto::TracingError error) {
          GetUIThreadTaskRunner({})->PostTask(
              FROM_HERE,
              base::BindOnce(&PerfettoTracingSession::OnTracingSessionFailed,
                             weak_ptr, error.message));
        });

    tracing_session_->Start();
  }

  void AdoptStartupTracingSession(
      const perfetto::TraceConfig& perfetto_config) {
    // Start a perfetto tracing session, which will claim startup tracing data.
    DCHECK(!TracingController::GetInstance()->IsTracing());
    waiting_for_startup_tracing_enabled_ = true;
    EnableTracing(
        perfetto_config,
        base::BindOnce(&PerfettoTracingSession::OnStartupTracingEnabled,
                       base::Unretained(this)));
  }

  void ChangeTraceConfig(const perfetto::TraceConfig& perfetto_config) {
    if (!tracing_session_)
      return;

#if DCHECK_IS_ON()
    // Ensure that the process filter is the only thing that gets changed
    // in a configuration during a tracing session.
    perfetto::TraceConfig config_without_filters = perfetto_config;
    for (auto& data_source : *(config_without_filters.mutable_data_sources())) {
      data_source.clear_producer_name_filter();
    }
    DCHECK(config_without_filters == last_perfetto_config_);
    last_perfetto_config_ = std::move(config_without_filters);
#endif

    tracing_session_->ChangeTraceConfig(perfetto_config);
  }

  void DisableTracing(
      scoped_refptr<TracingController::TraceDataEndpoint> endpoint) {
    DCHECK(endpoint);
    if (waiting_for_startup_tracing_enabled_) {
      pending_disable_tracing_task_ =
          base::BindOnce(&PerfettoTracingSession::DisableTracing,
                         base::Unretained(this), std::move(endpoint));
      return;
    }

    endpoint_ = endpoint;
    tracing_active_ = false;

    if (!tracing_session_) {
      endpoint_->ReceivedTraceFinalContents();
      return;
    }

    auto weak_ptr = weak_factory_.GetWeakPtr();
    tracing_session_->SetOnStopCallback([weak_ptr] {
      GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(&PerfettoTracingSession::OnTracingSessionStopped,
                         weak_ptr));
    });

    tracing_session_->Stop();
  }

  void GetBufferUsage(base::OnceCallback<void(bool success,
                                              float percent_full,
                                              size_t approximate_event_count)>
                          on_buffer_usage_callback) {
    DCHECK(on_buffer_usage_callback);
    if (!tracing_session_) {
      std::move(on_buffer_usage_callback).Run(false, 0.0f, 0);
      return;
    }

    if (on_buffer_usage_callback_) {
      // We only support one concurrent buffer usage request.
      std::move(on_buffer_usage_callback).Run(false, 0.0f, 0);
      return;
    }

    on_buffer_usage_callback_ = std::move(on_buffer_usage_callback);
    auto weak_ptr = weak_factory_.GetWeakPtr();

    tracing_session_->GetTraceStats(
        [weak_ptr](perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
          tracing::ReadTraceStats(
              args,
              base::BindOnce(&PerfettoTracingSession::OnBufferUsage, weak_ptr),
              GetUIThreadTaskRunner({}));
        });
  }

  bool HasTracingFailed() { return tracing_active_ && !tracing_session_; }

  bool HasDataLossOccurred() { return data_loss_; }

 private:
  void OnStartupTracingEnabled(const std::string& error_msg) {
    DCHECK(error_msg.empty());
    waiting_for_startup_tracing_enabled_ = false;
    if (pending_disable_tracing_task_)
      std::move(pending_disable_tracing_task_).Run();
  }

  void OnTracingSessionStarted() {
    if (start_callback_)
      std::move(start_callback_).Run(/*error_msg=*/std::string());
  }

  void OnTracingSessionFailed(std::string error_msg) {
    tracing_session_.reset();

    if (start_callback_)
      std::move(start_callback_).Run(error_msg);

    if (pending_disable_tracing_task_) {
      // Will call endpoint_->ReceivedTraceFinalContents() and delete |this|.
      std::move(pending_disable_tracing_task_).Run();
    } else if (endpoint_) {
      // Will delete |this|.
      endpoint_->ReceivedTraceFinalContents();
    }
  }

  void OnTracingSessionStopped() {
    DCHECK(tracing_session_);

    auto weak_ptr = weak_factory_.GetWeakPtr();

    if (use_proto_format_) {
      tracing_session_->ReadTrace(
          [weak_ptr](perfetto::TracingSession::ReadTraceCallbackArgs args) {
            tracing::ReadTraceAsProtobuf(
                args,
                base::BindOnce(&PerfettoTracingSession::OnTraceData, weak_ptr),
                base::BindOnce(&PerfettoTracingSession::OnTraceDataComplete,
                               weak_ptr),
                GetUIThreadTaskRunner({}));
          });
    } else {
      // Ref-counted because it is used within the lambda running on the
      // perfetto SDK's thread.
      auto tokenizer = base::MakeRefCounted<
          base::RefCountedData<std::unique_ptr<tracing::TracePacketTokenizer>>>(
          std::make_unique<tracing::TracePacketTokenizer>());
      tracing_session_->ReadTrace(
          [weak_ptr,
           tokenizer](perfetto::TracingSession::ReadTraceCallbackArgs args) {
            tracing::ReadTraceAsJson(
                args, tokenizer,
                base::BindOnce(&PerfettoTracingSession::OnTraceData, weak_ptr),
                base::BindOnce(&PerfettoTracingSession::OnTraceDataComplete,
                               weak_ptr),
                GetUIThreadTaskRunner({}));
          });
    }
  }

  void OnBufferUsage(bool success, float percent_full, bool data_loss) {
    data_loss_ |= data_loss;
    if (on_buffer_usage_callback_) {
      std::move(on_buffer_usage_callback_).Run(success, percent_full, 0);
    }
  }

  void OnTraceData(std::unique_ptr<std::string> data) {
    endpoint_->ReceiveTraceChunk(std::move(data));
  }

  void OnTraceDataComplete() {
    // Request stats to check if data loss occurred.
    GetBufferUsage(base::BindOnce(&PerfettoTracingSession::OnFinalBufferUsage,
                                  weak_factory_.GetWeakPtr()));
  }

  void OnFinalBufferUsage(bool success,
                          float percent_full,
                          size_t approximate_event_count) {
    // Will delete |this|.
    endpoint_->ReceivedTraceFinalContents();
  }

  std::unique_ptr<perfetto::TracingSession> tracing_session_;
  const bool use_proto_format_;
  perfetto::BackendType backend_type_ =
      perfetto::BackendType::kUnspecifiedBackend;
  base::OnceCallback<void(const std::string&)> start_callback_;
  base::OnceCallback<
      void(bool success, float percent_full, size_t approximate_event_count)>
      on_buffer_usage_callback_;
  base::OnceClosure pending_disable_tracing_task_;
  bool waiting_for_startup_tracing_enabled_ = false;
  scoped_refptr<TracingController::TraceDataEndpoint> endpoint_;
  bool tracing_active_ = false;
  bool data_loss_ = false;

#if DCHECK_IS_ON()
  perfetto::TraceConfig last_perfetto_config_;
#endif

  base::WeakPtrFactory<PerfettoTracingSession> weak_factory_{this};
};

TracingHandler::TracingHandler(DevToolsAgentHostImpl* host,
                               DevToolsIOContext* io_context,
                               DevToolsSession* root_session)
    : DevToolsDomainHandler(Tracing::Metainfo::domainName),
      io_context_(io_context),
      host_(host),
      session_for_process_filter_(root_session),
      did_initiate_recording_(false),
      return_as_stream_(false),
      gzip_compression_(false),
      buffer_usage_reporting_interval_(0) {
  video_consumer_ = std::make_unique<DevToolsVideoConsumer>(base::BindRepeating(
      &TracingHandler::OnFrameFromVideoConsumer, base::Unretained(this)));
}

TracingHandler::~TracingHandler() = default;

// static
std::vector<TracingHandler*> TracingHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<TracingHandler>(Tracing::Metainfo::domainName);
}

void TracingHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Tracing::Frontend>(dispatcher->channel());
  Tracing::Dispatcher::wire(dispatcher, this);
}

Response TracingHandler::Disable() {
  if (session_)
    StopTracing(nullptr);
  return Response::Success();
}

namespace {
class TracingNotification : public crdtp::Serializable {
 public:
  explicit TracingNotification(std::string json) : json_(std::move(json)) {}

  void AppendSerialized(std::vector<uint8_t>* out) const override {
    crdtp::Status status =
        crdtp::json::ConvertJSONToCBOR(crdtp::SpanFrom(json_), out);
    DCHECK(status.ok()) << status.ToASCIIString();
  }

 private:
  std::string json_;
};
}  // namespace

void TracingHandler::OnTraceDataCollected(
    std::unique_ptr<std::string> trace_fragment) {
  const std::string valid_trace_fragment =
      UpdateTraceDataBuffer(*trace_fragment);
  if (valid_trace_fragment.empty())
    return;

  // Hand-craft protocol notification message so we can substitute JSON
  // that we already got as string as a bare object, not a quoted string.
  std::string message(
      "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
  const size_t messageSuffixSize = 10;
  message.reserve(message.size() + valid_trace_fragment.size() +
                  messageSuffixSize - trace_data_buffer_state_.offset);
  message.append(valid_trace_fragment, trace_data_buffer_state_.offset);
  message += "] } }";

  frontend_->sendRawNotification(
      std::make_unique<TracingNotification>(std::move(message)));
}

void TracingHandler::OnTraceComplete() {
  if (!trace_data_buffer_state_.data.empty())
    OnTraceDataCollected(std::make_unique<std::string>(""));

  DCHECK(trace_data_buffer_state_.data.empty());
  DCHECK_EQ(0u, trace_data_buffer_state_.pos);
  DCHECK_EQ(0, trace_data_buffer_state_.open_braces);
  DCHECK(!trace_data_buffer_state_.in_string);
  DCHECK(!trace_data_buffer_state_.slashed);

  bool data_loss = session_->HasDataLossOccurred();
  process_set_monitor_.reset();
  session_.reset();
  frontend_->TracingComplete(data_loss);
}

std::string TracingHandler::UpdateTraceDataBuffer(
    const std::string& trace_fragment) {
  size_t end = 0;
  size_t last_open = 0;
  TraceDataBufferState& state = trace_data_buffer_state_;
  state.offset = 0;
  bool update_offset = state.open_braces == 0;
  for (; state.pos < trace_fragment.size(); ++state.pos) {
    char c = trace_fragment[state.pos];
    switch (c) {
      case '{':
        if (!state.in_string && !state.slashed) {
          state.open_braces++;
          if (state.open_braces == 1) {
            last_open = state.data.size() + state.pos;
            if (update_offset) {
              state.offset = last_open;
              update_offset = false;
            }
          }
        }
        break;
      case '}':
        if (!state.in_string && !state.slashed) {
          DCHECK_GT(state.open_braces, 0);
          state.open_braces--;
          if (state.open_braces == 0)
            end = state.data.size() + state.pos + 1;
        }
        break;
      case '"':
        if (!state.slashed)
          state.in_string = !state.in_string;
        break;
      case 'u':
        if (state.slashed)
          state.pos += 4;
        break;
    }

    if (state.in_string && c == '\\') {
      state.slashed = !state.slashed;
    } else {
      state.slashed = false;
    }
  }

  // Next starting position is usually 0 except when we are in the middle of
  // processing a unicode character, i.e. \uxxxx.
  state.pos -= trace_fragment.size();

  std::string complete_str = state.data + trace_fragment;
  state.data = complete_str.substr(std::max(end, last_open));

  complete_str.resize(end);
  return complete_str;
}

void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) {
  bool data_loss = session_->HasDataLossOccurred();
  process_set_monitor_.reset();
  session_.reset();
  std::string stream_format = (proto_format_ ? Tracing::StreamFormatEnum::Proto
                                             : Tracing::StreamFormatEnum::Json);
  std::string stream_compression =
      (gzip_compression_ ? Tracing::StreamCompressionEnum::Gzip
                         : Tracing::StreamCompressionEnum::None);
  frontend_->TracingComplete(data_loss, stream_handle, stream_format,
                             stream_compression);
}

void TracingHandler::Start(
    std::optional<std::string> categories,
    std::optional<std::string> options,
    std::optional<double> buffer_usage_reporting_interval,
    std::optional<std::string> transfer_mode,
    std::optional<std::string> transfer_format,
    std::optional<std::string> transfer_compression,
    std::unique_ptr<Tracing::TraceConfig> config,
    std::optional<Binary> perfetto_config,
    std::optional<std::string> tracing_backend,
    std::unique_ptr<StartCallback> callback) {
  bool return_as_stream = transfer_mode.value_or("") ==
                          Tracing::Start::TransferModeEnum::ReturnAsStream;
  bool gzip_compression =
      transfer_compression.value_or("") == Tracing::StreamCompressionEnum::Gzip;
  bool proto_format =
      transfer_format.value_or("") == Tracing::StreamFormatEnum::Proto;

  perfetto::TraceConfig trace_config;
  if (perfetto_config.has_value()) {
    bool parsed = trace_config.ParseFromArray(perfetto_config.value().data(),
                                              perfetto_config.value().size());
    if (!parsed) {
      callback->sendFailure(Response::InvalidParams(
          "Couldn't parse the supplied perfettoConfig."));
      return;
    }

    if (!trace_config.data_sources_size()) {
      callback->sendFailure(Response::InvalidParams(
          "Supplied perfettoConfig doesn't have any data sources specified"));
      return;
    }

    // Default to proto format for perfettoConfig, except if it specifies
    // convert_to_legacy_json in the data source config.
    proto_format = true;
    for (const auto& data_source : trace_config.data_sources()) {
      if (data_source.config().has_chrome_config() &&
          data_source.config().chrome_config().convert_to_legacy_json()) {
        proto_format = false;
        break;
      }
    }

    ConvertToTrackEventConfigIfNeeded(trace_config);
  } else {
    base::trace_event::TraceConfig browser_config =
        base::trace_event::TraceConfig();
    if (config) {
      base::Value::Dict dict;
      CHECK(crdtp::ConvertProtocolValue(*config, &dict));
      browser_config =
          GetTraceConfigFromDevToolsConfig(base::Value(std::move(dict)));
    } else if (categories.has_value() || options.has_value()) {
      browser_config = base::trace_event::TraceConfig(categories.value_or(""),
                                                      options.value_or(""));
    }
    trace_config = CreatePerfettoConfiguration(browser_config, return_as_stream,
                                               proto_format);
  }

  std::optional<perfetto::BackendType> backend = GetBackendTypeFromParameters(
      tracing_backend.value_or(Tracing::TracingBackendEnum::Auto),
      trace_config);

  if (!backend) {
    callback->sendFailure(Response::InvalidParams(
        "Unsupported value for tracing_backend parameter."));
    return;
  }

  // Check if we should adopt the startup tracing session. Only the first
  // Tracing.start() sent to the browser endpoint can adopt it.
  // TODO(crbug.com/40171330): Add tests for system-controlled startup traces.
  AttemptAdoptStartupSession(return_as_stream, gzip_compression, proto_format,
                             *backend);

  if (IsTracing()) {
    callback->sendFailure(Response::ServerError(
        "Tracing has already been started (possibly in another tab)."));
    return;
  }

  if (did_initiate_recording_) {
    callback->sendFailure(Response::ServerError(
        "Starting trace recording is already in progress"));
    return;
  }

  if (config && (categories.has_value() || options.has_value())) {
    callback->sendFailure(Response::InvalidParams(
        "Either trace config (preferred), or categories+options should be "
        "specified, but not both."));
    return;
  }

  if (proto_format && !return_as_stream) {
    callback->sendFailure(Response::InvalidParams(
        "Proto format is only supported when using stream transfer mode."));
    return;
  }

  return_as_stream_ = return_as_stream;
  gzip_compression_ = gzip_compression;
  proto_format_ = proto_format;
  buffer_usage_reporting_interval_ =
      buffer_usage_reporting_interval.value_or(0);
  did_initiate_recording_ = true;
  trace_config_ = std::move(trace_config);

  if (session_for_process_filter_) {
    process_set_monitor_ = TracingProcessSetMonitor::Start(
        *session_for_process_filter_,
        base::BindRepeating(&TracingHandler::AddProcessToFilter,
                            base::Unretained(this)));
    std::unordered_set<base::ProcessId> pids = process_set_monitor_->GetPids();

    base::ProcessId browser_pid = base::Process::Current().Pid();
    pids.insert(browser_pid);
    if (auto* gpu_process_host =
            GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED,
                                /* force_create */ false)) {
      base::ProcessId gpu_pid = gpu_process_host->process_id();
      if (gpu_pid != base::kNullProcessId) {
        pids.insert(gpu_pid);
      }
    }
    AddPidsToProcessFilter(pids, trace_config_);
  }

  session_ = std::make_unique<PerfettoTracingSession>(proto_format_, *backend);
  session_->EnableTracing(
      trace_config_,
      base::BindOnce(&TracingHandler::OnRecordingEnabled,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

perfetto::TraceConfig TracingHandler::CreatePerfettoConfiguration(
    const base::trace_event::TraceConfig& browser_config,
    bool return_as_stream,
    bool proto_format) {
  return tracing::GetDefaultPerfettoConfig(
      browser_config,
      /*privacy_filtering_enabled=*/false,
      /*convert_to_legacy_json=*/!proto_format,
      /*json_agent_label_filter*/
      (proto_format || return_as_stream)
          ? ""
          : tracing::mojom::kChromeTraceEventLabel);
}

void TracingHandler::AddProcessToFilter(base::ProcessId pid) {
  CHECK(did_initiate_recording_);
  CHECK(session_);
  AddPidsToProcessFilter({pid}, trace_config_);
  session_->ChangeTraceConfig(trace_config_);
}

void TracingHandler::AttemptAdoptStartupSession(
    bool return_as_stream,
    bool gzip_compression,
    bool proto_format,
    perfetto::BackendType tracing_backend) {
  // Only adopt startup session for browser-level sessions.
  if (session_for_process_filter_) {
    return;
  }
  auto& startup_config = tracing::TraceStartupConfig::GetInstance();
  if (!startup_config.AttemptAdoptBySessionOwner(
          tracing::TraceStartupConfig::SessionOwner::kDevToolsTracingHandler)) {
    return;
  }

  return_as_stream_ = return_as_stream;
  gzip_compression_ = gzip_compression;
  proto_format_ = proto_format;

  perfetto::TraceConfig perfetto_config =
      tracing::TraceStartupConfig::GetInstance().GetPerfettoConfig();

  session_ =
      std::make_unique<PerfettoTracingSession>(proto_format_, tracing_backend);
  session_->AdoptStartupTracingSession(perfetto_config);
}

Response TracingHandler::End() {
  if (!session_) {
    did_initiate_recording_ = false;
    return Response::ServerError("Tracing is not started");
  }

  if (session_->HasTracingFailed())
    return Response::ServerError("Tracing failed");

  scoped_refptr<TracingController::TraceDataEndpoint> endpoint;
  if (return_as_stream_) {
    endpoint = new DevToolsStreamEndpoint(
        weak_factory_.GetWeakPtr(),
        DevToolsStreamFile::Create(
            io_context_, gzip_compression_ || proto_format_ /* binary */));
    if (gzip_compression_) {
      endpoint = TracingControllerImpl::CreateCompressedStringEndpoint(
          endpoint, true /* compress_with_background_priority */);
    }
  } else {
    // Reset the trace data buffer state.
    trace_data_buffer_state_ = TracingHandler::TraceDataBufferState();
    endpoint = new DevToolsTraceEndpointProxy(weak_factory_.GetWeakPtr());
  }

  StopTracing(endpoint);

  return Response::Success();
}

void TracingHandler::GetCategories(
    std::unique_ptr<GetCategoriesCallback> callback) {
  // TODO(eseckler): Support this via the perfetto service too.
  TracingController::GetInstance()->GetCategories(
      base::BindOnce(&TracingHandler::OnCategoriesReceived,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void TracingHandler::OnRecordingEnabled(std::unique_ptr<StartCallback> callback,
                                        const std::string& error_msg) {
  if (!error_msg.empty()) {
    callback->sendFailure(Response::ServerError(error_msg));
    return;
  }

  if (!did_initiate_recording_) {
    callback->sendFailure(Response::ServerError(
        "Tracing was stopped before start has been completed."));
    return;
  }

  EmitFrameTree();
  callback->sendSuccess();

  SetupTimer(buffer_usage_reporting_interval_);

  bool screenshot_enabled;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED(
      TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &screenshot_enabled);
  if (screenshot_enabled) {
    // Reset number of screenshots received, each time tracing begins.
    number_of_screenshots_from_video_consumer_ = 0;
    if (WebContents* wc = host_ ? host_->GetWebContents() : nullptr) {
      auto* frame_host =
          static_cast<RenderFrameHostImpl*>(wc->GetPrimaryMainFrame());
      video_consumer_->SetFrameSinkId(
          frame_host->GetRenderWidgetHost()->GetFrameSinkId());
    }
    video_consumer_->SetMinAndMaxFrameSize(kMinFrameSize, kMaxFrameSize);
    video_consumer_->StartCapture();
  }
}

void TracingHandler::OnBufferUsage(bool success,
                                   float percent_full,
                                   size_t approximate_event_count) {
  if (!did_initiate_recording_)
    return;

  if (!success)
    return;

  // TODO(crbug426117): remove set_value once all clients have switched to
  // the new interface of the event.
  frontend_->BufferUsage(percent_full, approximate_event_count, percent_full);
}

void TracingHandler::OnCategoriesReceived(
    std::unique_ptr<GetCategoriesCallback> callback,
    const std::set<std::string>& category_set) {
  auto categories = std::make_unique<protocol::Array<std::string>>(
      category_set.begin(), category_set.end());
  callback->sendSuccess(std::move(categories));
}

void TracingHandler::RequestMemoryDump(
    std::optional<bool> deterministic,
    std::optional<std::string> level_of_detail,
    std::unique_ptr<RequestMemoryDumpCallback> callback) {
  if (!IsTracing()) {
    callback->sendFailure(Response::ServerError("Tracing is not started"));
    return;
  }

  std::optional<base::trace_event::MemoryDumpLevelOfDetail> memory_detail =
      StringToMemoryDumpLevelOfDetail(level_of_detail.value_or(
          Tracing::MemoryDumpLevelOfDetailEnum::Detailed));

  if (!memory_detail) {
    callback->sendFailure(
        Response::ServerError("Invalid levelOfDetail specified."));
    return;
  }

  auto determinism = deterministic.value_or(false)
                         ? base::trace_event::MemoryDumpDeterminism::kForceGc
                         : base::trace_event::MemoryDumpDeterminism::kNone;

  auto on_memory_dump_finished =
      base::BindOnce(&TracingHandler::OnMemoryDumpFinished,
                     weak_factory_.GetWeakPtr(), std::move(callback));

  memory_instrumentation::MemoryInstrumentation::GetInstance()
      ->RequestGlobalDumpAndAppendToTrace(
          base::trace_event::MemoryDumpType::kExplicitlyTriggered,
          *memory_detail, determinism, std::move(on_memory_dump_finished));
}

void TracingHandler::OnMemoryDumpFinished(
    std::unique_ptr<RequestMemoryDumpCallback> callback,
    memory_instrumentation::mojom::RequestOutcome outcome,
    uint64_t dump_id) {
  callback->sendSuccess(
      base::StringPrintf("0x%" PRIx64, dump_id),
      outcome == memory_instrumentation::mojom::RequestOutcome::kSuccess);
}

void TracingHandler::OnFrameFromVideoConsumer(
    scoped_refptr<media::VideoFrame> frame) {
  if (!IsTracing()) {
    return;
  }
  const SkBitmap skbitmap = DevToolsVideoConsumer::GetSkBitmapFromFrame(frame);
  // This reference_time is an ESTIMATE. It is set by the compositor frame sink
  // from the `expected_display_time`, which is based on a previously known
  // frame start PLUS the vsync interval (eg 16.6ms)
  base::TimeTicks expected_display_time = *frame->metadata().reference_time;

  uint64_t frame_sequence = *frame->metadata().frame_sequence;
  uint64_t source_id = *frame->metadata().source_id;

  TRACE_EVENT_INSTANT(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"),
                      "Screenshot", "expected_display_time",
                      expected_display_time, "frame_sequence", frame_sequence,
                      "source_id", source_id, "snapshot",
                      std::make_unique<DevToolsTraceableScreenshot>(skbitmap));

  ++number_of_screenshots_from_video_consumer_;
  DCHECK(video_consumer_);
  if (number_of_screenshots_from_video_consumer_ >=
      DevToolsTraceableScreenshot::kMaximumNumberOfScreenshots) {
    video_consumer_->StopCapture();
  }
}

Response TracingHandler::RecordClockSyncMarker(const std::string& sync_id) {
  if (!IsTracing())
    return Response::ServerError("Tracing is not started");
  TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id);
  return Response::Success();
}

void TracingHandler::SetupTimer(double usage_reporting_interval) {
  if (usage_reporting_interval == 0)
    return;

  if (usage_reporting_interval < kMinimumReportingInterval)
    usage_reporting_interval = kMinimumReportingInterval;

  base::TimeDelta interval =
      base::Milliseconds(std::ceil(usage_reporting_interval));
  buffer_usage_poll_timer_ = std::make_unique<base::RepeatingTimer>();
  buffer_usage_poll_timer_->Start(
      FROM_HERE, interval,
      base::BindRepeating(&TracingHandler::UpdateBufferUsage,
                          weak_factory_.GetWeakPtr()));
}

void TracingHandler::UpdateBufferUsage() {
  session_->GetBufferUsage(base::BindOnce(&TracingHandler::OnBufferUsage,
                                          weak_factory_.GetWeakPtr()));
}

void TracingHandler::StopTracing(
    const scoped_refptr<TracingController::TraceDataEndpoint>& endpoint) {
  DCHECK(session_);
  buffer_usage_poll_timer_.reset();
  process_set_monitor_.reset();
  if (endpoint) {
    // Will delete |session_|.
    session_->DisableTracing(std::move(endpoint));
  } else {
    session_.reset();
  }
  did_initiate_recording_ = false;
  video_consumer_->StopCapture();
}

bool TracingHandler::IsTracing() const {
  return TracingController::GetInstance()->IsTracing() || g_any_agent_tracing;
}

void TracingHandler::EmitFrameTree() {
  auto data = std::make_unique<base::trace_event::TracedValue>();
  if (WebContents* wc = host_ ? host_->GetWebContents() : nullptr) {
    auto* frame_host =
        static_cast<RenderFrameHostImpl*>(wc->GetPrimaryMainFrame());
    CHECK(frame_host);
    data->SetInteger(
        "frameTreeNodeId",
        frame_host->frame_tree_node()->frame_tree_node_id().value());
    data->SetBoolean("persistentIds", true);
    data->BeginArray("frames");
    wc->ForEachRenderFrameHost([&data](RenderFrameHost* rfh) {
      data->BeginDictionary();
      FillFrameData(data.get(), static_cast<RenderFrameHostImpl*>(rfh),
                    rfh->GetLastCommittedURL());
      data->EndDictionary();
    });
    data->EndArray();
  }
  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "TracingStartedInBrowser", TRACE_EVENT_SCOPE_THREAD,
                       "data", std::move(data));
}

void TracingHandler::WillInitiatePrerender(FrameTreeNode* frame_tree_node) {
  if (!did_initiate_recording_) {
    return;
  }
  auto data = std::make_unique<base::trace_event::TracedValue>();
  FillFrameData(data.get(), frame_tree_node->current_frame_host(),
                frame_tree_node->current_url());
  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "FrameCommittedInBrowser", TRACE_EVENT_SCOPE_THREAD,
                       "data", std::move(data));
}

void TracingHandler::ReadyToCommitNavigation(
    NavigationRequest* navigation_request) {
  if (!did_initiate_recording_)
    return;
  auto data = std::make_unique<base::trace_event::TracedValue>();
  RenderFrameHostImpl* frame_host = navigation_request->GetRenderFrameHost();
  FillFrameData(data.get(), frame_host, navigation_request->GetURL());
  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "FrameCommittedInBrowser", TRACE_EVENT_SCOPE_THREAD,
                       "data", std::move(data));
  if (frame_host->IsOutermostMainFrame()) {
    video_consumer_->SetFrameSinkId(navigation_request->GetRenderFrameHost()
                                        ->GetRenderWidgetHost()
                                        ->GetFrameSinkId());
  }
}

void TracingHandler::FrameDeleted(FrameTreeNodeId frame_tree_node_id) {
  if (!did_initiate_recording_)
    return;
  FrameTreeNode* node = FrameTreeNode::GloballyFindByID(frame_tree_node_id);

  if (!node->current_frame_host()) {
    // This might happen on prerendering activation when the prerender tree is
    // shutting how and the RFH is migrated to a different frame tree.
    return;
  }
  auto data = std::make_unique<base::trace_event::TracedValue>();
  data->SetString(
      "frame", node->current_frame_host()->devtools_frame_token().ToString());
  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                       "FrameDeletedInBrowser", TRACE_EVENT_SCOPE_THREAD,
                       "data", std::move(data));
}

// static
bool TracingHandler::IsStartupTracingActive() {
  return ::tracing::TraceStartupConfig::GetInstance().IsEnabled();
}

// static
base::trace_event::TraceConfig TracingHandler::GetTraceConfigFromDevToolsConfig(
    const base::Value& devtools_config) {
  base::Value config = ConvertDictKeyStyle(devtools_config);
  base::Value::Dict& config_dict = config.GetDict();
  if (std::string* mode = config_dict.FindString(kRecordModeParam)) {
    config_dict.Set(kRecordModeParam, ConvertFromCamelCase(*mode, '-'));
  }
  if (std::optional<double> buffer_size =
          config_dict.FindDouble(kTraceBufferSizeInKb)) {
    config_dict.Set(
        kTraceBufferSizeInKb,
        static_cast<int>(base::saturated_cast<size_t>(buffer_size.value())));
  }
  return base::trace_event::TraceConfig(config_dict);
}

}  // namespace content::protocol
