// 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/target.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 Target {

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

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

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



CRDTP_BEGIN_DESERIALIZER(TargetInfo)
    CRDTP_DESERIALIZE_FIELD("attached", m_attached),
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", m_browserContextId),
    CRDTP_DESERIALIZE_FIELD("canAccessOpener", m_canAccessOpener),
    CRDTP_DESERIALIZE_FIELD_OPT("embedderData", m_embedderData),
    CRDTP_DESERIALIZE_FIELD_OPT("openerFrameId", m_openerFrameId),
    CRDTP_DESERIALIZE_FIELD_OPT("openerId", m_openerId),
    CRDTP_DESERIALIZE_FIELD_OPT("parentFrameId", m_parentFrameId),
    CRDTP_DESERIALIZE_FIELD_OPT("parentId", m_parentId),
    CRDTP_DESERIALIZE_FIELD_OPT("subtype", m_subtype),
    CRDTP_DESERIALIZE_FIELD("targetId", m_targetId),
    CRDTP_DESERIALIZE_FIELD("title", m_title),
    CRDTP_DESERIALIZE_FIELD("type", m_type),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(TargetInfo)
    CRDTP_SERIALIZE_FIELD("targetId", m_targetId);
    CRDTP_SERIALIZE_FIELD("type", m_type);
    CRDTP_SERIALIZE_FIELD("title", m_title);
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("attached", m_attached);
    CRDTP_SERIALIZE_FIELD("parentId", m_parentId);
    CRDTP_SERIALIZE_FIELD("openerId", m_openerId);
    CRDTP_SERIALIZE_FIELD("canAccessOpener", m_canAccessOpener);
    CRDTP_SERIALIZE_FIELD("openerFrameId", m_openerFrameId);
    CRDTP_SERIALIZE_FIELD("parentFrameId", m_parentFrameId);
    CRDTP_SERIALIZE_FIELD("browserContextId", m_browserContextId);
    CRDTP_SERIALIZE_FIELD("subtype", m_subtype);
    CRDTP_SERIALIZE_FIELD("embedderData", m_embedderData);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(FilterEntry)
    CRDTP_DESERIALIZE_FIELD_OPT("exclude", m_exclude),
    CRDTP_DESERIALIZE_FIELD_OPT("type", m_type),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(FilterEntry)
    CRDTP_SERIALIZE_FIELD("exclude", m_exclude);
    CRDTP_SERIALIZE_FIELD("type", m_type);
CRDTP_END_SERIALIZER();



CRDTP_BEGIN_DESERIALIZER(RemoteLocation)
    CRDTP_DESERIALIZE_FIELD("host", m_host),
    CRDTP_DESERIALIZE_FIELD("port", m_port),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(RemoteLocation)
    CRDTP_SERIALIZE_FIELD("host", m_host);
    CRDTP_SERIALIZE_FIELD("port", m_port);
CRDTP_END_SERIALIZER();



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


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

void Frontend::AttachedToTarget(const String& sessionId, std::unique_ptr<protocol::Target::TargetInfo> targetInfo, bool waitingForDebugger)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("sessionId"), sessionId);
    serializer.AddField(crdtp::MakeSpan("targetInfo"), targetInfo);
    serializer.AddField(crdtp::MakeSpan("waitingForDebugger"), waitingForDebugger);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.attachedToTarget", serializer.Finish()));
}

void Frontend::DetachedFromTarget(const String& sessionId, std::optional<String> targetId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("sessionId"), sessionId);
    serializer.AddField(crdtp::MakeSpan("targetId"), targetId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.detachedFromTarget", serializer.Finish()));
}

void Frontend::ReceivedMessageFromTarget(const String& sessionId, const String& message, std::optional<String> targetId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("sessionId"), sessionId);
    serializer.AddField(crdtp::MakeSpan("message"), message);
    serializer.AddField(crdtp::MakeSpan("targetId"), targetId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.receivedMessageFromTarget", serializer.Finish()));
}

void Frontend::TargetCreated(std::unique_ptr<protocol::Target::TargetInfo> targetInfo)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("targetInfo"), targetInfo);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.targetCreated", serializer.Finish()));
}

void Frontend::TargetDestroyed(const String& targetId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("targetId"), targetId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.targetDestroyed", serializer.Finish()));
}

void Frontend::TargetCrashed(const String& targetId, const String& status, int errorCode)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("targetId"), targetId);
    serializer.AddField(crdtp::MakeSpan("status"), status);
    serializer.AddField(crdtp::MakeSpan("errorCode"), errorCode);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.targetCrashed", serializer.Finish()));
}

void Frontend::TargetInfoChanged(std::unique_ptr<protocol::Target::TargetInfo> targetInfo)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("targetInfo"), targetInfo);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Target.targetInfoChanged", 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 activateTarget(crdtp::Dispatchable& dispatchable);
    void attachToTarget(crdtp::Dispatchable& dispatchable);
    void attachToBrowserTarget(crdtp::Dispatchable& dispatchable);
    void closeTarget(crdtp::Dispatchable& dispatchable);
    void exposeDevToolsProtocol(crdtp::Dispatchable& dispatchable);
    void createBrowserContext(crdtp::Dispatchable& dispatchable);
    void getBrowserContexts(crdtp::Dispatchable& dispatchable);
    void createTarget(crdtp::Dispatchable& dispatchable);
    void detachFromTarget(crdtp::Dispatchable& dispatchable);
    void disposeBrowserContext(crdtp::Dispatchable& dispatchable);
    void getTargetInfo(crdtp::Dispatchable& dispatchable);
    void getTargets(crdtp::Dispatchable& dispatchable);
    void sendMessageToTarget(crdtp::Dispatchable& dispatchable);
    void setAutoAttach(crdtp::Dispatchable& dispatchable);
    void autoAttachRelated(crdtp::Dispatchable& dispatchable);
    void setDiscoverTargets(crdtp::Dispatchable& dispatchable);
    void setRemoteLocations(crdtp::Dispatchable& dispatchable);
    void getDevToolsTarget(crdtp::Dispatchable& dispatchable);
    void openDevTools(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("activateTarget"),
          &DomainDispatcherImpl::activateTarget
    },
    {
          crdtp::SpanFrom("attachToBrowserTarget"),
          &DomainDispatcherImpl::attachToBrowserTarget
    },
    {
          crdtp::SpanFrom("attachToTarget"),
          &DomainDispatcherImpl::attachToTarget
    },
    {
          crdtp::SpanFrom("autoAttachRelated"),
          &DomainDispatcherImpl::autoAttachRelated
    },
    {
          crdtp::SpanFrom("closeTarget"),
          &DomainDispatcherImpl::closeTarget
    },
    {
          crdtp::SpanFrom("createBrowserContext"),
          &DomainDispatcherImpl::createBrowserContext
    },
    {
          crdtp::SpanFrom("createTarget"),
          &DomainDispatcherImpl::createTarget
    },
    {
          crdtp::SpanFrom("detachFromTarget"),
          &DomainDispatcherImpl::detachFromTarget
    },
    {
          crdtp::SpanFrom("disposeBrowserContext"),
          &DomainDispatcherImpl::disposeBrowserContext
    },
    {
          crdtp::SpanFrom("exposeDevToolsProtocol"),
          &DomainDispatcherImpl::exposeDevToolsProtocol
    },
    {
          crdtp::SpanFrom("getBrowserContexts"),
          &DomainDispatcherImpl::getBrowserContexts
    },
    {
          crdtp::SpanFrom("getDevToolsTarget"),
          &DomainDispatcherImpl::getDevToolsTarget
    },
    {
          crdtp::SpanFrom("getTargetInfo"),
          &DomainDispatcherImpl::getTargetInfo
    },
    {
          crdtp::SpanFrom("getTargets"),
          &DomainDispatcherImpl::getTargets
    },
    {
          crdtp::SpanFrom("openDevTools"),
          &DomainDispatcherImpl::openDevTools
    },
    {
          crdtp::SpanFrom("sendMessageToTarget"),
          &DomainDispatcherImpl::sendMessageToTarget
    },
    {
          crdtp::SpanFrom("setAutoAttach"),
          &DomainDispatcherImpl::setAutoAttach
    },
    {
          crdtp::SpanFrom("setDiscoverTargets"),
          &DomainDispatcherImpl::setDiscoverTargets
    },
    {
          crdtp::SpanFrom("setRemoteLocations"),
          &DomainDispatcherImpl::setRemoteLocations
    },
    };
    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 {

struct activateTargetParams : public crdtp::DeserializableProtocolObject<activateTargetParams> {
    String targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(activateTargetParams)
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct attachToTargetParams : public crdtp::DeserializableProtocolObject<attachToTargetParams> {
    String targetId;
    std::optional<bool> flatten;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(attachToTargetParams)
    CRDTP_DESERIALIZE_FIELD_OPT("flatten", flatten),
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->AttachToTarget(params.targetId, std::move(params.flatten), &out_sessionId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("sessionId"), out_sessionId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {


}  // namespace

void DomainDispatcherImpl::attachToBrowserTarget(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    String out_sessionId;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->AttachToBrowserTarget(&out_sessionId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("sessionId"), out_sessionId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct closeTargetParams : public crdtp::DeserializableProtocolObject<closeTargetParams> {
    String targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(closeTargetParams)
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->CloseTarget(params.targetId, &out_success);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("success"), out_success);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

class ExposeDevToolsProtocolCallbackImpl : public Backend::ExposeDevToolsProtocolCallback, public DomainDispatcher::Callback {
public:
    ExposeDevToolsProtocolCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Target.exposeDevToolsProtocol")) { }

    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 exposeDevToolsProtocolParams : public crdtp::DeserializableProtocolObject<exposeDevToolsProtocolParams> {
    String targetId;
    std::optional<String> bindingName;
    std::optional<bool> inheritPermissions;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(exposeDevToolsProtocolParams)
    CRDTP_DESERIALIZE_FIELD_OPT("bindingName", bindingName),
    CRDTP_DESERIALIZE_FIELD_OPT("inheritPermissions", inheritPermissions),
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ExposeDevToolsProtocol(params.targetId, std::move(params.bindingName), std::move(params.inheritPermissions), std::make_unique<ExposeDevToolsProtocolCallbackImpl>(weakPtr(), dispatchable));
}

class CreateBrowserContextCallbackImpl : public Backend::CreateBrowserContextCallback, public DomainDispatcher::Callback {
public:
    CreateBrowserContextCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Target.createBrowserContext")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct createBrowserContextParams : public crdtp::DeserializableProtocolObject<createBrowserContextParams> {
    std::optional<bool> disposeOnDetach;
    std::optional<String> proxyServer;
    std::optional<String> proxyBypassList;
    std::unique_ptr<protocol::Array<String>> originsWithUniversalNetworkAccess;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(createBrowserContextParams)
    CRDTP_DESERIALIZE_FIELD_OPT("disposeOnDetach", disposeOnDetach),
    CRDTP_DESERIALIZE_FIELD_OPT("originsWithUniversalNetworkAccess", originsWithUniversalNetworkAccess),
    CRDTP_DESERIALIZE_FIELD_OPT("proxyBypassList", proxyBypassList),
    CRDTP_DESERIALIZE_FIELD_OPT("proxyServer", proxyServer),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->CreateBrowserContext(std::move(params.disposeOnDetach), std::move(params.proxyServer), std::move(params.proxyBypassList), std::move(params.originsWithUniversalNetworkAccess), std::make_unique<CreateBrowserContextCallbackImpl>(weakPtr(), dispatchable));
}

namespace {


}  // namespace

void DomainDispatcherImpl::getBrowserContexts(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    std::unique_ptr<protocol::Array<String>> out_browserContextIds;
    std::optional<String> out_defaultBrowserContextId;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetBrowserContexts(&out_browserContextIds, &out_defaultBrowserContextId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("browserContextIds"), out_browserContextIds);
          serializer.AddField(crdtp::MakeSpan("defaultBrowserContextId"), out_defaultBrowserContextId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct createTargetParams : public crdtp::DeserializableProtocolObject<createTargetParams> {
    String url;
    std::optional<int> left;
    std::optional<int> top;
    std::optional<int> width;
    std::optional<int> height;
    std::optional<String> windowState;
    std::optional<String> browserContextId;
    std::optional<bool> enableBeginFrameControl;
    std::optional<bool> newWindow;
    std::optional<bool> background;
    std::optional<bool> forTab;
    std::optional<bool> hidden;
    std::optional<bool> focus;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(createTargetParams)
    CRDTP_DESERIALIZE_FIELD_OPT("background", background),
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD_OPT("enableBeginFrameControl", enableBeginFrameControl),
    CRDTP_DESERIALIZE_FIELD_OPT("focus", focus),
    CRDTP_DESERIALIZE_FIELD_OPT("forTab", forTab),
    CRDTP_DESERIALIZE_FIELD_OPT("height", height),
    CRDTP_DESERIALIZE_FIELD_OPT("hidden", hidden),
    CRDTP_DESERIALIZE_FIELD_OPT("left", left),
    CRDTP_DESERIALIZE_FIELD_OPT("newWindow", newWindow),
    CRDTP_DESERIALIZE_FIELD_OPT("top", top),
    CRDTP_DESERIALIZE_FIELD("url", url),
    CRDTP_DESERIALIZE_FIELD_OPT("width", width),
    CRDTP_DESERIALIZE_FIELD_OPT("windowState", windowState),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->CreateTarget(params.url, std::move(params.left), std::move(params.top), std::move(params.width), std::move(params.height), std::move(params.windowState), std::move(params.browserContextId), std::move(params.enableBeginFrameControl), std::move(params.newWindow), std::move(params.background), std::move(params.forTab), std::move(params.hidden), std::move(params.focus), &out_targetId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("targetId"), out_targetId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct detachFromTargetParams : public crdtp::DeserializableProtocolObject<detachFromTargetParams> {
    std::optional<String> sessionId;
    std::optional<String> targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(detachFromTargetParams)
    CRDTP_DESERIALIZE_FIELD_OPT("sessionId", sessionId),
    CRDTP_DESERIALIZE_FIELD_OPT("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class DisposeBrowserContextCallbackImpl : public Backend::DisposeBrowserContextCallback, public DomainDispatcher::Callback {
public:
    DisposeBrowserContextCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Target.disposeBrowserContext")) { }

    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 disposeBrowserContextParams : public crdtp::DeserializableProtocolObject<disposeBrowserContextParams> {
    String browserContextId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(disposeBrowserContextParams)
    CRDTP_DESERIALIZE_FIELD("browserContextId", browserContextId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->DisposeBrowserContext(params.browserContextId, std::make_unique<DisposeBrowserContextCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct getTargetInfoParams : public crdtp::DeserializableProtocolObject<getTargetInfoParams> {
    std::optional<String> targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getTargetInfoParams)
    CRDTP_DESERIALIZE_FIELD_OPT("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::getTargetInfo(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    getTargetInfoParams params;
    if (!getTargetInfoParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::unique_ptr<protocol::Target::TargetInfo> out_targetInfo;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetTargetInfo(std::move(params.targetId), &out_targetInfo);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("targetInfo"), out_targetInfo);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct getTargetsParams : public crdtp::DeserializableProtocolObject<getTargetsParams> {
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getTargetsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("filter", filter),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::getTargets(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    getTargetsParams params;
    if (!getTargetsParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::unique_ptr<protocol::Array<protocol::Target::TargetInfo>> out_targetInfos;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetTargets(std::move(params.filter), &out_targetInfos);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("targetInfos"), out_targetInfos);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct sendMessageToTargetParams : public crdtp::DeserializableProtocolObject<sendMessageToTargetParams> {
    String message;
    std::optional<String> sessionId;
    std::optional<String> targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(sendMessageToTargetParams)
    CRDTP_DESERIALIZE_FIELD("message", message),
    CRDTP_DESERIALIZE_FIELD_OPT("sessionId", sessionId),
    CRDTP_DESERIALIZE_FIELD_OPT("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class SetAutoAttachCallbackImpl : public Backend::SetAutoAttachCallback, public DomainDispatcher::Callback {
public:
    SetAutoAttachCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Target.setAutoAttach")) { }

    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 setAutoAttachParams : public crdtp::DeserializableProtocolObject<setAutoAttachParams> {
    bool autoAttach;
    bool waitForDebuggerOnStart;
    std::optional<bool> flatten;
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setAutoAttachParams)
    CRDTP_DESERIALIZE_FIELD("autoAttach", autoAttach),
    CRDTP_DESERIALIZE_FIELD_OPT("filter", filter),
    CRDTP_DESERIALIZE_FIELD_OPT("flatten", flatten),
    CRDTP_DESERIALIZE_FIELD("waitForDebuggerOnStart", waitForDebuggerOnStart),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SetAutoAttach(params.autoAttach, params.waitForDebuggerOnStart, std::move(params.flatten), std::move(params.filter), std::make_unique<SetAutoAttachCallbackImpl>(weakPtr(), dispatchable));
}

class AutoAttachRelatedCallbackImpl : public Backend::AutoAttachRelatedCallback, public DomainDispatcher::Callback {
public:
    AutoAttachRelatedCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Target.autoAttachRelated")) { }

    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 autoAttachRelatedParams : public crdtp::DeserializableProtocolObject<autoAttachRelatedParams> {
    String targetId;
    bool waitForDebuggerOnStart;
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(autoAttachRelatedParams)
    CRDTP_DESERIALIZE_FIELD_OPT("filter", filter),
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
    CRDTP_DESERIALIZE_FIELD("waitForDebuggerOnStart", waitForDebuggerOnStart),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->AutoAttachRelated(params.targetId, params.waitForDebuggerOnStart, std::move(params.filter), std::make_unique<AutoAttachRelatedCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct setDiscoverTargetsParams : public crdtp::DeserializableProtocolObject<setDiscoverTargetsParams> {
    bool discover;
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setDiscoverTargetsParams)
    CRDTP_DESERIALIZE_FIELD("discover", discover),
    CRDTP_DESERIALIZE_FIELD_OPT("filter", filter),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setRemoteLocationsParams : public crdtp::DeserializableProtocolObject<setRemoteLocationsParams> {
    std::unique_ptr<protocol::Array<protocol::Target::RemoteLocation>> locations;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setRemoteLocationsParams)
    CRDTP_DESERIALIZE_FIELD("locations", locations),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct getDevToolsTargetParams : public crdtp::DeserializableProtocolObject<getDevToolsTargetParams> {
    String targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getDevToolsTargetParams)
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::getDevToolsTarget(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    getDevToolsTargetParams params;
    if (!getDevToolsTargetParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::optional<String> out_targetId;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetDevToolsTarget(params.targetId, &out_targetId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("targetId"), out_targetId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct openDevToolsParams : public crdtp::DeserializableProtocolObject<openDevToolsParams> {
    String targetId;
    std::optional<String> panelId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(openDevToolsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("panelId", panelId),
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->OpenDevTools(params.targetId, std::move(params.panelId), &out_targetId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("targetId"), out_targetId);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

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("Target"), SortedRedirects(), std::move(dispatcher));
}

} // Target
} // namespace content
} // namespace protocol
