// 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/page.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 Page {

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

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

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




CRDTP_BEGIN_DESERIALIZER(NavigationEntry)
    CRDTP_DESERIALIZE_FIELD("id", m_id),
    CRDTP_DESERIALIZE_FIELD("title", m_title),
    CRDTP_DESERIALIZE_FIELD("transitionType", m_transitionType),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
    CRDTP_DESERIALIZE_FIELD("userTypedURL", m_userTypedURL),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(NavigationEntry)
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("userTypedURL", m_userTypedURL);
    CRDTP_SERIALIZE_FIELD("title", m_title);
    CRDTP_SERIALIZE_FIELD("transitionType", m_transitionType);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ScreencastFrameMetadata)
    CRDTP_DESERIALIZE_FIELD("deviceHeight", m_deviceHeight),
    CRDTP_DESERIALIZE_FIELD("deviceWidth", m_deviceWidth),
    CRDTP_DESERIALIZE_FIELD("offsetTop", m_offsetTop),
    CRDTP_DESERIALIZE_FIELD("pageScaleFactor", m_pageScaleFactor),
    CRDTP_DESERIALIZE_FIELD("scrollOffsetX", m_scrollOffsetX),
    CRDTP_DESERIALIZE_FIELD("scrollOffsetY", m_scrollOffsetY),
    CRDTP_DESERIALIZE_FIELD_OPT("timestamp", m_timestamp),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ScreencastFrameMetadata)
    CRDTP_SERIALIZE_FIELD("offsetTop", m_offsetTop);
    CRDTP_SERIALIZE_FIELD("pageScaleFactor", m_pageScaleFactor);
    CRDTP_SERIALIZE_FIELD("deviceWidth", m_deviceWidth);
    CRDTP_SERIALIZE_FIELD("deviceHeight", m_deviceHeight);
    CRDTP_SERIALIZE_FIELD("scrollOffsetX", m_scrollOffsetX);
    CRDTP_SERIALIZE_FIELD("scrollOffsetY", m_scrollOffsetY);
    CRDTP_SERIALIZE_FIELD("timestamp", m_timestamp);
CRDTP_END_SERIALIZER();



CRDTP_BEGIN_DESERIALIZER(AppManifestError)
    CRDTP_DESERIALIZE_FIELD("column", m_column),
    CRDTP_DESERIALIZE_FIELD("critical", m_critical),
    CRDTP_DESERIALIZE_FIELD("line", m_line),
    CRDTP_DESERIALIZE_FIELD("message", m_message),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(AppManifestError)
    CRDTP_SERIALIZE_FIELD("message", m_message);
    CRDTP_SERIALIZE_FIELD("critical", m_critical);
    CRDTP_SERIALIZE_FIELD("line", m_line);
    CRDTP_SERIALIZE_FIELD("column", m_column);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(AppManifestParsedProperties)
    CRDTP_DESERIALIZE_FIELD("scope", m_scope),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(AppManifestParsedProperties)
    CRDTP_SERIALIZE_FIELD("scope", m_scope);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Viewport)
    CRDTP_DESERIALIZE_FIELD("height", m_height),
    CRDTP_DESERIALIZE_FIELD("scale", m_scale),
    CRDTP_DESERIALIZE_FIELD("width", m_width),
    CRDTP_DESERIALIZE_FIELD("x", m_x),
    CRDTP_DESERIALIZE_FIELD("y", m_y),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Viewport)
    CRDTP_SERIALIZE_FIELD("x", m_x);
    CRDTP_SERIALIZE_FIELD("y", m_y);
    CRDTP_SERIALIZE_FIELD("width", m_width);
    CRDTP_SERIALIZE_FIELD("height", m_height);
    CRDTP_SERIALIZE_FIELD("scale", m_scale);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(InstallabilityErrorArgument)
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("value", m_value),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(InstallabilityErrorArgument)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("value", m_value);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(InstallabilityError)
    CRDTP_DESERIALIZE_FIELD("errorArguments", m_errorArguments),
    CRDTP_DESERIALIZE_FIELD("errorId", m_errorId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(InstallabilityError)
    CRDTP_SERIALIZE_FIELD("errorId", m_errorId);
    CRDTP_SERIALIZE_FIELD("errorArguments", m_errorArguments);
CRDTP_END_SERIALIZER();



CRDTP_BEGIN_DESERIALIZER(FileFilter)
    CRDTP_DESERIALIZE_FIELD_OPT("accepts", m_accepts),
    CRDTP_DESERIALIZE_FIELD_OPT("name", m_name),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(FileFilter)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("accepts", m_accepts);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(FileHandler)
    CRDTP_DESERIALIZE_FIELD_OPT("accepts", m_accepts),
    CRDTP_DESERIALIZE_FIELD("action", m_action),
    CRDTP_DESERIALIZE_FIELD("launchType", m_launchType),
    CRDTP_DESERIALIZE_FIELD("name", m_name),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(FileHandler)
    CRDTP_SERIALIZE_FIELD("action", m_action);
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("accepts", m_accepts);
    CRDTP_SERIALIZE_FIELD("launchType", m_launchType);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ImageResource)
    CRDTP_DESERIALIZE_FIELD_OPT("sizes", m_sizes),
    CRDTP_DESERIALIZE_FIELD_OPT("type", m_type),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ImageResource)
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("sizes", m_sizes);
    CRDTP_SERIALIZE_FIELD("type", m_type);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(LaunchHandler)
    CRDTP_DESERIALIZE_FIELD("clientMode", m_clientMode),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(LaunchHandler)
    CRDTP_SERIALIZE_FIELD("clientMode", m_clientMode);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ProtocolHandler)
    CRDTP_DESERIALIZE_FIELD("protocol", m_protocol),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ProtocolHandler)
    CRDTP_SERIALIZE_FIELD("protocol", m_protocol);
    CRDTP_SERIALIZE_FIELD("url", m_url);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(RelatedApplication)
    CRDTP_DESERIALIZE_FIELD_OPT("id", m_id),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(RelatedApplication)
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("url", m_url);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ScopeExtension)
    CRDTP_DESERIALIZE_FIELD("hasOriginWildcard", m_hasOriginWildcard),
    CRDTP_DESERIALIZE_FIELD("origin", m_origin),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ScopeExtension)
    CRDTP_SERIALIZE_FIELD("origin", m_origin);
    CRDTP_SERIALIZE_FIELD("hasOriginWildcard", m_hasOriginWildcard);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Screenshot)
    CRDTP_DESERIALIZE_FIELD("formFactor", m_formFactor),
    CRDTP_DESERIALIZE_FIELD("image", m_image),
    CRDTP_DESERIALIZE_FIELD_OPT("label", m_label),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Screenshot)
    CRDTP_SERIALIZE_FIELD("image", m_image);
    CRDTP_SERIALIZE_FIELD("formFactor", m_formFactor);
    CRDTP_SERIALIZE_FIELD("label", m_label);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ShareTarget)
    CRDTP_DESERIALIZE_FIELD("action", m_action),
    CRDTP_DESERIALIZE_FIELD("enctype", m_enctype),
    CRDTP_DESERIALIZE_FIELD_OPT("files", m_files),
    CRDTP_DESERIALIZE_FIELD("method", m_method),
    CRDTP_DESERIALIZE_FIELD_OPT("text", m_text),
    CRDTP_DESERIALIZE_FIELD_OPT("title", m_title),
    CRDTP_DESERIALIZE_FIELD_OPT("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ShareTarget)
    CRDTP_SERIALIZE_FIELD("action", m_action);
    CRDTP_SERIALIZE_FIELD("method", m_method);
    CRDTP_SERIALIZE_FIELD("enctype", m_enctype);
    CRDTP_SERIALIZE_FIELD("title", m_title);
    CRDTP_SERIALIZE_FIELD("text", m_text);
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("files", m_files);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Shortcut)
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Shortcut)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("url", m_url);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(WebAppManifest)
    CRDTP_DESERIALIZE_FIELD_OPT("backgroundColor", m_backgroundColor),
    CRDTP_DESERIALIZE_FIELD_OPT("description", m_description),
    CRDTP_DESERIALIZE_FIELD_OPT("dir", m_dir),
    CRDTP_DESERIALIZE_FIELD_OPT("display", m_display),
    CRDTP_DESERIALIZE_FIELD_OPT("displayOverrides", m_displayOverrides),
    CRDTP_DESERIALIZE_FIELD_OPT("fileHandlers", m_fileHandlers),
    CRDTP_DESERIALIZE_FIELD_OPT("icons", m_icons),
    CRDTP_DESERIALIZE_FIELD_OPT("id", m_id),
    CRDTP_DESERIALIZE_FIELD_OPT("lang", m_lang),
    CRDTP_DESERIALIZE_FIELD_OPT("launchHandler", m_launchHandler),
    CRDTP_DESERIALIZE_FIELD_OPT("name", m_name),
    CRDTP_DESERIALIZE_FIELD_OPT("orientation", m_orientation),
    CRDTP_DESERIALIZE_FIELD_OPT("preferRelatedApplications", m_preferRelatedApplications),
    CRDTP_DESERIALIZE_FIELD_OPT("protocolHandlers", m_protocolHandlers),
    CRDTP_DESERIALIZE_FIELD_OPT("relatedApplications", m_relatedApplications),
    CRDTP_DESERIALIZE_FIELD_OPT("scope", m_scope),
    CRDTP_DESERIALIZE_FIELD_OPT("scopeExtensions", m_scopeExtensions),
    CRDTP_DESERIALIZE_FIELD_OPT("screenshots", m_screenshots),
    CRDTP_DESERIALIZE_FIELD_OPT("shareTarget", m_shareTarget),
    CRDTP_DESERIALIZE_FIELD_OPT("shortName", m_shortName),
    CRDTP_DESERIALIZE_FIELD_OPT("shortcuts", m_shortcuts),
    CRDTP_DESERIALIZE_FIELD_OPT("startUrl", m_startUrl),
    CRDTP_DESERIALIZE_FIELD_OPT("themeColor", m_themeColor),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(WebAppManifest)
    CRDTP_SERIALIZE_FIELD("backgroundColor", m_backgroundColor);
    CRDTP_SERIALIZE_FIELD("description", m_description);
    CRDTP_SERIALIZE_FIELD("dir", m_dir);
    CRDTP_SERIALIZE_FIELD("display", m_display);
    CRDTP_SERIALIZE_FIELD("displayOverrides", m_displayOverrides);
    CRDTP_SERIALIZE_FIELD("fileHandlers", m_fileHandlers);
    CRDTP_SERIALIZE_FIELD("icons", m_icons);
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("lang", m_lang);
    CRDTP_SERIALIZE_FIELD("launchHandler", m_launchHandler);
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("orientation", m_orientation);
    CRDTP_SERIALIZE_FIELD("preferRelatedApplications", m_preferRelatedApplications);
    CRDTP_SERIALIZE_FIELD("protocolHandlers", m_protocolHandlers);
    CRDTP_SERIALIZE_FIELD("relatedApplications", m_relatedApplications);
    CRDTP_SERIALIZE_FIELD("scope", m_scope);
    CRDTP_SERIALIZE_FIELD("scopeExtensions", m_scopeExtensions);
    CRDTP_SERIALIZE_FIELD("screenshots", m_screenshots);
    CRDTP_SERIALIZE_FIELD("shareTarget", m_shareTarget);
    CRDTP_SERIALIZE_FIELD("shortName", m_shortName);
    CRDTP_SERIALIZE_FIELD("shortcuts", m_shortcuts);
    CRDTP_SERIALIZE_FIELD("startUrl", m_startUrl);
    CRDTP_SERIALIZE_FIELD("themeColor", m_themeColor);
CRDTP_END_SERIALIZER();




CRDTP_BEGIN_DESERIALIZER(BackForwardCacheBlockingDetails)
    CRDTP_DESERIALIZE_FIELD("columnNumber", m_columnNumber),
    CRDTP_DESERIALIZE_FIELD_OPT("function", m_function),
    CRDTP_DESERIALIZE_FIELD("lineNumber", m_lineNumber),
    CRDTP_DESERIALIZE_FIELD_OPT("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(BackForwardCacheBlockingDetails)
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("function", m_function);
    CRDTP_SERIALIZE_FIELD("lineNumber", m_lineNumber);
    CRDTP_SERIALIZE_FIELD("columnNumber", m_columnNumber);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(BackForwardCacheNotRestoredExplanation)
    CRDTP_DESERIALIZE_FIELD_OPT("context", m_context),
    CRDTP_DESERIALIZE_FIELD_OPT("details", m_details),
    CRDTP_DESERIALIZE_FIELD("reason", m_reason),
    CRDTP_DESERIALIZE_FIELD("type", m_type),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(BackForwardCacheNotRestoredExplanation)
    CRDTP_SERIALIZE_FIELD("type", m_type);
    CRDTP_SERIALIZE_FIELD("reason", m_reason);
    CRDTP_SERIALIZE_FIELD("context", m_context);
    CRDTP_SERIALIZE_FIELD("details", m_details);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(BackForwardCacheNotRestoredExplanationTree)
    CRDTP_DESERIALIZE_FIELD("children", m_children),
    CRDTP_DESERIALIZE_FIELD("explanations", m_explanations),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(BackForwardCacheNotRestoredExplanationTree)
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("explanations", m_explanations);
    CRDTP_SERIALIZE_FIELD("children", m_children);
CRDTP_END_SERIALIZER();


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


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

void Frontend::FrameDetached(const String& frameId, const String& reason)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("reason"), reason);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.frameDetached", serializer.Finish()));
}

void Frontend::FrameStartedNavigating(const String& frameId, const String& url, const String& loaderId, const String& navigationType)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("url"), url);
    serializer.AddField(crdtp::MakeSpan("loaderId"), loaderId);
    serializer.AddField(crdtp::MakeSpan("navigationType"), navigationType);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.frameStartedNavigating", serializer.Finish()));
}

void Frontend::FrameStartedLoading(const String& frameId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.frameStartedLoading", serializer.Finish()));
}

void Frontend::FrameStoppedLoading(const String& frameId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.frameStoppedLoading", serializer.Finish()));
}

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("Page.downloadWillBegin", serializer.Finish()));
}

void Frontend::DownloadProgress(const String& guid, double totalBytes, double receivedBytes, const String& state)
{
    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);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.downloadProgress", serializer.Finish()));
}

void Frontend::InterstitialHidden()
{
    if (!frontend_channel_)
        return;
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.interstitialHidden"));
}

void Frontend::InterstitialShown()
{
    if (!frontend_channel_)
        return;
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.interstitialShown"));
}

void Frontend::JavascriptDialogClosed(const String& frameId, bool result, const String& userInput)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("result"), result);
    serializer.AddField(crdtp::MakeSpan("userInput"), userInput);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.javascriptDialogClosed", serializer.Finish()));
}

void Frontend::JavascriptDialogOpening(const String& url, const String& frameId, const String& message, const String& type, bool hasBrowserHandler, std::optional<String> defaultPrompt)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("url"), url);
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("message"), message);
    serializer.AddField(crdtp::MakeSpan("type"), type);
    serializer.AddField(crdtp::MakeSpan("hasBrowserHandler"), hasBrowserHandler);
    serializer.AddField(crdtp::MakeSpan("defaultPrompt"), defaultPrompt);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.javascriptDialogOpening", serializer.Finish()));
}

void Frontend::BackForwardCacheNotUsed(const String& loaderId, const String& frameId, std::unique_ptr<protocol::Array<protocol::Page::BackForwardCacheNotRestoredExplanation>> notRestoredExplanations, std::unique_ptr<protocol::Page::BackForwardCacheNotRestoredExplanationTree> notRestoredExplanationsTree)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("loaderId"), loaderId);
    serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
    serializer.AddField(crdtp::MakeSpan("notRestoredExplanations"), notRestoredExplanations);
    serializer.AddField(crdtp::MakeSpan("notRestoredExplanationsTree"), notRestoredExplanationsTree);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.backForwardCacheNotUsed", serializer.Finish()));
}

void Frontend::ScreencastFrame(const Binary& data, std::unique_ptr<protocol::Page::ScreencastFrameMetadata> metadata, int sessionId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("data"), data);
    serializer.AddField(crdtp::MakeSpan("metadata"), metadata);
    serializer.AddField(crdtp::MakeSpan("sessionId"), sessionId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.screencastFrame", serializer.Finish()));
}

void Frontend::ScreencastVisibilityChanged(bool visible)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("visible"), visible);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Page.screencastVisibilityChanged", 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 addScriptToEvaluateOnLoad(crdtp::Dispatchable& dispatchable);
    void addScriptToEvaluateOnNewDocument(crdtp::Dispatchable& dispatchable);
    void bringToFront(crdtp::Dispatchable& dispatchable);
    void captureScreenshot(crdtp::Dispatchable& dispatchable);
    void captureSnapshot(crdtp::Dispatchable& dispatchable);
    void disable(crdtp::Dispatchable& dispatchable);
    void enable(crdtp::Dispatchable& dispatchable);
    void getAppManifest(crdtp::Dispatchable& dispatchable);
    void getInstallabilityErrors(crdtp::Dispatchable& dispatchable);
    void getManifestIcons(crdtp::Dispatchable& dispatchable);
    void getAppId(crdtp::Dispatchable& dispatchable);
    void getNavigationHistory(crdtp::Dispatchable& dispatchable);
    void resetNavigationHistory(crdtp::Dispatchable& dispatchable);
    void handleJavaScriptDialog(crdtp::Dispatchable& dispatchable);
    void navigate(crdtp::Dispatchable& dispatchable);
    void navigateToHistoryEntry(crdtp::Dispatchable& dispatchable);
    void reload(crdtp::Dispatchable& dispatchable);
    void removeScriptToEvaluateOnLoad(crdtp::Dispatchable& dispatchable);
    void removeScriptToEvaluateOnNewDocument(crdtp::Dispatchable& dispatchable);
    void screencastFrameAck(crdtp::Dispatchable& dispatchable);
    void setBypassCSP(crdtp::Dispatchable& dispatchable);
    void setDownloadBehavior(crdtp::Dispatchable& dispatchable);
    void startScreencast(crdtp::Dispatchable& dispatchable);
    void startScreenRecording(crdtp::Dispatchable& dispatchable);
    void stopScreenRecording(crdtp::Dispatchable& dispatchable);
    void stopLoading(crdtp::Dispatchable& dispatchable);
    void crash(crdtp::Dispatchable& dispatchable);
    void close(crdtp::Dispatchable& dispatchable);
    void setWebLifecycleState(crdtp::Dispatchable& dispatchable);
    void stopScreencast(crdtp::Dispatchable& dispatchable);
    void addCompilationCache(crdtp::Dispatchable& dispatchable);
    void setPrerenderingAllowed(crdtp::Dispatchable& dispatchable);
    void getAnnotatedPageContent(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("addCompilationCache"),
          &DomainDispatcherImpl::addCompilationCache
    },
    {
          crdtp::SpanFrom("addScriptToEvaluateOnLoad"),
          &DomainDispatcherImpl::addScriptToEvaluateOnLoad
    },
    {
          crdtp::SpanFrom("addScriptToEvaluateOnNewDocument"),
          &DomainDispatcherImpl::addScriptToEvaluateOnNewDocument
    },
    {
          crdtp::SpanFrom("bringToFront"),
          &DomainDispatcherImpl::bringToFront
    },
    {
          crdtp::SpanFrom("captureScreenshot"),
          &DomainDispatcherImpl::captureScreenshot
    },
    {
          crdtp::SpanFrom("captureSnapshot"),
          &DomainDispatcherImpl::captureSnapshot
    },
    {
          crdtp::SpanFrom("close"),
          &DomainDispatcherImpl::close
    },
    {
          crdtp::SpanFrom("crash"),
          &DomainDispatcherImpl::crash
    },
    {
          crdtp::SpanFrom("disable"),
          &DomainDispatcherImpl::disable
    },
    {
          crdtp::SpanFrom("enable"),
          &DomainDispatcherImpl::enable
    },
    {
          crdtp::SpanFrom("getAnnotatedPageContent"),
          &DomainDispatcherImpl::getAnnotatedPageContent
    },
    {
          crdtp::SpanFrom("getAppId"),
          &DomainDispatcherImpl::getAppId
    },
    {
          crdtp::SpanFrom("getAppManifest"),
          &DomainDispatcherImpl::getAppManifest
    },
    {
          crdtp::SpanFrom("getInstallabilityErrors"),
          &DomainDispatcherImpl::getInstallabilityErrors
    },
    {
          crdtp::SpanFrom("getManifestIcons"),
          &DomainDispatcherImpl::getManifestIcons
    },
    {
          crdtp::SpanFrom("getNavigationHistory"),
          &DomainDispatcherImpl::getNavigationHistory
    },
    {
          crdtp::SpanFrom("handleJavaScriptDialog"),
          &DomainDispatcherImpl::handleJavaScriptDialog
    },
    {
          crdtp::SpanFrom("navigate"),
          &DomainDispatcherImpl::navigate
    },
    {
          crdtp::SpanFrom("navigateToHistoryEntry"),
          &DomainDispatcherImpl::navigateToHistoryEntry
    },
    {
          crdtp::SpanFrom("reload"),
          &DomainDispatcherImpl::reload
    },
    {
          crdtp::SpanFrom("removeScriptToEvaluateOnLoad"),
          &DomainDispatcherImpl::removeScriptToEvaluateOnLoad
    },
    {
          crdtp::SpanFrom("removeScriptToEvaluateOnNewDocument"),
          &DomainDispatcherImpl::removeScriptToEvaluateOnNewDocument
    },
    {
          crdtp::SpanFrom("resetNavigationHistory"),
          &DomainDispatcherImpl::resetNavigationHistory
    },
    {
          crdtp::SpanFrom("screencastFrameAck"),
          &DomainDispatcherImpl::screencastFrameAck
    },
    {
          crdtp::SpanFrom("setBypassCSP"),
          &DomainDispatcherImpl::setBypassCSP
    },
    {
          crdtp::SpanFrom("setDownloadBehavior"),
          &DomainDispatcherImpl::setDownloadBehavior
    },
    {
          crdtp::SpanFrom("setPrerenderingAllowed"),
          &DomainDispatcherImpl::setPrerenderingAllowed
    },
    {
          crdtp::SpanFrom("setWebLifecycleState"),
          &DomainDispatcherImpl::setWebLifecycleState
    },
    {
          crdtp::SpanFrom("startScreenRecording"),
          &DomainDispatcherImpl::startScreenRecording
    },
    {
          crdtp::SpanFrom("startScreencast"),
          &DomainDispatcherImpl::startScreencast
    },
    {
          crdtp::SpanFrom("stopLoading"),
          &DomainDispatcherImpl::stopLoading
    },
    {
          crdtp::SpanFrom("stopScreenRecording"),
          &DomainDispatcherImpl::stopScreenRecording
    },
    {
          crdtp::SpanFrom("stopScreencast"),
          &DomainDispatcherImpl::stopScreencast
    },
    };
    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 addScriptToEvaluateOnLoadParams : public crdtp::DeserializableProtocolObject<addScriptToEvaluateOnLoadParams> {
    String scriptSource;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(addScriptToEvaluateOnLoadParams)
    CRDTP_DESERIALIZE_FIELD("scriptSource", scriptSource),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct addScriptToEvaluateOnNewDocumentParams : public crdtp::DeserializableProtocolObject<addScriptToEvaluateOnNewDocumentParams> {
    String source;
    std::optional<String> worldName;
    std::optional<bool> includeCommandLineAPI;
    std::optional<bool> runImmediately;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(addScriptToEvaluateOnNewDocumentParams)
    CRDTP_DESERIALIZE_FIELD_OPT("includeCommandLineAPI", includeCommandLineAPI),
    CRDTP_DESERIALIZE_FIELD_OPT("runImmediately", runImmediately),
    CRDTP_DESERIALIZE_FIELD("source", source),
    CRDTP_DESERIALIZE_FIELD_OPT("worldName", worldName),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->AddScriptToEvaluateOnNewDocument(params.source, std::move(params.worldName), std::move(params.includeCommandLineAPI), std::move(params.runImmediately), &out_identifier);
    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("identifier"), out_identifier);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {


}  // namespace

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

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

class CaptureScreenshotCallbackImpl : public Backend::CaptureScreenshotCallback, public DomainDispatcher::Callback {
public:
    CaptureScreenshotCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.captureScreenshot")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct captureScreenshotParams : public crdtp::DeserializableProtocolObject<captureScreenshotParams> {
    std::optional<String> format;
    std::optional<int> quality;
    std::unique_ptr<protocol::Page::Viewport> clip;
    std::optional<bool> fromSurface;
    std::optional<bool> captureBeyondViewport;
    std::optional<bool> optimizeForSpeed;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(captureScreenshotParams)
    CRDTP_DESERIALIZE_FIELD_OPT("captureBeyondViewport", captureBeyondViewport),
    CRDTP_DESERIALIZE_FIELD_OPT("clip", clip),
    CRDTP_DESERIALIZE_FIELD_OPT("format", format),
    CRDTP_DESERIALIZE_FIELD_OPT("fromSurface", fromSurface),
    CRDTP_DESERIALIZE_FIELD_OPT("optimizeForSpeed", optimizeForSpeed),
    CRDTP_DESERIALIZE_FIELD_OPT("quality", quality),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->CaptureScreenshot(std::move(params.format), std::move(params.quality), std::move(params.clip), std::move(params.fromSurface), std::move(params.captureBeyondViewport), std::move(params.optimizeForSpeed), std::make_unique<CaptureScreenshotCallbackImpl>(weakPtr(), dispatchable));
}

class CaptureSnapshotCallbackImpl : public Backend::CaptureSnapshotCallback, public DomainDispatcher::Callback {
public:
    CaptureSnapshotCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.captureSnapshot")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

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

CRDTP_BEGIN_DESERIALIZER(captureSnapshotParams)
    CRDTP_DESERIALIZE_FIELD_OPT("format", format),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->CaptureSnapshot(std::move(params.format), std::make_unique<CaptureSnapshotCallbackImpl>(weakPtr(), dispatchable));
}

namespace {


}  // namespace

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

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

namespace {

struct enableParams : public crdtp::DeserializableProtocolObject<enableParams> {
    std::optional<bool> enableFileChooserOpenedEvent;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(enableParams)
    CRDTP_DESERIALIZE_FIELD_OPT("enableFileChooserOpenedEvent", enableFileChooserOpenedEvent),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class GetAppManifestCallbackImpl : public Backend::GetAppManifestCallback, public DomainDispatcher::Callback {
public:
    GetAppManifestCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getAppManifest")) { }

    void sendSuccess(const String& url, std::unique_ptr<protocol::Array<protocol::Page::AppManifestError>> errors, std::optional<String> data, std::unique_ptr<protocol::Page::AppManifestParsedProperties> parsed, std::unique_ptr<protocol::Page::WebAppManifest> manifest) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("url"), url);
        serializer.AddField(crdtp::MakeSpan("errors"), errors);
        serializer.AddField(crdtp::MakeSpan("data"), data);
        serializer.AddField(crdtp::MakeSpan("parsed"), parsed);
        serializer.AddField(crdtp::MakeSpan("manifest"), manifest);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

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

CRDTP_BEGIN_DESERIALIZER(getAppManifestParams)
    CRDTP_DESERIALIZE_FIELD_OPT("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GetAppManifest(std::move(params.manifestId), std::make_unique<GetAppManifestCallbackImpl>(weakPtr(), dispatchable));
}

class GetInstallabilityErrorsCallbackImpl : public Backend::GetInstallabilityErrorsCallback, public DomainDispatcher::Callback {
public:
    GetInstallabilityErrorsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getInstallabilityErrors")) { }

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

    m_backend->GetInstallabilityErrors(std::make_unique<GetInstallabilityErrorsCallbackImpl>(weakPtr(), dispatchable));
}

class GetManifestIconsCallbackImpl : public Backend::GetManifestIconsCallback, public DomainDispatcher::Callback {
public:
    GetManifestIconsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getManifestIcons")) { }

    void sendSuccess(std::optional<Binary> primaryIcon) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("primaryIcon"), primaryIcon);
        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::getManifestIcons(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetManifestIcons(std::make_unique<GetManifestIconsCallbackImpl>(weakPtr(), dispatchable));
}

class GetAppIdCallbackImpl : public Backend::GetAppIdCallback, public DomainDispatcher::Callback {
public:
    GetAppIdCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getAppId")) { }

    void sendSuccess(std::optional<String> appId, std::optional<String> recommendedId) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("appId"), appId);
        serializer.AddField(crdtp::MakeSpan("recommendedId"), recommendedId);
        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::getAppId(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetAppId(std::make_unique<GetAppIdCallbackImpl>(weakPtr(), dispatchable));
}

namespace {


}  // namespace

void DomainDispatcherImpl::getNavigationHistory(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    int out_currentIndex;
    std::unique_ptr<protocol::Array<protocol::Page::NavigationEntry>> out_entries;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetNavigationHistory(&out_currentIndex, &out_entries);
    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("currentIndex"), out_currentIndex);
          serializer.AddField(crdtp::MakeSpan("entries"), out_entries);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {


}  // namespace

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

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

namespace {

struct handleJavaScriptDialogParams : public crdtp::DeserializableProtocolObject<handleJavaScriptDialogParams> {
    bool accept;
    std::optional<String> promptText;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(handleJavaScriptDialogParams)
    CRDTP_DESERIALIZE_FIELD("accept", accept),
    CRDTP_DESERIALIZE_FIELD_OPT("promptText", promptText),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class NavigateCallbackImpl : public Backend::NavigateCallback, public DomainDispatcher::Callback {
public:
    NavigateCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.navigate")) { }

    void sendSuccess(const String& frameId, std::optional<String> loaderId, std::optional<String> errorText, std::optional<bool> isDownload) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("frameId"), frameId);
        serializer.AddField(crdtp::MakeSpan("loaderId"), loaderId);
        serializer.AddField(crdtp::MakeSpan("errorText"), errorText);
        serializer.AddField(crdtp::MakeSpan("isDownload"), isDownload);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct navigateParams : public crdtp::DeserializableProtocolObject<navigateParams> {
    String url;
    std::optional<String> referrer;
    std::optional<String> transitionType;
    std::optional<String> frameId;
    std::optional<String> referrerPolicy;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(navigateParams)
    CRDTP_DESERIALIZE_FIELD_OPT("frameId", frameId),
    CRDTP_DESERIALIZE_FIELD_OPT("referrer", referrer),
    CRDTP_DESERIALIZE_FIELD_OPT("referrerPolicy", referrerPolicy),
    CRDTP_DESERIALIZE_FIELD_OPT("transitionType", transitionType),
    CRDTP_DESERIALIZE_FIELD("url", url),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->Navigate(params.url, std::move(params.referrer), std::move(params.transitionType), std::move(params.frameId), std::move(params.referrerPolicy), std::make_unique<NavigateCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct navigateToHistoryEntryParams : public crdtp::DeserializableProtocolObject<navigateToHistoryEntryParams> {
    int entryId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(navigateToHistoryEntryParams)
    CRDTP_DESERIALIZE_FIELD("entryId", entryId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class ReloadCallbackImpl : public Backend::ReloadCallback, public DomainDispatcher::Callback {
public:
    ReloadCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.reload")) { }

    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 reloadParams : public crdtp::DeserializableProtocolObject<reloadParams> {
    std::optional<bool> ignoreCache;
    std::optional<String> scriptToEvaluateOnLoad;
    std::optional<String> loaderId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(reloadParams)
    CRDTP_DESERIALIZE_FIELD_OPT("ignoreCache", ignoreCache),
    CRDTP_DESERIALIZE_FIELD_OPT("loaderId", loaderId),
    CRDTP_DESERIALIZE_FIELD_OPT("scriptToEvaluateOnLoad", scriptToEvaluateOnLoad),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->Reload(std::move(params.ignoreCache), std::move(params.scriptToEvaluateOnLoad), std::move(params.loaderId), std::make_unique<ReloadCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct removeScriptToEvaluateOnLoadParams : public crdtp::DeserializableProtocolObject<removeScriptToEvaluateOnLoadParams> {
    String identifier;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(removeScriptToEvaluateOnLoadParams)
    CRDTP_DESERIALIZE_FIELD("identifier", identifier),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct removeScriptToEvaluateOnNewDocumentParams : public crdtp::DeserializableProtocolObject<removeScriptToEvaluateOnNewDocumentParams> {
    String identifier;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(removeScriptToEvaluateOnNewDocumentParams)
    CRDTP_DESERIALIZE_FIELD("identifier", identifier),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct screencastFrameAckParams : public crdtp::DeserializableProtocolObject<screencastFrameAckParams> {
    int sessionId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(screencastFrameAckParams)
    CRDTP_DESERIALIZE_FIELD("sessionId", sessionId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setBypassCSPParams : public crdtp::DeserializableProtocolObject<setBypassCSPParams> {
    bool enabled;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setBypassCSPParams)
    CRDTP_DESERIALIZE_FIELD("enabled", enabled),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

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

CRDTP_BEGIN_DESERIALIZER(setDownloadBehaviorParams)
    CRDTP_DESERIALIZE_FIELD("behavior", behavior),
    CRDTP_DESERIALIZE_FIELD_OPT("downloadPath", downloadPath),
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.downloadPath));
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

namespace {

struct startScreencastParams : public crdtp::DeserializableProtocolObject<startScreencastParams> {
    std::optional<String> format;
    std::optional<int> quality;
    std::optional<int> maxWidth;
    std::optional<int> maxHeight;
    std::optional<int> everyNthFrame;
    std::optional<int> maxFramesInFlight;
    std::optional<bool> sendLastFrame;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(startScreencastParams)
    CRDTP_DESERIALIZE_FIELD_OPT("everyNthFrame", everyNthFrame),
    CRDTP_DESERIALIZE_FIELD_OPT("format", format),
    CRDTP_DESERIALIZE_FIELD_OPT("maxFramesInFlight", maxFramesInFlight),
    CRDTP_DESERIALIZE_FIELD_OPT("maxHeight", maxHeight),
    CRDTP_DESERIALIZE_FIELD_OPT("maxWidth", maxWidth),
    CRDTP_DESERIALIZE_FIELD_OPT("quality", quality),
    CRDTP_DESERIALIZE_FIELD_OPT("sendLastFrame", sendLastFrame),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->StartScreencast(std::move(params.format), std::move(params.quality), std::move(params.maxWidth), std::move(params.maxHeight), std::move(params.everyNthFrame), std::move(params.maxFramesInFlight), std::move(params.sendLastFrame));
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

namespace {

struct startScreenRecordingParams : public crdtp::DeserializableProtocolObject<startScreenRecordingParams> {
    std::optional<bool> audio;
    std::optional<int> maxWidth;
    std::optional<int> maxHeight;
    std::optional<int> frameRate;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(startScreenRecordingParams)
    CRDTP_DESERIALIZE_FIELD_OPT("audio", audio),
    CRDTP_DESERIALIZE_FIELD_OPT("frameRate", frameRate),
    CRDTP_DESERIALIZE_FIELD_OPT("maxHeight", maxHeight),
    CRDTP_DESERIALIZE_FIELD_OPT("maxWidth", maxWidth),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->StartScreenRecording(std::move(params.audio), std::move(params.maxWidth), std::move(params.maxHeight), std::move(params.frameRate), &out_stream);
    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("stream"), out_stream);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

class StopScreenRecordingCallbackImpl : public Backend::StopScreenRecordingCallback, public DomainDispatcher::Callback {
public:
    StopScreenRecordingCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.stopScreenRecording")) { }

    void sendSuccess(const String& stream) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("stream"), stream);
        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::stopScreenRecording(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->StopScreenRecording(std::make_unique<StopScreenRecordingCallbackImpl>(weakPtr(), dispatchable));
}

namespace {


}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->StopLoading();
    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::close(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

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

namespace {

struct setWebLifecycleStateParams : public crdtp::DeserializableProtocolObject<setWebLifecycleStateParams> {
    String state;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setWebLifecycleStateParams)
    CRDTP_DESERIALIZE_FIELD("state", state),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {


}  // namespace

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

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

namespace {

struct addCompilationCacheParams : public crdtp::DeserializableProtocolObject<addCompilationCacheParams> {
    String url;
    Binary data;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(addCompilationCacheParams)
    CRDTP_DESERIALIZE_FIELD("data", data),
    CRDTP_DESERIALIZE_FIELD("url", url),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setPrerenderingAllowedParams : public crdtp::DeserializableProtocolObject<setPrerenderingAllowedParams> {
    bool isAllowed;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setPrerenderingAllowedParams)
    CRDTP_DESERIALIZE_FIELD("isAllowed", isAllowed),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class GetAnnotatedPageContentCallbackImpl : public Backend::GetAnnotatedPageContentCallback, public DomainDispatcher::Callback {
public:
    GetAnnotatedPageContentCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getAnnotatedPageContent")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct getAnnotatedPageContentParams : public crdtp::DeserializableProtocolObject<getAnnotatedPageContentParams> {
    std::optional<bool> includeActionableInformation;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getAnnotatedPageContentParams)
    CRDTP_DESERIALIZE_FIELD_OPT("includeActionableInformation", includeActionableInformation),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GetAnnotatedPageContent(std::move(params.includeActionableInformation), std::make_unique<GetAnnotatedPageContentCallbackImpl>(weakPtr(), dispatchable));
}

namespace {
// This helper method (with a static map of redirects) is used from Dispatcher::wire
// immediately below.
const std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>& SortedRedirects() {
  static auto* redirects = [](){
    auto* redirects = new std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>{
          { crdtp::SpanFrom("Page.clearDeviceMetricsOverride"), crdtp::SpanFrom("Emulation.clearDeviceMetricsOverride") },
          { crdtp::SpanFrom("Page.clearDeviceOrientationOverride"), crdtp::SpanFrom("DeviceOrientation.clearDeviceOrientationOverride") },
          { crdtp::SpanFrom("Page.clearGeolocationOverride"), crdtp::SpanFrom("Emulation.clearGeolocationOverride") },
          { crdtp::SpanFrom("Page.deleteCookie"), crdtp::SpanFrom("Network.deleteCookie") },
          { crdtp::SpanFrom("Page.setDeviceMetricsOverride"), crdtp::SpanFrom("Emulation.setDeviceMetricsOverride") },
          { crdtp::SpanFrom("Page.setDeviceOrientationOverride"), crdtp::SpanFrom("DeviceOrientation.setDeviceOrientationOverride") },
          { crdtp::SpanFrom("Page.setGeolocationOverride"), crdtp::SpanFrom("Emulation.setGeolocationOverride") },
          { crdtp::SpanFrom("Page.setTouchEmulationEnabled"), crdtp::SpanFrom("Emulation.setTouchEmulationEnabled") },
    };
    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("Page"), SortedRedirects(), std::move(dispatcher));
}

} // Page
} // namespace content
} // namespace protocol
