// 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/storage.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 Storage {

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

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

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



CRDTP_BEGIN_DESERIALIZER(UsageForType)
    CRDTP_DESERIALIZE_FIELD("storageType", m_storageType),
    CRDTP_DESERIALIZE_FIELD("usage", m_usage),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(UsageForType)
    CRDTP_SERIALIZE_FIELD("storageType", m_storageType);
    CRDTP_SERIALIZE_FIELD("usage", m_usage);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(TrustTokens)
    CRDTP_DESERIALIZE_FIELD("count", m_count),
    CRDTP_DESERIALIZE_FIELD("issuerOrigin", m_issuerOrigin),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(TrustTokens)
    CRDTP_SERIALIZE_FIELD("issuerOrigin", m_issuerOrigin);
    CRDTP_SERIALIZE_FIELD("count", m_count);
CRDTP_END_SERIALIZER();



CRDTP_BEGIN_DESERIALIZER(StorageBucket)
    CRDTP_DESERIALIZE_FIELD_OPT("name", m_name),
    CRDTP_DESERIALIZE_FIELD("storageKey", m_storageKey),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(StorageBucket)
    CRDTP_SERIALIZE_FIELD("storageKey", m_storageKey);
    CRDTP_SERIALIZE_FIELD("name", m_name);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(StorageBucketInfo)
    CRDTP_DESERIALIZE_FIELD("bucket", m_bucket),
    CRDTP_DESERIALIZE_FIELD("durability", m_durability),
    CRDTP_DESERIALIZE_FIELD("expiration", m_expiration),
    CRDTP_DESERIALIZE_FIELD("id", m_id),
    CRDTP_DESERIALIZE_FIELD("persistent", m_persistent),
    CRDTP_DESERIALIZE_FIELD("quota", m_quota),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(StorageBucketInfo)
    CRDTP_SERIALIZE_FIELD("bucket", m_bucket);
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("expiration", m_expiration);
    CRDTP_SERIALIZE_FIELD("quota", m_quota);
    CRDTP_SERIALIZE_FIELD("persistent", m_persistent);
    CRDTP_SERIALIZE_FIELD("durability", m_durability);
CRDTP_END_SERIALIZER();


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


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

void Frontend::CacheStorageContentUpdated(const String& origin, const String& storageKey, const String& bucketId, const String& cacheName)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    serializer.AddField(crdtp::MakeSpan("cacheName"), cacheName);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.cacheStorageContentUpdated", serializer.Finish()));
}

void Frontend::CacheStorageListUpdated(const String& origin, const String& storageKey, const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.cacheStorageListUpdated", serializer.Finish()));
}

void Frontend::IndexedDBContentUpdated(const String& origin, const String& storageKey, const String& bucketId, const String& databaseName, const String& objectStoreName)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    serializer.AddField(crdtp::MakeSpan("databaseName"), databaseName);
    serializer.AddField(crdtp::MakeSpan("objectStoreName"), objectStoreName);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.indexedDBContentUpdated", serializer.Finish()));
}

void Frontend::IndexedDBListUpdated(const String& origin, const String& storageKey, const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.indexedDBListUpdated", serializer.Finish()));
}

void Frontend::StorageBucketCreatedOrUpdated(std::unique_ptr<protocol::Storage::StorageBucketInfo> bucketInfo)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("bucketInfo"), bucketInfo);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.storageBucketCreatedOrUpdated", serializer.Finish()));
}

void Frontend::StorageBucketDeleted(const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.storageBucketDeleted", 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 getStorageKeyForFrame(crdtp::Dispatchable& dispatchable);
    void getStorageKey(crdtp::Dispatchable& dispatchable);
    void clearDataForOrigin(crdtp::Dispatchable& dispatchable);
    void clearDataForStorageKey(crdtp::Dispatchable& dispatchable);
    void getCookies(crdtp::Dispatchable& dispatchable);
    void setCookies(crdtp::Dispatchable& dispatchable);
    void clearCookies(crdtp::Dispatchable& dispatchable);
    void getUsageAndQuota(crdtp::Dispatchable& dispatchable);
    void overrideQuotaForOrigin(crdtp::Dispatchable& dispatchable);
    void trackCacheStorageForOrigin(crdtp::Dispatchable& dispatchable);
    void trackCacheStorageForStorageKey(crdtp::Dispatchable& dispatchable);
    void trackIndexedDBForOrigin(crdtp::Dispatchable& dispatchable);
    void trackIndexedDBForStorageKey(crdtp::Dispatchable& dispatchable);
    void untrackCacheStorageForOrigin(crdtp::Dispatchable& dispatchable);
    void untrackCacheStorageForStorageKey(crdtp::Dispatchable& dispatchable);
    void untrackIndexedDBForOrigin(crdtp::Dispatchable& dispatchable);
    void untrackIndexedDBForStorageKey(crdtp::Dispatchable& dispatchable);
    void getTrustTokens(crdtp::Dispatchable& dispatchable);
    void clearTrustTokens(crdtp::Dispatchable& dispatchable);
    void setStorageBucketTracking(crdtp::Dispatchable& dispatchable);
    void deleteStorageBucket(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("clearCookies"),
          &DomainDispatcherImpl::clearCookies
    },
    {
          crdtp::SpanFrom("clearDataForOrigin"),
          &DomainDispatcherImpl::clearDataForOrigin
    },
    {
          crdtp::SpanFrom("clearDataForStorageKey"),
          &DomainDispatcherImpl::clearDataForStorageKey
    },
    {
          crdtp::SpanFrom("clearTrustTokens"),
          &DomainDispatcherImpl::clearTrustTokens
    },
    {
          crdtp::SpanFrom("deleteStorageBucket"),
          &DomainDispatcherImpl::deleteStorageBucket
    },
    {
          crdtp::SpanFrom("getCookies"),
          &DomainDispatcherImpl::getCookies
    },
    {
          crdtp::SpanFrom("getStorageKey"),
          &DomainDispatcherImpl::getStorageKey
    },
    {
          crdtp::SpanFrom("getStorageKeyForFrame"),
          &DomainDispatcherImpl::getStorageKeyForFrame
    },
    {
          crdtp::SpanFrom("getTrustTokens"),
          &DomainDispatcherImpl::getTrustTokens
    },
    {
          crdtp::SpanFrom("getUsageAndQuota"),
          &DomainDispatcherImpl::getUsageAndQuota
    },
    {
          crdtp::SpanFrom("overrideQuotaForOrigin"),
          &DomainDispatcherImpl::overrideQuotaForOrigin
    },
    {
          crdtp::SpanFrom("setCookies"),
          &DomainDispatcherImpl::setCookies
    },
    {
          crdtp::SpanFrom("setStorageBucketTracking"),
          &DomainDispatcherImpl::setStorageBucketTracking
    },
    {
          crdtp::SpanFrom("trackCacheStorageForOrigin"),
          &DomainDispatcherImpl::trackCacheStorageForOrigin
    },
    {
          crdtp::SpanFrom("trackCacheStorageForStorageKey"),
          &DomainDispatcherImpl::trackCacheStorageForStorageKey
    },
    {
          crdtp::SpanFrom("trackIndexedDBForOrigin"),
          &DomainDispatcherImpl::trackIndexedDBForOrigin
    },
    {
          crdtp::SpanFrom("trackIndexedDBForStorageKey"),
          &DomainDispatcherImpl::trackIndexedDBForStorageKey
    },
    {
          crdtp::SpanFrom("untrackCacheStorageForOrigin"),
          &DomainDispatcherImpl::untrackCacheStorageForOrigin
    },
    {
          crdtp::SpanFrom("untrackCacheStorageForStorageKey"),
          &DomainDispatcherImpl::untrackCacheStorageForStorageKey
    },
    {
          crdtp::SpanFrom("untrackIndexedDBForOrigin"),
          &DomainDispatcherImpl::untrackIndexedDBForOrigin
    },
    {
          crdtp::SpanFrom("untrackIndexedDBForStorageKey"),
          &DomainDispatcherImpl::untrackIndexedDBForStorageKey
    },
    };
    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 getStorageKeyForFrameParams : public crdtp::DeserializableProtocolObject<getStorageKeyForFrameParams> {
    String frameId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getStorageKeyForFrameParams)
    CRDTP_DESERIALIZE_FIELD("frameId", frameId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

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

CRDTP_BEGIN_DESERIALIZER(getStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD_OPT("frameId", frameId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class ClearDataForOriginCallbackImpl : public Backend::ClearDataForOriginCallback, public DomainDispatcher::Callback {
public:
    ClearDataForOriginCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.clearDataForOrigin")) { }

    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 clearDataForOriginParams : public crdtp::DeserializableProtocolObject<clearDataForOriginParams> {
    String origin;
    String storageTypes;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(clearDataForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
    CRDTP_DESERIALIZE_FIELD("storageTypes", storageTypes),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ClearDataForOrigin(params.origin, params.storageTypes, std::make_unique<ClearDataForOriginCallbackImpl>(weakPtr(), dispatchable));
}

class ClearDataForStorageKeyCallbackImpl : public Backend::ClearDataForStorageKeyCallback, public DomainDispatcher::Callback {
public:
    ClearDataForStorageKeyCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.clearDataForStorageKey")) { }

    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 clearDataForStorageKeyParams : public crdtp::DeserializableProtocolObject<clearDataForStorageKeyParams> {
    String storageKey;
    String storageTypes;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(clearDataForStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
    CRDTP_DESERIALIZE_FIELD("storageTypes", storageTypes),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ClearDataForStorageKey(params.storageKey, params.storageTypes, std::make_unique<ClearDataForStorageKeyCallbackImpl>(weakPtr(), dispatchable));
}

class GetCookiesCallbackImpl : public Backend::GetCookiesCallback, public DomainDispatcher::Callback {
public:
    GetCookiesCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.getCookies")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

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

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

}  // namespace

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

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

class SetCookiesCallbackImpl : public Backend::SetCookiesCallback, public DomainDispatcher::Callback {
public:
    SetCookiesCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.setCookies")) { }

    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 setCookiesParams : public crdtp::DeserializableProtocolObject<setCookiesParams> {
    std::unique_ptr<protocol::Array<protocol::Network::CookieParam>> cookies;
    std::optional<String> browserContextId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setCookiesParams)
    CRDTP_DESERIALIZE_FIELD_OPT("browserContextId", browserContextId),
    CRDTP_DESERIALIZE_FIELD("cookies", cookies),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SetCookies(std::move(params.cookies), std::move(params.browserContextId), std::make_unique<SetCookiesCallbackImpl>(weakPtr(), dispatchable));
}

class ClearCookiesCallbackImpl : public Backend::ClearCookiesCallback, public DomainDispatcher::Callback {
public:
    ClearCookiesCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.clearCookies")) { }

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

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

}  // namespace

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

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

class GetUsageAndQuotaCallbackImpl : public Backend::GetUsageAndQuotaCallback, public DomainDispatcher::Callback {
public:
    GetUsageAndQuotaCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.getUsageAndQuota")) { }

    void sendSuccess(double usage, double quota, bool overrideActive, std::unique_ptr<protocol::Array<protocol::Storage::UsageForType>> usageBreakdown) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("usage"), usage);
        serializer.AddField(crdtp::MakeSpan("quota"), quota);
        serializer.AddField(crdtp::MakeSpan("overrideActive"), overrideActive);
        serializer.AddField(crdtp::MakeSpan("usageBreakdown"), usageBreakdown);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct getUsageAndQuotaParams : public crdtp::DeserializableProtocolObject<getUsageAndQuotaParams> {
    String origin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getUsageAndQuotaParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GetUsageAndQuota(params.origin, std::make_unique<GetUsageAndQuotaCallbackImpl>(weakPtr(), dispatchable));
}

class OverrideQuotaForOriginCallbackImpl : public Backend::OverrideQuotaForOriginCallback, public DomainDispatcher::Callback {
public:
    OverrideQuotaForOriginCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.overrideQuotaForOrigin")) { }

    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 overrideQuotaForOriginParams : public crdtp::DeserializableProtocolObject<overrideQuotaForOriginParams> {
    String origin;
    std::optional<double> quotaSize;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(overrideQuotaForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
    CRDTP_DESERIALIZE_FIELD_OPT("quotaSize", quotaSize),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->OverrideQuotaForOrigin(params.origin, std::move(params.quotaSize), std::make_unique<OverrideQuotaForOriginCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct trackCacheStorageForOriginParams : public crdtp::DeserializableProtocolObject<trackCacheStorageForOriginParams> {
    String origin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(trackCacheStorageForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct trackCacheStorageForStorageKeyParams : public crdtp::DeserializableProtocolObject<trackCacheStorageForStorageKeyParams> {
    String storageKey;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(trackCacheStorageForStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct trackIndexedDBForOriginParams : public crdtp::DeserializableProtocolObject<trackIndexedDBForOriginParams> {
    String origin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(trackIndexedDBForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct trackIndexedDBForStorageKeyParams : public crdtp::DeserializableProtocolObject<trackIndexedDBForStorageKeyParams> {
    String storageKey;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(trackIndexedDBForStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct untrackCacheStorageForOriginParams : public crdtp::DeserializableProtocolObject<untrackCacheStorageForOriginParams> {
    String origin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(untrackCacheStorageForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct untrackCacheStorageForStorageKeyParams : public crdtp::DeserializableProtocolObject<untrackCacheStorageForStorageKeyParams> {
    String storageKey;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(untrackCacheStorageForStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct untrackIndexedDBForOriginParams : public crdtp::DeserializableProtocolObject<untrackIndexedDBForOriginParams> {
    String origin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(untrackIndexedDBForOriginParams)
    CRDTP_DESERIALIZE_FIELD("origin", origin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct untrackIndexedDBForStorageKeyParams : public crdtp::DeserializableProtocolObject<untrackIndexedDBForStorageKeyParams> {
    String storageKey;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(untrackIndexedDBForStorageKeyParams)
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class GetTrustTokensCallbackImpl : public Backend::GetTrustTokensCallback, public DomainDispatcher::Callback {
public:
    GetTrustTokensCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.getTrustTokens")) { }

    void sendSuccess(std::unique_ptr<protocol::Array<protocol::Storage::TrustTokens>> tokens) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("tokens"), tokens);
        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::getTrustTokens(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetTrustTokens(std::make_unique<GetTrustTokensCallbackImpl>(weakPtr(), dispatchable));
}

class ClearTrustTokensCallbackImpl : public Backend::ClearTrustTokensCallback, public DomainDispatcher::Callback {
public:
    ClearTrustTokensCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.clearTrustTokens")) { }

    void sendSuccess(bool didDeleteTokens) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("didDeleteTokens"), didDeleteTokens);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct clearTrustTokensParams : public crdtp::DeserializableProtocolObject<clearTrustTokensParams> {
    String issuerOrigin;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(clearTrustTokensParams)
    CRDTP_DESERIALIZE_FIELD("issuerOrigin", issuerOrigin),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ClearTrustTokens(params.issuerOrigin, std::make_unique<ClearTrustTokensCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct setStorageBucketTrackingParams : public crdtp::DeserializableProtocolObject<setStorageBucketTrackingParams> {
    String storageKey;
    bool enable;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setStorageBucketTrackingParams)
    CRDTP_DESERIALIZE_FIELD("enable", enable),
    CRDTP_DESERIALIZE_FIELD("storageKey", storageKey),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct deleteStorageBucketParams : public crdtp::DeserializableProtocolObject<deleteStorageBucketParams> {
    std::unique_ptr<protocol::Storage::StorageBucket> bucket;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(deleteStorageBucketParams)
    CRDTP_DESERIALIZE_FIELD("bucket", bucket),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->DeleteStorageBucket(std::move(params.bucket));
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    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("Storage"), SortedRedirects(), std::move(dispatcher));
}

} // Storage
} // namespace content
} // namespace protocol
