// This file is generated by TypeBuilder_cpp.template.

// Copyright 2016 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.h"

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

#include "third_party/inspector_protocol/crdtp/cbor.h"
#include "third_party/inspector_protocol/crdtp/find_by_first.h"
#include "third_party/inspector_protocol/crdtp/span.h"

namespace content {
namespace protocol {
namespace Tracing {

using crdtp::DeserializerState;
using crdtp::FallthroughCallback;
using crdtp::ProtocolTypeTraits;

// ------------- Enum values from types.

const char Metainfo::domainName[] = "Tracing";
const char Metainfo::commandPrefix[] = "Tracing.";
const char Metainfo::version[] = "1.3";



const char* TraceConfig::RecordModeEnum::RecordUntilFull = "recordUntilFull";
const char* TraceConfig::RecordModeEnum::RecordContinuously = "recordContinuously";
const char* TraceConfig::RecordModeEnum::RecordAsMuchAsPossible = "recordAsMuchAsPossible";
const char* TraceConfig::RecordModeEnum::EchoToConsole = "echoToConsole";
CRDTP_BEGIN_DESERIALIZER(TraceConfig)
    CRDTP_DESERIALIZE_FIELD_OPT("enableArgumentFilter", m_enableArgumentFilter),
    CRDTP_DESERIALIZE_FIELD_OPT("enableSampling", m_enableSampling),
    CRDTP_DESERIALIZE_FIELD_OPT("enableSystrace", m_enableSystrace),
    CRDTP_DESERIALIZE_FIELD_OPT("excludedCategories", m_excludedCategories),
    CRDTP_DESERIALIZE_FIELD_OPT("includedCategories", m_includedCategories),
    CRDTP_DESERIALIZE_FIELD_OPT("memoryDumpConfig", m_memoryDumpConfig),
    CRDTP_DESERIALIZE_FIELD_OPT("recordMode", m_recordMode),
    CRDTP_DESERIALIZE_FIELD_OPT("syntheticDelays", m_syntheticDelays),
    CRDTP_DESERIALIZE_FIELD_OPT("traceBufferSizeInKb", m_traceBufferSizeInKb),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(TraceConfig)
    CRDTP_SERIALIZE_FIELD("recordMode", m_recordMode);
    CRDTP_SERIALIZE_FIELD("traceBufferSizeInKb", m_traceBufferSizeInKb);
    CRDTP_SERIALIZE_FIELD("enableSampling", m_enableSampling);
    CRDTP_SERIALIZE_FIELD("enableSystrace", m_enableSystrace);
    CRDTP_SERIALIZE_FIELD("enableArgumentFilter", m_enableArgumentFilter);
    CRDTP_SERIALIZE_FIELD("includedCategories", m_includedCategories);
    CRDTP_SERIALIZE_FIELD("excludedCategories", m_excludedCategories);
    CRDTP_SERIALIZE_FIELD("syntheticDelays", m_syntheticDelays);
    CRDTP_SERIALIZE_FIELD("memoryDumpConfig", m_memoryDumpConfig);
CRDTP_END_SERIALIZER();






// ------------- Enum values from params.


// ------------- Frontend notifications.

void Frontend::BufferUsage(std::optional<double> percentFull, std::optional<double> eventCount, std::optional<double> value)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("percentFull"), percentFull);
    serializer.AddField(crdtp::MakeSpan("eventCount"), eventCount);
    serializer.AddField(crdtp::MakeSpan("value"), value);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Tracing.bufferUsage", serializer.Finish()));
}

void Frontend::DataCollected(std::unique_ptr<protocol::Array<protocol::DictionaryValue>> value)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("value"), value);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Tracing.dataCollected", serializer.Finish()));
}

void Frontend::TracingComplete(bool dataLossOccurred, std::optional<String> stream, std::optional<String> traceFormat, std::optional<String> streamCompression)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("dataLossOccurred"), dataLossOccurred);
    serializer.AddField(crdtp::MakeSpan("stream"), stream);
    serializer.AddField(crdtp::MakeSpan("traceFormat"), traceFormat);
    serializer.AddField(crdtp::MakeSpan("streamCompression"), streamCompression);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Tracing.tracingComplete", serializer.Finish()));
}

void Frontend::flush()
{
    frontend_channel_->FlushProtocolNotifications();
}

void Frontend::sendRawNotification(std::unique_ptr<Serializable> notification)
{
    frontend_channel_->SendProtocolNotification(std::move(notification));
}

// --------------------- Dispatcher.

class DomainDispatcherImpl : public protocol::DomainDispatcher {
public:
    DomainDispatcherImpl(FrontendChannel* frontendChannel, Backend* backend)
        : DomainDispatcher(frontendChannel)
        , m_backend(backend) {}
    ~DomainDispatcherImpl() override { }

    using CallHandler = void (DomainDispatcherImpl::*)(crdtp::Dispatchable& dispatchable);

    bool Dispatch(crdtp::span<uint8_t> command_name, crdtp::Dispatchable& dispatchable) override;

    void end(crdtp::Dispatchable& dispatchable);
    void getCategories(crdtp::Dispatchable& dispatchable);
    void getTrackEventDescriptor(crdtp::Dispatchable& dispatchable);
    void recordClockSyncMarker(crdtp::Dispatchable& dispatchable);
    void requestMemoryDump(crdtp::Dispatchable& dispatchable);
    void start(crdtp::Dispatchable& dispatchable);
 protected:
    Backend* m_backend;
};

namespace {
// This helper method with a static map of command methods (instance methods
// of DomainDispatcherImpl declared just above) by their name is used immediately below,
// in the DomainDispatcherImpl::Dispatch method.
DomainDispatcherImpl::CallHandler CommandByName(crdtp::span<uint8_t> command_name) {
  static auto* commands = [](){
    auto* commands = new std::vector<std::pair<crdtp::span<uint8_t>,
                              DomainDispatcherImpl::CallHandler>>{
    {
          crdtp::SpanFrom("end"),
          &DomainDispatcherImpl::end
    },
    {
          crdtp::SpanFrom("getCategories"),
          &DomainDispatcherImpl::getCategories
    },
    {
          crdtp::SpanFrom("getTrackEventDescriptor"),
          &DomainDispatcherImpl::getTrackEventDescriptor
    },
    {
          crdtp::SpanFrom("recordClockSyncMarker"),
          &DomainDispatcherImpl::recordClockSyncMarker
    },
    {
          crdtp::SpanFrom("requestMemoryDump"),
          &DomainDispatcherImpl::requestMemoryDump
    },
    {
          crdtp::SpanFrom("start"),
          &DomainDispatcherImpl::start
    },
    };
    return commands;
  }();
  return crdtp::FindByFirst<DomainDispatcherImpl::CallHandler>(*commands, command_name, nullptr);
}
}  // namespace

bool DomainDispatcherImpl::Dispatch(crdtp::span<uint8_t> command_name, crdtp::Dispatchable& dispatchable) {
  CallHandler handler = CommandByName(command_name);
  if (!handler) return false;

  (this->*handler)(dispatchable);
  return true;
}


namespace {


}  // namespace

void DomainDispatcherImpl::end(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->End();
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

class GetCategoriesCallbackImpl : public Backend::GetCategoriesCallback, public DomainDispatcher::Callback {
public:
    GetCategoriesCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Tracing.getCategories")) { }

    void sendSuccess(std::unique_ptr<protocol::Array<String>> categories) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("categories"), categories);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {


}  // namespace

void DomainDispatcherImpl::getCategories(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetCategories(std::make_unique<GetCategoriesCallbackImpl>(weakPtr(), dispatchable));
}

class GetTrackEventDescriptorCallbackImpl : public Backend::GetTrackEventDescriptorCallback, public DomainDispatcher::Callback {
public:
    GetTrackEventDescriptorCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Tracing.getTrackEventDescriptor")) { }

    void sendSuccess(const Binary& descriptor) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("descriptor"), descriptor);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {


}  // namespace

void DomainDispatcherImpl::getTrackEventDescriptor(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetTrackEventDescriptor(std::make_unique<GetTrackEventDescriptorCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct recordClockSyncMarkerParams : public crdtp::DeserializableProtocolObject<recordClockSyncMarkerParams> {
    String syncId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(recordClockSyncMarkerParams)
    CRDTP_DESERIALIZE_FIELD("syncId", syncId),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::recordClockSyncMarker(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    recordClockSyncMarkerParams params;
    if (!recordClockSyncMarkerParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->RecordClockSyncMarker(params.syncId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

class RequestMemoryDumpCallbackImpl : public Backend::RequestMemoryDumpCallback, public DomainDispatcher::Callback {
public:
    RequestMemoryDumpCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Tracing.requestMemoryDump")) { }

    void sendSuccess(const String& dumpGuid, bool success) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("dumpGuid"), dumpGuid);
        serializer.AddField(crdtp::MakeSpan("success"), success);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {

struct requestMemoryDumpParams : public crdtp::DeserializableProtocolObject<requestMemoryDumpParams> {
    std::optional<bool> deterministic;
    std::optional<String> levelOfDetail;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(requestMemoryDumpParams)
    CRDTP_DESERIALIZE_FIELD_OPT("deterministic", deterministic),
    CRDTP_DESERIALIZE_FIELD_OPT("levelOfDetail", levelOfDetail),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::requestMemoryDump(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    requestMemoryDumpParams params;
    if (!requestMemoryDumpParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }

    m_backend->RequestMemoryDump(std::move(params.deterministic), std::move(params.levelOfDetail), std::make_unique<RequestMemoryDumpCallbackImpl>(weakPtr(), dispatchable));
}

class StartCallbackImpl : public Backend::StartCallback, public DomainDispatcher::Callback {
public:
    StartCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Tracing.start")) { }

    void sendSuccess() override
    {
        crdtp::ObjectSerializer serializer;
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {

struct startParams : public crdtp::DeserializableProtocolObject<startParams> {
    std::optional<String> categories;
    std::optional<String> options;
    std::optional<double> bufferUsageReportingInterval;
    std::optional<String> transferMode;
    std::optional<String> streamFormat;
    std::optional<String> streamCompression;
    std::unique_ptr<protocol::Tracing::TraceConfig> traceConfig;
    std::optional<Binary> perfettoConfig;
    std::optional<String> tracingBackend;
    std::optional<int> screenshotMaxSize;
    std::optional<int> screenshotMaxCount;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(startParams)
    CRDTP_DESERIALIZE_FIELD_OPT("bufferUsageReportingInterval", bufferUsageReportingInterval),
    CRDTP_DESERIALIZE_FIELD_OPT("categories", categories),
    CRDTP_DESERIALIZE_FIELD_OPT("options", options),
    CRDTP_DESERIALIZE_FIELD_OPT("perfettoConfig", perfettoConfig),
    CRDTP_DESERIALIZE_FIELD_OPT("screenshotMaxCount", screenshotMaxCount),
    CRDTP_DESERIALIZE_FIELD_OPT("screenshotMaxSize", screenshotMaxSize),
    CRDTP_DESERIALIZE_FIELD_OPT("streamCompression", streamCompression),
    CRDTP_DESERIALIZE_FIELD_OPT("streamFormat", streamFormat),
    CRDTP_DESERIALIZE_FIELD_OPT("traceConfig", traceConfig),
    CRDTP_DESERIALIZE_FIELD_OPT("tracingBackend", tracingBackend),
    CRDTP_DESERIALIZE_FIELD_OPT("transferMode", transferMode),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::start(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    startParams params;
    if (!startParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }

    m_backend->Start(std::move(params.categories), std::move(params.options), std::move(params.bufferUsageReportingInterval), std::move(params.transferMode), std::move(params.streamFormat), std::move(params.streamCompression), std::move(params.traceConfig), std::move(params.perfettoConfig), std::move(params.tracingBackend), std::move(params.screenshotMaxSize), std::move(params.screenshotMaxCount), std::make_unique<StartCallbackImpl>(weakPtr(), dispatchable));
}

namespace {
// This helper method (with a static map of redirects) is used from Dispatcher::wire
// immediately below.
const std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>& SortedRedirects() {
  static auto* redirects = [](){
    auto* redirects = new std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>{
    };
    return redirects;
  }();
  return *redirects;
}
}  // namespace

// static
void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
{
    auto dispatcher = std::make_unique<DomainDispatcherImpl>(uber->channel(), backend);
    uber->WireBackend(crdtp::SpanFrom("Tracing"), SortedRedirects(), std::move(dispatcher));
}

} // Tracing
} // namespace content
} // namespace protocol
