// 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/browser.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 Browser {

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

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

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




CRDTP_BEGIN_DESERIALIZER(PermissionDescriptor)
    CRDTP_DESERIALIZE_FIELD_OPT("allowWithoutGesture", m_allowWithoutGesture),
    CRDTP_DESERIALIZE_FIELD_OPT("allowWithoutSanitization", m_allowWithoutSanitization),
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD_OPT("panTiltZoom", m_panTiltZoom),
    CRDTP_DESERIALIZE_FIELD_OPT("sysex", m_sysex),
    CRDTP_DESERIALIZE_FIELD_OPT("userVisibleOnly", m_userVisibleOnly),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(PermissionDescriptor)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("sysex", m_sysex);
    CRDTP_SERIALIZE_FIELD("userVisibleOnly", m_userVisibleOnly);
    CRDTP_SERIALIZE_FIELD("allowWithoutSanitization", m_allowWithoutSanitization);
    CRDTP_SERIALIZE_FIELD("allowWithoutGesture", m_allowWithoutGesture);
    CRDTP_SERIALIZE_FIELD("panTiltZoom", m_panTiltZoom);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Bucket)
    CRDTP_DESERIALIZE_FIELD("count", m_count),
    CRDTP_DESERIALIZE_FIELD("high", m_high),
    CRDTP_DESERIALIZE_FIELD("low", m_low),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Bucket)
    CRDTP_SERIALIZE_FIELD("low", m_low);
    CRDTP_SERIALIZE_FIELD("high", m_high);
    CRDTP_SERIALIZE_FIELD("count", m_count);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Histogram)
    CRDTP_DESERIALIZE_FIELD("buckets", m_buckets),
    CRDTP_DESERIALIZE_FIELD("count", m_count),
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("sum", m_sum),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Histogram)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("sum", m_sum);
    CRDTP_SERIALIZE_FIELD("count", m_count);
    CRDTP_SERIALIZE_FIELD("buckets", m_buckets);
CRDTP_END_SERIALIZER();


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


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

void Frontend::DownloadWillBegin(const String& frameId, const String& guid, const String& url, const String& suggestedFilename)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("guid"), guid);
    serializer.AddField(crdtp::MakeSpan("url"), url);
    serializer.AddField(crdtp::MakeSpan("suggestedFilename"), suggestedFilename);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Browser.downloadWillBegin", serializer.Finish()));
}

void Frontend::DownloadProgress(const String& guid, double totalBytes, double receivedBytes, const String& state, std::optional<String> filePath)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("guid"), guid);
    serializer.AddField(crdtp::MakeSpan("totalBytes"), totalBytes);
    serializer.AddField(crdtp::MakeSpan("receivedBytes"), receivedBytes);
    serializer.AddField(crdtp::MakeSpan("state"), state);
    serializer.AddField(crdtp::MakeSpan("filePath"), filePath);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Browser.downloadProgress", 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 setPermission(crdtp::Dispatchable& dispatchable);
    void grantPermissions(crdtp::Dispatchable& dispatchable);
    void resetPermissions(crdtp::Dispatchable& dispatchable);
    void setDownloadBehavior(crdtp::Dispatchable& dispatchable);
    void cancelDownload(crdtp::Dispatchable& dispatchable);
    void crash(crdtp::Dispatchable& dispatchable);
    void crashGpuProcess(crdtp::Dispatchable& dispatchable);
    void getVersion(crdtp::Dispatchable& dispatchable);
    void getBrowserCommandLine(crdtp::Dispatchable& dispatchable);
    void addMockCamera(crdtp::Dispatchable& dispatchable);
    void getHistograms(crdtp::Dispatchable& dispatchable);
    void getHistogram(crdtp::Dispatchable& dispatchable);
    void getGlobalPrivacyControl(crdtp::Dispatchable& dispatchable);
    void setGlobalPrivacyControl(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("addMockCamera"),
          &DomainDispatcherImpl::addMockCamera
    },
    {
          crdtp::SpanFrom("cancelDownload"),
          &DomainDispatcherImpl::cancelDownload
    },
    {
          crdtp::SpanFrom("crash"),
          &DomainDispatcherImpl::crash
    },
    {
          crdtp::SpanFrom("crashGpuProcess"),
          &DomainDispatcherImpl::crashGpuProcess
    },
    {
          crdtp::SpanFrom("getBrowserCommandLine"),
          &DomainDispatcherImpl::getBrowserCommandLine
    },
    {
          crdtp::SpanFrom("getGlobalPrivacyControl"),
          &DomainDispatcherImpl::getGlobalPrivacyControl
    },
    {
          crdtp::SpanFrom("getHistogram"),
          &DomainDispatcherImpl::getHistogram
    },
    {
          crdtp::SpanFrom("getHistograms"),
          &DomainDispatcherImpl::getHistograms
    },
    {
          crdtp::SpanFrom("getVersion"),
          &DomainDispatcherImpl::getVersion
    },
    {
          crdtp::SpanFrom("grantPermissions"),
          &DomainDispatcherImpl::grantPermissions
    },
    {
          crdtp::SpanFrom("resetPermissions"),
          &DomainDispatcherImpl::resetPermissions
    },
    {
          crdtp::SpanFrom("setDownloadBehavior"),
          &DomainDispatcherImpl::setDownloadBehavior
    },
    {
          crdtp::SpanFrom("setGlobalPrivacyControl"),
          &DomainDispatcherImpl::setGlobalPrivacyControl
    },
    {
          crdtp::SpanFrom("setPermission"),
          &DomainDispatcherImpl::setPermission
    },
    };
    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;
}


class SetPermissionCallbackImpl : public Backend::SetPermissionCallback, public DomainDispatcher::Callback {
public:
    SetPermissionCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Browser.setPermission")) { }

    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 setPermissionParams : public crdtp::DeserializableProtocolObject<setPermissionParams> {
    std::unique_ptr<protocol::Browser::PermissionDescriptor> permission;
    String setting;
    std::optional<String> origin;
    std::optional<String> embeddedOrigin;
    std::optional<String> browserContextId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setPermissionParams)
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD_OPT("embeddedOrigin", embeddedOrigin),
    CRDTP_DESERIALIZE_FIELD_OPT("origin", origin),
    CRDTP_DESERIALIZE_FIELD("permission", permission),
    CRDTP_DESERIALIZE_FIELD("setting", setting),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SetPermission(std::move(params.permission), params.setting, std::move(params.origin), std::move(params.embeddedOrigin), std::move(params.browserContextId), std::make_unique<SetPermissionCallbackImpl>(weakPtr(), dispatchable));
}

class GrantPermissionsCallbackImpl : public Backend::GrantPermissionsCallback, public DomainDispatcher::Callback {
public:
    GrantPermissionsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Browser.grantPermissions")) { }

    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 grantPermissionsParams : public crdtp::DeserializableProtocolObject<grantPermissionsParams> {
    std::unique_ptr<protocol::Array<String>> permissions;
    std::optional<String> origin;
    std::optional<String> browserContextId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(grantPermissionsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD_OPT("origin", origin),
    CRDTP_DESERIALIZE_FIELD("permissions", permissions),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GrantPermissions(std::move(params.permissions), std::move(params.origin), std::move(params.browserContextId), std::make_unique<GrantPermissionsCallbackImpl>(weakPtr(), dispatchable));
}

class ResetPermissionsCallbackImpl : public Backend::ResetPermissionsCallback, public DomainDispatcher::Callback {
public:
    ResetPermissionsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Browser.resetPermissions")) { }

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

CRDTP_BEGIN_DESERIALIZER(resetPermissionsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ResetPermissions(std::move(params.browserContextId), std::make_unique<ResetPermissionsCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct setDownloadBehaviorParams : public crdtp::DeserializableProtocolObject<setDownloadBehaviorParams> {
    String behavior;
    std::optional<String> browserContextId;
    std::optional<String> downloadPath;
    std::optional<bool> eventsEnabled;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setDownloadBehaviorParams)
    CRDTP_DESERIALIZE_FIELD("behavior", behavior),
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD_OPT("downloadPath", downloadPath),
    CRDTP_DESERIALIZE_FIELD_OPT("eventsEnabled", eventsEnabled),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct cancelDownloadParams : public crdtp::DeserializableProtocolObject<cancelDownloadParams> {
    String guid;
    std::optional<String> browserContextId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(cancelDownloadParams)
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD("guid", guid),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {


}  // namespace

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

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

namespace {


}  // namespace

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

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

namespace {


}  // namespace

void DomainDispatcherImpl::getVersion(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    String out_protocolVersion;
    String out_product;
    String out_revision;
    String out_userAgent;
    String out_jsVersion;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetVersion(&out_protocolVersion, &out_product, &out_revision, &out_userAgent, &out_jsVersion);
    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("protocolVersion"), out_protocolVersion);
          serializer.AddField(crdtp::MakeSpan("product"), out_product);
          serializer.AddField(crdtp::MakeSpan("revision"), out_revision);
          serializer.AddField(crdtp::MakeSpan("userAgent"), out_userAgent);
          serializer.AddField(crdtp::MakeSpan("jsVersion"), out_jsVersion);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {


}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetBrowserCommandLine(&out_arguments);
    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("arguments"), out_arguments);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct addMockCameraParams : public crdtp::DeserializableProtocolObject<addMockCameraParams> {
    String deviceId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(addMockCameraParams)
    CRDTP_DESERIALIZE_FIELD("deviceId", deviceId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct getHistogramsParams : public crdtp::DeserializableProtocolObject<getHistogramsParams> {
    std::optional<String> query;
    std::optional<bool> delta;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getHistogramsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("delta", delta),
    CRDTP_DESERIALIZE_FIELD_OPT("query", query),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetHistograms(std::move(params.query), std::move(params.delta), &out_histograms);
    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("histograms"), out_histograms);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct getHistogramParams : public crdtp::DeserializableProtocolObject<getHistogramParams> {
    String name;
    std::optional<bool> delta;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getHistogramParams)
    CRDTP_DESERIALIZE_FIELD_OPT("delta", delta),
    CRDTP_DESERIALIZE_FIELD("name", name),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::getHistogram(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    getHistogramParams params;
    if (!getHistogramParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::unique_ptr<protocol::Browser::Histogram> out_histogram;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetHistogram(params.name, std::move(params.delta), &out_histogram);
    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("histogram"), out_histogram);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {


}  // namespace

void DomainDispatcherImpl::getGlobalPrivacyControl(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    bool out_gpc;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetGlobalPrivacyControl(&out_gpc);
    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("gpc"), out_gpc);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {

struct setGlobalPrivacyControlParams : public crdtp::DeserializableProtocolObject<setGlobalPrivacyControlParams> {
    bool gpc;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setGlobalPrivacyControlParams)
    CRDTP_DESERIALIZE_FIELD("gpc", gpc),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->SetGlobalPrivacyControl(params.gpc, &out_gpc);
    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("gpc"), out_gpc);
          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("Browser"), SortedRedirects(), std::move(dispatcher));
}

} // Browser
} // namespace content
} // namespace protocol
