/*
 * Copyright (C) 2009-2020 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "InspectorDOMAgent.h"

#include "AXObjectCache.h"
#include "AccessibilityNodeObject.h"
#include "AddEventListenerOptions.h"
#include "Attr.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSParser.h"
#include "CSSPropertyNames.h"
#include "CSSPropertySourceData.h"
#include "CSSRule.h"
#include "CSSRuleList.h"
#include "CSSSelector.h"
#include "CSSSelectorList.h"
#include "CSSStyleRule.h"
#include "CSSStyleSheet.h"
#include "CharacterData.h"
#include "CommandLineAPIHost.h"
#include "ComposedTreeIterator.h"
#include "ContainerNode.h"
#include "Cookie.h"
#include "CookieJar.h"
#include "DOMEditor.h"
#include "DOMException.h"
#include "DOMPatchSupport.h"
#include "DOMWindow.h"
#include "DocumentInlines.h"
#include "DocumentType.h"
#include "Editing.h"
#include "Element.h"
#include "Event.h"
#include "EventListener.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "FullscreenManager.h"
#include "HTMLElement.h"
#include "HTMLFrameOwnerElement.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "HTMLScriptElement.h"
#include "HTMLStyleElement.h"
#include "HTMLTemplateElement.h"
#include "HTMLVideoElement.h"
#include "HitTestResult.h"
#include "InspectorCSSAgent.h"
#include "InspectorClient.h"
#include "InspectorController.h"
#include "InspectorHistory.h"
#include "InspectorNodeFinder.h"
#include "InspectorPageAgent.h"
#include "InstrumentingAgents.h"
#include "IntRect.h"
#include "JSDOMBindingSecurity.h"
#include "JSDOMWindowCustom.h"
#include "JSEventListener.h"
#include "JSNode.h"
#include "MutationEvent.h"
#include "Node.h"
#include "NodeList.h"
#include "Page.h"
#include "Pasteboard.h"
#include "PseudoElement.h"
#include "RenderGrid.h"
#include "RenderObject.h"
#include "RenderStyle.h"
#include "RenderStyleConstants.h"
#include "ScriptController.h"
#include "SelectorChecker.h"
#include "ShadowRoot.h"
#include "StaticNodeList.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
#include "StyleSheetList.h"
#include "Styleable.h"
#include "Text.h"
#include "TextNodeTraversal.h"
#include "Timer.h"
#include "VideoPlaybackQuality.h"
#include "WebInjectedScriptManager.h"
#include "XPathResult.h"
#include "markup.h"
#include <JavaScriptCore/IdentifiersFactory.h>
#include <JavaScriptCore/InjectedScript.h>
#include <JavaScriptCore/InjectedScriptManager.h>
#include <JavaScriptCore/InspectorDebuggerAgent.h>
#include <JavaScriptCore/JSCInlines.h>
#include <pal/crypto/CryptoDigest.h>
#include <wtf/Function.h>
#include <wtf/text/Base64.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringToIntegerConversion.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

using namespace Inspector;

using namespace HTMLNames;

static const size_t maxTextSize = 10000;
static const UChar ellipsisUChar[] = { 0x2026, 0 };

static std::optional<Color> parseColor(RefPtr<JSON::Object>&& colorObject)
{
    if (!colorObject)
        return std::nullopt;

    auto r = colorObject->getInteger(Protocol::DOM::RGBAColor::rKey);
    auto g = colorObject->getInteger(Protocol::DOM::RGBAColor::gKey);
    auto b = colorObject->getInteger(Protocol::DOM::RGBAColor::bKey);
    if (!r || !g || !b)
        return std::nullopt;

    auto a = colorObject->getDouble(Protocol::DOM::RGBAColor::aKey);
    if (!a)
        return { makeFromComponentsClamping<SRGBA<uint8_t>>(*r, *g, *b) };
    return { makeFromComponentsClampingExceptAlpha<SRGBA<uint8_t>>(*r, *g, *b, convertFloatAlphaTo<uint8_t>(*a)) };
}

static Color parseConfigColor(const String& fieldName, JSON::Object& configObject)
{
    return parseColor(configObject.getObject(fieldName)).value_or(Color::transparentBlack);
}

static bool parseQuad(Ref<JSON::Array>&& quadArray, FloatQuad* quad)
{
    const size_t coordinatesInQuad = 8;
    double coordinates[coordinatesInQuad];
    if (quadArray->length() != coordinatesInQuad)
        return false;
    for (size_t i = 0; i < coordinatesInQuad; ++i) {
        auto coordinate = quadArray->get(i)->asDouble();
        if (!coordinate)
            return false;
        coordinates[i] = *coordinate;
    }
    quad->setP1(FloatPoint(coordinates[0], coordinates[1]));
    quad->setP2(FloatPoint(coordinates[2], coordinates[3]));
    quad->setP3(FloatPoint(coordinates[4], coordinates[5]));
    quad->setP4(FloatPoint(coordinates[6], coordinates[7]));

    return true;
}

class RevalidateStyleAttributeTask {
    WTF_MAKE_FAST_ALLOCATED;
public:
    RevalidateStyleAttributeTask(InspectorDOMAgent*);
    void scheduleFor(Element*);
    void reset() { m_timer.stop(); }
    void timerFired();

private:
    InspectorDOMAgent* m_domAgent;
    Timer m_timer;
    HashSet<RefPtr<Element>> m_elements;
};

RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
    : m_domAgent(domAgent)
    , m_timer(*this, &RevalidateStyleAttributeTask::timerFired)
{
}

void RevalidateStyleAttributeTask::scheduleFor(Element* element)
{
    m_elements.add(element);
    if (!m_timer.isActive())
        m_timer.startOneShot(0_s);
}

void RevalidateStyleAttributeTask::timerFired()
{
    // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
    Vector<Element*> elements;
    for (auto& element : m_elements)
        elements.append(element.get());
    m_domAgent->styleAttributeInvalidated(elements);

    m_elements.clear();
}

class InspectableNode final : public CommandLineAPIHost::InspectableObject {
public:
    explicit InspectableNode(Node* node)
        : m_node(node)
    {
    }

    JSC::JSValue get(JSC::JSGlobalObject& state) final
    {
        return InspectorDOMAgent::nodeAsScriptValue(state, m_node.get());
    }
private:
    RefPtr<Node> m_node;
};

class EventFiredCallback final : public EventListener {
public:
    static Ref<EventFiredCallback> create(InspectorDOMAgent& domAgent)
    {
        return adoptRef(*new EventFiredCallback(domAgent));
    }

    bool operator==(const EventListener& other) const final
    {
        return this == &other;
    }

    void handleEvent(ScriptExecutionContext&, Event& event) final
    {
        if (!is<Node>(event.target()) || m_domAgent.m_dispatchedEvents.contains(&event))
            return;

        auto* node = downcast<Node>(event.target());
        auto nodeId = m_domAgent.pushNodePathToFrontend(node);
        if (!nodeId)
            return;

        m_domAgent.m_dispatchedEvents.add(&event);

        RefPtr<JSON::Object> data = JSON::Object::create();

#if ENABLE(FULLSCREEN_API)
        if (event.type() == eventNames().webkitfullscreenchangeEvent)
            data->setBoolean("enabled"_s, !!node->document().fullscreenManager().fullscreenElement());
#endif // ENABLE(FULLSCREEN_API)

        auto timestamp = m_domAgent.m_environment.executionStopwatch().elapsedTime().seconds();
        m_domAgent.m_frontendDispatcher->didFireEvent(nodeId, event.type(), timestamp, data->size() ? WTFMove(data) : nullptr);
    }

private:
    EventFiredCallback(InspectorDOMAgent& domAgent)
        : EventListener(EventListener::CPPEventListenerType)
        , m_domAgent(domAgent)
    {
    }

    InspectorDOMAgent& m_domAgent;
};

String InspectorDOMAgent::toErrorString(ExceptionCode ec)
{
    return ec ? String(DOMException::name(ec)) : emptyString();
}

String InspectorDOMAgent::toErrorString(Exception&& exception)
{
    return DOMException::name(exception.code());
}

InspectorDOMAgent::InspectorDOMAgent(PageAgentContext& context, InspectorOverlay* overlay)
    : InspectorAgentBase("DOM"_s, context)
    , m_injectedScriptManager(context.injectedScriptManager)
    , m_frontendDispatcher(makeUnique<Inspector::DOMFrontendDispatcher>(context.frontendRouter))
    , m_backendDispatcher(Inspector::DOMBackendDispatcher::create(context.backendDispatcher, this))
    , m_inspectedPage(context.inspectedPage)
    , m_overlay(overlay)
    , m_destroyedNodesTimer(*this, &InspectorDOMAgent::destroyedNodesTimerFired)
#if ENABLE(VIDEO)
    , m_mediaMetricsTimer(*this, &InspectorDOMAgent::mediaMetricsTimerFired)
#endif
{
}

InspectorDOMAgent::~InspectorDOMAgent() = default;

void InspectorDOMAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
{
    m_history = makeUnique<InspectorHistory>();
    m_domEditor = makeUnique<DOMEditor>(*m_history);

    m_instrumentingAgents.setPersistentDOMAgent(this);
    m_document = m_inspectedPage.mainFrame().document();

    // Force a layout so that we can collect additional information from the layout process.
    relayoutDocument();

#if ENABLE(VIDEO)
    if (m_document)
        addEventListenersToNode(*m_document);

    for (auto* mediaElement : HTMLMediaElement::allMediaElements())
        addEventListenersToNode(*mediaElement);
#endif
}

void InspectorDOMAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
{
    m_history.reset();
    m_domEditor.reset();
    m_nodeToFocus = nullptr;
    m_mousedOverNode = nullptr;
    m_inspectedNode = nullptr;

    Protocol::ErrorString ignored;
    setSearchingForNode(ignored, false, nullptr, false);
    hideHighlight();

    m_overlay->clearAllGridOverlays();
    m_overlay->clearAllFlexOverlays();

    m_instrumentingAgents.setPersistentDOMAgent(nullptr);
    m_documentRequested = false;
    reset();
}

Vector<Document*> InspectorDOMAgent::documents()
{
    Vector<Document*> result;
    for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
        Document* document = frame->document();
        if (!document)
            continue;
        result.append(document);
    }
    return result;
}

void InspectorDOMAgent::reset()
{
    if (m_history)
        m_history->reset();
    m_searchResults.clear();
    discardBindings();
    if (m_revalidateStyleAttrTask)
        m_revalidateStyleAttrTask->reset();
    m_document = nullptr;

    m_destroyedDetachedNodeIdentifiers.clear();
    m_destroyedAttachedNodeIdentifiers.clear();
    if (m_destroyedNodesTimer.isActive())
        m_destroyedNodesTimer.stop();
}

void InspectorDOMAgent::setDocument(Document* document)
{
    if (document == m_document.get())
        return;

    reset();

    m_document = document;

    // Force a layout so that we can collect additional information from the layout process.
    relayoutDocument();

    if (!m_documentRequested)
        return;

    // Immediately communicate null document or document that has finished loading.
    if (!document || !document->parsing())
        m_frontendDispatcher->documentUpdated();
}

void InspectorDOMAgent::relayoutDocument()
{
    if (!m_document)
        return;

    m_flexibleBoxRendererCachedItemsAtStartOfLine.clear();
    
    m_document->updateLayout();
}

Protocol::DOM::NodeId InspectorDOMAgent::bind(Node& node)
{
    return m_nodeToId.ensure(node, [&] {
        auto id = m_lastNodeId++;
        m_idToNode.set(id, node);
        return id;
    }).iterator->value;
}

void InspectorDOMAgent::unbind(Node& node)
{
    auto id = m_nodeToId.take(node);
    if (!id)
        return;

    m_idToNode.remove(id);

    if (node.isFrameOwnerElement()) {
        const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(&node);
        if (Document* contentDocument = frameOwner->contentDocument())
            unbind(*contentDocument);
    }

    if (is<Element>(node)) {
        Element& element = downcast<Element>(node);
        if (ShadowRoot* root = element.shadowRoot())
            unbind(*root);
        if (PseudoElement* beforeElement = element.beforePseudoElement())
            unbind(*beforeElement);
        if (PseudoElement* afterElement = element.afterPseudoElement())
            unbind(*afterElement);
    }

    if (auto* cssAgent = m_instrumentingAgents.enabledCSSAgent())
        cssAgent->didRemoveDOMNode(node, id);

    if (m_childrenRequested.remove(id)) {
        // FIXME: Would be better to do this iteratively rather than recursively.
        for (Node* child = innerFirstChild(&node); child; child = innerNextSibling(child))
            unbind(*child);
    }
}

Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
    Node* node = nodeForId(nodeId);
    if (!node) {
        errorString = "Missing node for given nodeId"_s;
        return nullptr;
    }
    return node;
}

Document* InspectorDOMAgent::assertDocument(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return nullptr;
    if (!is<Document>(node)) {
        errorString = "Node for given nodeId is not a document"_s;
        return nullptr;
    }
    return downcast<Document>(node);
}

Element* InspectorDOMAgent::assertElement(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return nullptr;
    if (!is<Element>(node)) {
        errorString = "Node for given nodeId is not an element"_s;
        return nullptr;
    }
    return downcast<Element>(node);
}

Node* InspectorDOMAgent::assertEditableNode(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return nullptr;
    if (node->isInUserAgentShadowTree() && !m_allowEditingUserAgentShadowTrees) {
        errorString = "Node for given nodeId is in a shadow tree"_s;
        return nullptr;
    }
    if (node->isPseudoElement()) {
        errorString = "Node for given nodeId is a pseudo-element"_s;
        return nullptr;
    }
    return node;
}

Element* InspectorDOMAgent::assertEditableElement(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId)
{
    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return nullptr;
    if (!is<Element>(node)) {
        errorString = "Node for given nodeId is not an element"_s;
        return nullptr;
    }
    return downcast<Element>(node);
}

Protocol::ErrorStringOr<Ref<Protocol::DOM::Node>> InspectorDOMAgent::getDocument()
{
    m_documentRequested = true;

    if (!m_document)
        return makeUnexpected("Internal error: missing document"_s);

    // Reset backend state.
    RefPtr<Document> document = m_document;
    reset();
    m_document = document;

    auto root = buildObjectForNode(m_document.get(), 2);

    if (m_nodeToFocus)
        focusNode();

    return root;
}

void InspectorDOMAgent::pushChildNodesToFrontend(Protocol::DOM::NodeId nodeId, int depth)
{
    Node* node = nodeForId(nodeId);
    if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
        return;

    if (m_childrenRequested.contains(nodeId)) {
        if (depth <= 1)
            return;

        depth--;

        for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
            auto childNodeId = boundNodeId(node);
            ASSERT(childNodeId);
            pushChildNodesToFrontend(childNodeId, depth);
        }

        return;
    }

    auto children = buildArrayForContainerChildren(node, depth);
    m_frontendDispatcher->setChildNodes(nodeId, WTFMove(children));
}

void InspectorDOMAgent::discardBindings()
{
    m_nodeToId.clear();
    m_idToNode.clear();
    m_dispatchedEvents.clear();
    m_eventListenerEntries.clear();
    m_childrenRequested.clear();
}

static Element* elementToPushForStyleable(const Styleable& styleable)
{
    // FIXME: We want to get rid of PseudoElement.
    auto* element = &styleable.element;

    if (styleable.pseudoId == PseudoId::Before)
        element = element->beforePseudoElement();
    else if (styleable.pseudoId == PseudoId::After)
        element = element->afterPseudoElement();

    return element;
}

Protocol::DOM::NodeId InspectorDOMAgent::pushStyleableElementToFrontend(const Styleable& styleable)
{
    auto* element = elementToPushForStyleable(styleable);
    return pushNodeToFrontend(element ? element : &styleable.element);
}

Protocol::DOM::NodeId InspectorDOMAgent::pushNodeToFrontend(Node* nodeToPush)
{
    if (!nodeToPush)
        return 0;

    // FIXME: <https://webkit.org/b/213499> Web Inspector: allow DOM nodes to be instrumented at any point, regardless of whether the main document has also been instrumented

    Protocol::ErrorString ignored;
    return pushNodeToFrontend(ignored, boundNodeId(&nodeToPush->document()), nodeToPush);
}

Protocol::DOM::NodeId InspectorDOMAgent::pushNodeToFrontend(Protocol::ErrorString& errorString, Protocol::DOM::NodeId documentNodeId, Node* nodeToPush)
{
    Document* document = assertDocument(errorString, documentNodeId);
    if (!document)
        return 0;
    if (&nodeToPush->document() != document) {
        errorString = "nodeToPush is not part of the document with given documentNodeId"_s;
        return 0;
    }

    return pushNodePathToFrontend(errorString, nodeToPush);
}

Node* InspectorDOMAgent::nodeForId(Protocol::DOM::NodeId id)
{
    if (!m_idToNode.isValidKey(id))
        return nullptr;

    return m_idToNode.get(id).get();
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::requestChildNodes(Protocol::DOM::NodeId nodeId, std::optional<int>&& depth)
{
    int sanitizedDepth;

    if (!depth)
        sanitizedDepth = 1;
    else if (*depth == -1)
        sanitizedDepth = INT_MAX;
    else if (*depth > 0)
        sanitizedDepth = *depth;
    else
        return makeUnexpected("Unexpected value below -1 for given depth"_s);

    pushChildNodesToFrontend(nodeId, sanitizedDepth);

    return { };
}

Protocol::ErrorStringOr<std::optional<Protocol::DOM::NodeId>> InspectorDOMAgent::querySelector(Protocol::DOM::NodeId nodeId, const String& selector)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);
    if (!is<ContainerNode>(*node))
        return makeUnexpected("Node for given nodeId is not a container node"_s);

    auto queryResult = downcast<ContainerNode>(*node).querySelector(selector);
    if (queryResult.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(queryResult.releaseException()));

    auto* queryResultNode = queryResult.releaseReturnValue();
    if (!queryResultNode)
        return { };

    auto resultNodeId = pushNodePathToFrontend(errorString, queryResultNode);
    if (!resultNodeId)
        return makeUnexpected(errorString);

    return { resultNodeId };
}

Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::DOM::NodeId>>> InspectorDOMAgent::querySelectorAll(Protocol::DOM::NodeId nodeId, const String& selector)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);
    if (!is<ContainerNode>(*node))
        return makeUnexpected("Node for given nodeId is not a container node"_s);

    auto queryResult = downcast<ContainerNode>(*node).querySelectorAll(selector);
    if (queryResult.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(queryResult.releaseException()));

    auto nodes = queryResult.releaseReturnValue();

    auto nodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
    for (unsigned i = 0; i < nodes->length(); ++i)
        nodeIds->addItem(pushNodePathToFrontend(nodes->item(i)));
    return nodeIds;
}

Protocol::DOM::NodeId InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
{
    Protocol::ErrorString ignored;
    return pushNodePathToFrontend(ignored, nodeToPush);
}

Ref<Protocol::DOM::Styleable> InspectorDOMAgent::pushStyleablePathToFrontend(Protocol::ErrorString errorString, const Styleable& styleable)
{
    auto* element = elementToPushForStyleable(styleable);
    auto nodeId = pushNodePathToFrontend(errorString, element ? element : &styleable.element);

    auto protocolStyleable = Protocol::DOM::Styleable::create()
        .setNodeId(nodeId)
        .release();

    if (styleable.pseudoId != PseudoId::None) {
        if (auto pseudoId = InspectorCSSAgent::protocolValueForPseudoId(styleable.pseudoId))
            protocolStyleable->setPseudoId(*pseudoId);
    }

    return protocolStyleable;
}

Protocol::DOM::NodeId InspectorDOMAgent::pushNodePathToFrontend(Protocol::ErrorString errorString, Node* nodeToPush)
{
    ASSERT(nodeToPush);  // Invalid input

    if (!m_document) {
        errorString = "Missing document"_s;
        return 0;
    }

    // FIXME: <https://webkit.org/b/213499> Web Inspector: allow DOM nodes to be instrumented at any point, regardless of whether the main document has also been instrumented
    if (!m_nodeToId.contains(*m_document)) {
        errorString = "Document must have been requested"_s;
        return 0;
    }

    // Return id in case the node is known.
    if (auto result = boundNodeId(nodeToPush))
        return result;

    Node* node = nodeToPush;
    Vector<Node*> path;

    while (true) {
        Node* parent = innerParentNode(node);
        if (!parent) {
            // Node being pushed is detached -> push subtree root.
            auto children = JSON::ArrayOf<Protocol::DOM::Node>::create();
            children->addItem(buildObjectForNode(node, 0));
            m_frontendDispatcher->setChildNodes(0, WTFMove(children));
            break;
        } else {
            path.append(parent);
            if (boundNodeId(parent))
                break;
            node = parent;
        }
    }

    for (int i = path.size() - 1; i >= 0; --i) {
        auto nodeId = boundNodeId(path.at(i));
        ASSERT(nodeId);
        pushChildNodesToFrontend(nodeId);
    }
    return boundNodeId(nodeToPush);
}

Protocol::DOM::NodeId InspectorDOMAgent::boundNodeId(const Node* node)
{
    if (!node)
        return 0;

    return m_nodeToId.get(*node);
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setAttributeValue(Protocol::DOM::NodeId nodeId, const String& name, const String& value)
{
    Protocol::ErrorString errorString;

    Element* element = assertEditableElement(errorString, nodeId);
    if (!element)
        return makeUnexpected(errorString);

    if (!m_domEditor->setAttribute(*element, AtomString { name }, AtomString { value }, errorString))
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setAttributesAsText(Protocol::DOM::NodeId nodeId, const String& text, const String& name)
{
    Protocol::ErrorString errorString;

    Element* element = assertEditableElement(errorString, nodeId);
    if (!element)
        return makeUnexpected(errorString);

    auto parsedElement = createHTMLElement(element->document(), spanTag);
    auto result = parsedElement.get().setInnerHTML("<span " + text + "></span>");
    if (result.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(result.releaseException()));

    Node* child = parsedElement->firstChild();
    if (!child)
        return makeUnexpected("Could not parse given text"_s);

    Element* childElement = downcast<Element>(child);
    if (!childElement->hasAttributes() && !!name) {
        if (!m_domEditor->removeAttribute(*element, AtomString { name }, errorString))
            return makeUnexpected(errorString);
        return { };
    }

    bool foundOriginalAttribute = false;
    for (const Attribute& attribute : childElement->attributesIterator()) {
        // Add attribute pair
        auto attributeName = attribute.name().toAtomString();
        foundOriginalAttribute = foundOriginalAttribute || attributeName == name;
        if (!m_domEditor->setAttribute(*element, attributeName, attribute.value(), errorString))
            return makeUnexpected(errorString);
    }

    if (!foundOriginalAttribute && name.find(isNotSpaceOrNewline) != notFound) {
        if (!m_domEditor->removeAttribute(*element, AtomString { name }, errorString))
            return makeUnexpected(errorString);
    }

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::removeAttribute(Protocol::DOM::NodeId nodeId, const String& name)
{
    Protocol::ErrorString errorString;

    Element* element = assertEditableElement(errorString, nodeId);
    if (!element)
        return makeUnexpected(errorString);

    if (!m_domEditor->removeAttribute(*element, AtomString { name }, errorString))
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::removeNode(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    ContainerNode* parentNode = node->parentNode();
    if (!parentNode)
        return makeUnexpected("Cannot remove detached node"_s);

    if (!m_domEditor->removeChild(*parentNode, *node, errorString))
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::setNodeName(Protocol::DOM::NodeId nodeId, const String& tagName)
{
    Protocol::ErrorString errorString;

    auto oldNode = assertElement(errorString, nodeId);
    if (!oldNode)
        return makeUnexpected(errorString);

    auto createElementResult = oldNode->document().createElementForBindings(AtomString { tagName });
    if (createElementResult.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(createElementResult.releaseException()));

    auto newElement = createElementResult.releaseReturnValue();

    // Copy over the original node's attributes.
    newElement->cloneAttributesFromElement(*oldNode);

    // Copy over the original node's children.
    RefPtr<Node> child;
    while ((child = oldNode->firstChild())) {
        if (!m_domEditor->insertBefore(newElement, *child, 0, errorString))
            return makeUnexpected(errorString);
    }

    // Replace the old node with the new node
    RefPtr<ContainerNode> parent = oldNode->parentNode();
    if (!m_domEditor->insertBefore(*parent, newElement.copyRef(), oldNode->nextSibling(), errorString))
        return makeUnexpected(errorString);
    if (!m_domEditor->removeChild(*parent, *oldNode, errorString))
        return makeUnexpected(errorString);

    auto resultNodeId = pushNodePathToFrontend(errorString, newElement.ptr());
    if (m_childrenRequested.contains(nodeId))
        pushChildNodesToFrontend(resultNodeId);

    return resultNodeId;
}

Protocol::ErrorStringOr<String> InspectorDOMAgent::getOuterHTML(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    return serializeFragment(*node, SerializedNodes::SubtreeIncludingNode);
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setOuterHTML(Protocol::DOM::NodeId nodeId, const String& outerHTML)
{
    Protocol::ErrorString errorString;

    if (!nodeId) {
        DOMPatchSupport { *m_domEditor, *m_document }.patchDocument(outerHTML);
        return { };
    }

    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    Document& document = node->document();
    if (!document.isHTMLDocument() && !document.isXMLDocument())
        return makeUnexpected("Document of node for given nodeId is not HTML/XML"_s);

    Node* newNode = nullptr;
    if (!m_domEditor->setOuterHTML(*node, outerHTML, newNode, errorString))
        return makeUnexpected(errorString);

    if (!newNode) {
        // The only child node has been deleted.
        return { };
    }

    auto newId = pushNodePathToFrontend(errorString, newNode);

    bool childrenRequested = m_childrenRequested.contains(nodeId);
    if (childrenRequested)
        pushChildNodesToFrontend(newId);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::insertAdjacentHTML(Protocol::DOM::NodeId nodeId, const String& position, const String& html)
{
    Protocol::ErrorString errorString;

    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    if (!is<Element>(node))
        return makeUnexpected("Node for given nodeId is not an element"_s);

    if (!m_domEditor->insertAdjacentHTML(downcast<Element>(*node), position, html, errorString))
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setNodeValue(Protocol::DOM::NodeId nodeId, const String& value)
{
    Protocol::ErrorString errorString;

    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    if (!is<Text>(*node))
        return makeUnexpected("Node for given nodeId is not text"_s);

    if (!m_domEditor->replaceWholeText(downcast<Text>(*node), value, errorString))
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<Ref<JSON::ArrayOf<String>>> InspectorDOMAgent::getSupportedEventNames()
{
    auto eventNames = JSON::ArrayOf<String>::create();

#define DOM_EVENT_NAMES_ADD(name) eventNames->addItem(#name""_s);
    DOM_EVENT_NAMES_FOR_EACH(DOM_EVENT_NAMES_ADD)
#undef DOM_EVENT_NAMES_ADD

    return eventNames;
}

#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::DOM::DataBinding>>> InspectorDOMAgent::getDataBindingsForNode(Protocol::DOM::NodeId)
{
    return makeUnexpected("Not supported"_s);
}

Protocol::ErrorStringOr<String> InspectorDOMAgent::getAssociatedDataForNode(Protocol::DOM::NodeId)
{
    return makeUnexpected("Not supported"_s);
}
#endif

Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::DOM::EventListener>>> InspectorDOMAgent::getEventListenersForNode(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    auto* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    Vector<RefPtr<EventTarget>> ancestors;
    ancestors.append(node);
    for (auto* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
        ancestors.append(ancestor);
    if (auto* window = node->document().domWindow())
        ancestors.append(window);

    struct EventListenerInfo {
        RefPtr<EventTarget> eventTarget;
        const AtomString eventType;
        const EventListenerVector eventListeners;
    };

    Vector<EventListenerInfo> eventInformation;
    for (size_t i = ancestors.size(); i; --i) {
        auto& ancestor = ancestors[i - 1];
        for (auto& eventType : ancestor->eventTypes()) {
            EventListenerVector filteredListeners;
            for (auto& listener : ancestor->eventListeners(eventType)) {
                if (listener->callback().type() == EventListener::JSEventListenerType)
                    filteredListeners.append(listener);
            }
            if (!filteredListeners.isEmpty())
                eventInformation.append({ ancestor, eventType, WTFMove(filteredListeners) });
        }
    }

    auto listeners = JSON::ArrayOf<Protocol::DOM::EventListener>::create();

    auto addListener = [&] (RegisteredEventListener& listener, const EventListenerInfo& info) {
        Protocol::DOM::EventListenerId identifier = 0;
        bool disabled = false;
        RefPtr<JSC::Breakpoint> breakpoint;

        for (auto& inspectorEventListener : m_eventListenerEntries.values()) {
            if (inspectorEventListener.matches(*info.eventTarget, info.eventType, listener.callback(), listener.useCapture())) {
                identifier = inspectorEventListener.identifier;
                disabled = inspectorEventListener.disabled;
                breakpoint = inspectorEventListener.breakpoint;
                break;
            }
        }

        if (!identifier) {
            InspectorEventListener inspectorEventListener(m_lastEventListenerId++, *info.eventTarget, info.eventType, listener.callback(), listener.useCapture());

            identifier = inspectorEventListener.identifier;
            disabled = inspectorEventListener.disabled;
            breakpoint = inspectorEventListener.breakpoint;

            m_eventListenerEntries.add(identifier, inspectorEventListener);
        }

        listeners->addItem(buildObjectForEventListener(listener, identifier, *info.eventTarget, info.eventType, disabled, breakpoint));
    };

    // Get Capturing Listeners (in this order)
    size_t eventInformationLength = eventInformation.size();
    for (auto& info : eventInformation) {
        for (auto& listener : info.eventListeners) {
            if (listener->useCapture())
                addListener(*listener, info);
        }
    }

    // Get Bubbling Listeners (reverse order)
    for (size_t i = eventInformationLength; i; --i) {
        const EventListenerInfo& info = eventInformation[i - 1];
        for (auto& listener : info.eventListeners) {
            if (!listener->useCapture())
                addListener(*listener, info);
        }
    }

    if (m_inspectedNode == node)
        m_suppressEventListenerChangedEvent = false;

    return listeners;
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setEventListenerDisabled(Protocol::DOM::EventListenerId eventListenerId, bool disabled)
{
    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end())
        return makeUnexpected("Missing event listener for given eventListenerId"_s);

    it->value.disabled = disabled;

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setBreakpointForEventListener(Protocol::DOM::EventListenerId eventListenerId, RefPtr<JSON::Object>&& options)
{
    Protocol::ErrorString errorString;

    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end())
        return makeUnexpected("Missing event listener for given eventListenerId"_s);

    if (it->value.breakpoint)
        return makeUnexpected("Breakpoint for given eventListenerId already exists"_s);

    it->value.breakpoint = InspectorDebuggerAgent::debuggerBreakpointFromPayload(errorString, WTFMove(options));
    if (!it->value.breakpoint)
        return makeUnexpected(errorString);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::removeBreakpointForEventListener(Protocol::DOM::EventListenerId eventListenerId)
{
    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end())
        return makeUnexpected("Missing event listener for given eventListenerId"_s);

    if (!it->value.breakpoint)
        return makeUnexpected("Breakpoint for given eventListenerId missing"_s);

    it->value.breakpoint = nullptr;

    return { };
}

Protocol::ErrorStringOr<Ref<Protocol::DOM::AccessibilityProperties>> InspectorDOMAgent::getAccessibilityPropertiesForNode(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    return buildObjectForAccessibilityProperties(*node);
}

Protocol::ErrorStringOr<std::tuple<String /* searchId */, int /* resultCount */>> InspectorDOMAgent::performSearch(const String& query, RefPtr<JSON::Array>&& nodeIds, std::optional<bool>&& caseSensitive)
{
    Protocol::ErrorString errorString;

    // FIXME: Search works with node granularity - number of matches within node is not calculated.
    InspectorNodeFinder finder(query, caseSensitive && *caseSensitive);

    if (nodeIds) {
        for (auto& nodeValue : *nodeIds) {
            auto nodeId = nodeValue->asInteger();
            if (!nodeId)
                return makeUnexpected("Unexpected non-integer item in given nodeIds"_s);

            Node* node = assertNode(errorString, *nodeId);
            if (!node)
                return makeUnexpected(errorString);

            finder.performSearch(node);
        }
    } else {
        // There's no need to iterate the frames tree because
        // the search helper will go inside the frame owner elements.
        finder.performSearch(m_document.get());
    }

    auto searchId = IdentifiersFactory::createIdentifier();

    auto& resultsVector = m_searchResults.add(searchId, Vector<RefPtr<Node>>()).iterator->value;
    for (auto& result : finder.results())
        resultsVector.append(result);

    return { { searchId, resultsVector.size() } };
}

Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::DOM::NodeId>>> InspectorDOMAgent::getSearchResults(const String& searchId, int fromIndex, int toIndex)
{
    SearchResults::iterator it = m_searchResults.find(searchId);
    if (it == m_searchResults.end())
        return makeUnexpected("Missing search result for given searchId"_s);

    int size = it->value.size();
    if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex)
        return makeUnexpected("Invalid search result range for given fromIndex and toIndex"_s);

    auto nodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
    for (int i = fromIndex; i < toIndex; ++i)
        nodeIds->addItem(pushNodePathToFrontend((it->value)[i].get()));
    return nodeIds;
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::discardSearchResults(const String& searchId)
{
    m_searchResults.remove(searchId);

    return { };
}

bool InspectorDOMAgent::handleMousePress()
{
    if (!m_searchingForNode)
        return false;

    if (Node* node = m_overlay->highlightedNode()) {
        inspect(node);
        return true;
    }
    return false;
}

bool InspectorDOMAgent::handleTouchEvent(Node& node)
{
    if (!m_searchingForNode)
        return false;
    if (m_inspectModeHighlightConfig) {
        m_overlay->highlightNode(&node, *m_inspectModeHighlightConfig);
        inspect(&node);
        return true;
    }
    return false;
}

void InspectorDOMAgent::inspect(Node* inspectedNode)
{
    Protocol::ErrorString ignored;
    RefPtr<Node> node = inspectedNode;
    setSearchingForNode(ignored, false, nullptr, false);

    if (!node->isElementNode() && !node->isDocumentNode())
        node = node->parentNode();
    m_nodeToFocus = node;

    if (!m_nodeToFocus)
        return;

    focusNode();
}

void InspectorDOMAgent::focusNode()
{
    // FIXME: <https://webkit.org/b/213499> Web Inspector: allow DOM nodes to be instrumented at any point, regardless of whether the main document has also been instrumented
    if (!m_documentRequested)
        return;

    ASSERT(m_nodeToFocus);
    auto node = std::exchange(m_nodeToFocus, nullptr);
    auto frame = node->document().frame();
    if (!frame)
        return;

    auto& globalObject = mainWorldGlobalObject(*frame);
    auto injectedScript = m_injectedScriptManager.injectedScriptFor(&globalObject);
    if (injectedScript.hasNoValue())
        return;

    injectedScript.inspectObject(nodeAsScriptValue(globalObject, node.get()));
}

void InspectorDOMAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
{
    m_mousedOverNode = result.innerNode();

    if (!m_searchingForNode)
        return;

    highlightMousedOverNode();
}

void InspectorDOMAgent::highlightMousedOverNode()
{
    Node* node = m_mousedOverNode.get();
    if (node && node->isTextNode())
        node = node->parentNode();
    if (node && m_inspectModeHighlightConfig)
        m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
}

void InspectorDOMAgent::setSearchingForNode(Protocol::ErrorString& errorString, bool enabled, RefPtr<JSON::Object>&& highlightInspectorObject, bool showRulers)
{
    if (m_searchingForNode == enabled)
        return;

    m_searchingForNode = enabled;

    m_overlay->setShowRulersDuringElementSelection(m_searchingForNode && showRulers);

    if (m_searchingForNode) {
        m_inspectModeHighlightConfig = highlightConfigFromInspectorObject(errorString, WTFMove(highlightInspectorObject));
        if (!m_inspectModeHighlightConfig)
            return;
        highlightMousedOverNode();
    } else
        hideHighlight();

    m_overlay->didSetSearchingForNode(m_searchingForNode);

    if (InspectorClient* client = m_inspectedPage.inspectorController().inspectorClient())
        client->elementSelectionChanged(m_searchingForNode);
}

std::unique_ptr<InspectorOverlay::Highlight::Config> InspectorDOMAgent::highlightConfigFromInspectorObject(Protocol::ErrorString& errorString, RefPtr<JSON::Object>&& highlightInspectorObject)
{
    if (!highlightInspectorObject) {
        errorString = "Internal error: highlight configuration parameter is missing"_s;
        return nullptr;
    }

    auto highlightConfig = makeUnique<InspectorOverlay::Highlight::Config>();
    highlightConfig->showInfo = highlightInspectorObject->getBoolean(Protocol::DOM::HighlightConfig::showInfoKey).value_or(false);
    highlightConfig->content = parseConfigColor(Protocol::DOM::HighlightConfig::contentColorKey, *highlightInspectorObject);
    highlightConfig->padding = parseConfigColor(Protocol::DOM::HighlightConfig::paddingColorKey, *highlightInspectorObject);
    highlightConfig->border = parseConfigColor(Protocol::DOM::HighlightConfig::borderColorKey, *highlightInspectorObject);
    highlightConfig->margin = parseConfigColor(Protocol::DOM::HighlightConfig::marginColorKey, *highlightInspectorObject);
    return highlightConfig;
}

#if PLATFORM(IOS_FAMILY)
Protocol::ErrorStringOr<void> InspectorDOMAgent::setInspectModeEnabled(bool enabled, RefPtr<JSON::Object>&& highlightConfig)
{
    Protocol::ErrorString errorString;

    setSearchingForNode(errorString, enabled, WTFMove(highlightConfig), false);

    if (!!errorString)
        return makeUnexpected(errorString);

    return { };
}
#else
Protocol::ErrorStringOr<void> InspectorDOMAgent::setInspectModeEnabled(bool enabled, RefPtr<JSON::Object>&& highlightConfig, std::optional<bool>&& showRulers)
{
    Protocol::ErrorString errorString;

    setSearchingForNode(errorString, enabled, WTFMove(highlightConfig), showRulers && *showRulers);

    if (!!errorString)
        return makeUnexpected(errorString);

    return { };
}
#endif

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightRect(int x, int y, int width, int height, RefPtr<JSON::Object>&& color, RefPtr<JSON::Object>&& outlineColor, std::optional<bool>&& usePageCoordinates)
{
    auto quad = makeUnique<FloatQuad>(FloatRect(x, y, width, height));
    innerHighlightQuad(WTFMove(quad), WTFMove(color), WTFMove(outlineColor), WTFMove(usePageCoordinates));

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightQuad(Ref<JSON::Array>&& quadObject, RefPtr<JSON::Object>&& color, RefPtr<JSON::Object>&& outlineColor, std::optional<bool>&& usePageCoordinates)
{
    auto quad = makeUnique<FloatQuad>();
    if (!parseQuad(WTFMove(quadObject), quad.get()))
        return makeUnexpected("Unexpected invalid quad"_s);

    innerHighlightQuad(WTFMove(quad), WTFMove(color), WTFMove(outlineColor), WTFMove(usePageCoordinates));

    return { };
}

void InspectorDOMAgent::innerHighlightQuad(std::unique_ptr<FloatQuad> quad, RefPtr<JSON::Object>&& color, RefPtr<JSON::Object>&& outlineColor, std::optional<bool>&& usePageCoordinates)
{
    auto highlightConfig = makeUnique<InspectorOverlay::Highlight::Config>();
    highlightConfig->content = parseColor(WTFMove(color)).value_or(Color::transparentBlack);
    highlightConfig->contentOutline = parseColor(WTFMove(outlineColor)).value_or(Color::transparentBlack);
    highlightConfig->usePageCoordinates = usePageCoordinates ? *usePageCoordinates : false;
    m_overlay->highlightQuad(WTFMove(quad), *highlightConfig);
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightSelector(Ref<JSON::Object>&& highlightInspectorObject, const String& selectorString, const Protocol::Network::FrameId& frameId)
{
    Protocol::ErrorString errorString;

    auto highlightConfig = highlightConfigFromInspectorObject(errorString, WTFMove(highlightInspectorObject));
    if (!highlightConfig)
        return makeUnexpected(errorString);

    RefPtr<Document> document;

    if (!!frameId) {
        auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
        if (!pageAgent)
            return makeUnexpected("Page domain must be enabled"_s);

        auto* frame = pageAgent->assertFrame(errorString, frameId);
        if (!frame)
            return makeUnexpected(errorString);

        document = frame->document();
    } else
        document = m_document;

    if (!document)
        return makeUnexpected("Missing document of frame for given frameId"_s);

    CSSParser parser(*document);
    auto selectorList = parser.parseSelector(selectorString);
    if (!selectorList)
        return { };

    SelectorChecker selectorChecker(*document);

    Vector<Ref<Node>> nodeList;
    HashSet<Ref<Node>> seenNodes;

    for (auto& descendant : composedTreeDescendants(*document)) {
        if (!is<Element>(descendant))
            continue;

        auto& descendantElement = downcast<Element>(descendant);

        auto isInUserAgentShadowTree = descendantElement.isInUserAgentShadowTree();
        auto pseudoId = descendantElement.pseudoId();
        auto& pseudo = descendantElement.pseudo();

        for (const auto* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
            if (isInUserAgentShadowTree && (selector->match() != CSSSelector::PseudoElement || selector->value() != pseudo))
                continue;

            SelectorChecker::CheckingContext context(SelectorChecker::Mode::ResolvingStyle);
            context.pseudoId = pseudoId;

            if (selectorChecker.match(*selector, descendantElement, context)) {
                if (seenNodes.add(descendantElement))
                    nodeList.append(descendantElement);
            }

            if (context.pseudoIDSet) {
                auto pseudoIDs = PseudoIdSet::fromMask(context.pseudoIDSet.data());

                if (pseudoIDs.has(PseudoId::Before)) {
                    pseudoIDs.remove(PseudoId::Before);
                    if (auto* beforePseudoElement = descendantElement.beforePseudoElement()) {
                        if (seenNodes.add(*beforePseudoElement))
                            nodeList.append(*beforePseudoElement);
                    }
                }

                if (pseudoIDs.has(PseudoId::After)) {
                    pseudoIDs.remove(PseudoId::After);
                    if (auto* afterPseudoElement = descendantElement.afterPseudoElement()) {
                        if (seenNodes.add(*afterPseudoElement))
                            nodeList.append(*afterPseudoElement);
                    }
                }

                if (pseudoIDs) {
                    if (seenNodes.add(descendantElement))
                        nodeList.append(descendantElement);
                }
            }
        }
    }

    m_overlay->highlightNodeList(StaticNodeList::create(WTFMove(nodeList)), *highlightConfig);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightNode(Ref<JSON::Object>&& highlightInspectorObject, std::optional<Protocol::DOM::NodeId>&& nodeId, const Protocol::Runtime::RemoteObjectId& objectId)
{
    Protocol::ErrorString errorString;

    Node* node = nullptr;
    if (nodeId)
        node = assertNode(errorString, *nodeId);
    else if (!!objectId) {
        node = nodeForObjectId(objectId);
        errorString = "Missing node for given objectId"_s;
    } else
        errorString = "Either nodeId or objectId must be specified"_s;

    if (!node)
        return makeUnexpected(errorString);

    std::unique_ptr<InspectorOverlay::Highlight::Config> highlightConfig = highlightConfigFromInspectorObject(errorString, WTFMove(highlightInspectorObject));
    if (!highlightConfig)
        return makeUnexpected(errorString);

    m_overlay->highlightNode(node, *highlightConfig);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightNodeList(Ref<JSON::Array>&& nodeIds, Ref<JSON::Object>&& highlightInspectorObject)
{
    Protocol::ErrorString errorString;

    Vector<Ref<Node>> nodes;
    for (auto& nodeIdValue : nodeIds.get()) {
        auto nodeId = nodeIdValue->asInteger();
        if (!nodeId)
            return makeUnexpected("Unexpected non-integer item in given nodeIds"_s);

        // In the case that a node is removed in the time between when highlightNodeList is invoked
        // by the frontend and it is executed by the backend, we should still attempt to highlight
        // as many nodes as possible. As such, we should ignore any errors generated when attempting
        // to get a Node from a given nodeId. 
        Protocol::ErrorString ignored;
        Node* node = assertNode(ignored, *nodeId);
        if (!node)
            continue;

        nodes.append(*node);
    }

    std::unique_ptr<InspectorOverlay::Highlight::Config> highlightConfig = highlightConfigFromInspectorObject(errorString, WTFMove(highlightInspectorObject));
    if (!highlightConfig)
        return makeUnexpected(errorString);

    m_overlay->highlightNodeList(StaticNodeList::create(WTFMove(nodes)), *highlightConfig);

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::highlightFrame(const Protocol::Network::FrameId& frameId, RefPtr<JSON::Object>&& color, RefPtr<JSON::Object>&& outlineColor)
{
    Protocol::ErrorString errorString;

    auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
    if (!pageAgent)
        return makeUnexpected("Page domain must be enabled"_s);

    auto* frame = pageAgent->assertFrame(errorString, frameId);
    if (!frame)
        return makeUnexpected(errorString);

    if (frame->ownerElement()) {
        auto highlightConfig = makeUnique<InspectorOverlay::Highlight::Config>();
        highlightConfig->showInfo = true; // Always show tooltips for frames.
        highlightConfig->content = parseColor(WTFMove(color)).value_or(Color::transparentBlack);
        highlightConfig->contentOutline = parseColor(WTFMove(outlineColor)).value_or(Color::transparentBlack);
        m_overlay->highlightNode(frame->ownerElement(), *highlightConfig);
    }

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::hideHighlight()
{
    m_overlay->hideHighlight();

    return { };
}

Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::showGridOverlay(Inspector::Protocol::DOM::NodeId nodeId,  Ref<JSON::Object>&& gridColor, std::optional<bool>&& showLineNames, std::optional<bool>&& showLineNumbers, std::optional<bool>&& showExtendedGridLines, std::optional<bool>&& showTrackSizes, std::optional<bool>&& showAreaNames)
{
    Protocol::ErrorString errorString;
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    auto parsedColor = parseColor(WTFMove(gridColor));
    if (!parsedColor)
        return makeUnexpected("Invalid color could not be parsed."_s);

    InspectorOverlay::Grid::Config config;
    config.gridColor = *parsedColor;
    config.showLineNames = showLineNames.value_or(false);
    config.showLineNumbers = showLineNumbers.value_or(false);
    config.showExtendedGridLines = showExtendedGridLines.value_or(false);
    config.showTrackSizes = showTrackSizes.value_or(false);
    config.showAreaNames = showAreaNames.value_or(false);

    m_overlay->setGridOverlayForNode(*node, config);

    return { };
}

Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::hideGridOverlay(std::optional<Protocol::DOM::NodeId>&& nodeId)
{
    if (nodeId) {
        Protocol::ErrorString errorString;
        auto node = assertNode(errorString, *nodeId);
        if (!node)
            return makeUnexpected(errorString);

        return m_overlay->clearGridOverlayForNode(*node);
}

    m_overlay->clearAllGridOverlays();

    return { };
}

Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::showFlexOverlay(Inspector::Protocol::DOM::NodeId nodeId, Ref<JSON::Object>&& flexColor, std::optional<bool>&& showOrderNumbers)
{
    Protocol::ErrorString errorString;
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    auto parsedColor = parseColor(WTFMove(flexColor));
    if (!parsedColor)
        return makeUnexpected("Invalid color could not be parsed."_s);

    InspectorOverlay::Flex::Config config;
    config.flexColor = *parsedColor;
    config.showOrderNumbers = showOrderNumbers.value_or(false);

    m_overlay->setFlexOverlayForNode(*node, config);

    return { };
}

Inspector::Protocol::ErrorStringOr<void> InspectorDOMAgent::hideFlexOverlay(std::optional<Protocol::DOM::NodeId>&& nodeId)
{
    if (nodeId) {
        Protocol::ErrorString errorString;
        auto node = assertNode(errorString, *nodeId);
        if (!node)
            return makeUnexpected(errorString);

        return m_overlay->clearFlexOverlayForNode(*node);
    }

    m_overlay->clearAllFlexOverlays();

    return { };
}

Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::moveTo(Protocol::DOM::NodeId nodeId, Protocol::DOM::NodeId targetNodeId, std::optional<Protocol::DOM::NodeId>&& insertBeforeNodeId)
{
    Protocol::ErrorString errorString;

    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    Element* targetElement = assertEditableElement(errorString, targetNodeId);
    if (!targetElement)
        return makeUnexpected(errorString);

    Node* anchorNode = nullptr;
    if (insertBeforeNodeId && *insertBeforeNodeId) {
        anchorNode = assertEditableNode(errorString, *insertBeforeNodeId);
        if (!anchorNode)
            return makeUnexpected(errorString);
        if (anchorNode->parentNode() != targetElement)
            return makeUnexpected("Given insertBeforeNodeId must be a child of given targetNodeId"_s);
    }

    if (!m_domEditor->insertBefore(*targetElement, *node, anchorNode, errorString))
        return makeUnexpected(errorString);

    return pushNodePathToFrontend(errorString, node);
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::undo()
{
    auto result = m_history->undo();
    if (result.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(result.releaseException()));

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::redo()
{
    auto result = m_history->redo();
    if (result.hasException())
        return makeUnexpected(InspectorDOMAgent::toErrorString(result.releaseException()));

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::markUndoableState()
{
    m_history->markUndoableState();

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::focus(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Element* element = assertElement(errorString, nodeId);
    if (!element)
        return makeUnexpected(errorString);
    if (!element->isFocusable())
        return makeUnexpected("Element for given nodeId is not focusable"_s);

    element->focus();

    return { };
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setInspectedNode(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    if (node->isInUserAgentShadowTree() && !m_allowEditingUserAgentShadowTrees)
        return makeUnexpected("Node for given nodeId is in a shadow tree"_s);

    m_inspectedNode = node;

    if (auto& commandLineAPIHost = static_cast<WebInjectedScriptManager&>(m_injectedScriptManager).commandLineAPIHost())
        commandLineAPIHost->addInspectedObject(makeUnique<InspectableNode>(node));

    m_suppressEventListenerChangedEvent = false;

    return { };
}

Protocol::ErrorStringOr<Ref<Protocol::Runtime::RemoteObject>> InspectorDOMAgent::resolveNode(Protocol::DOM::NodeId nodeId, const String& objectGroup)
{
    Protocol::ErrorString errorString;

    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return makeUnexpected(errorString);

    auto object = resolveNode(node, objectGroup);
    if (!object)
        return makeUnexpected("Missing injected script for given nodeId"_s);

    return object.releaseNonNull();
}

Protocol::ErrorStringOr<Ref<JSON::ArrayOf<String>>> InspectorDOMAgent::getAttributes(Protocol::DOM::NodeId nodeId)
{
    Protocol::ErrorString errorString;

    Element* element = assertElement(errorString, nodeId);
    if (!element)
        return makeUnexpected(errorString);

    return buildArrayForElementAttributes(element);
}

Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::requestNode(const Protocol::Runtime::RemoteObjectId& objectId)
{
    Protocol::ErrorString errorString;

    Node* node = nodeForObjectId(objectId);
    if (!node)
        return makeUnexpected("Missing node for given objectId"_s);

    auto nodeId = pushNodePathToFrontend(errorString, node);
    if (!nodeId)
        return makeUnexpected(errorString);

    return nodeId;
}

String InspectorDOMAgent::documentURLString(Document* document)
{
    if (!document || document->url().isNull())
        return emptyString();
    return document->url().string();
}

static String documentBaseURLString(Document* document)
{
    return document->completeURL(emptyString()).string();
}

static bool pseudoElementType(PseudoId pseudoId, Protocol::DOM::PseudoType* type)
{
    switch (pseudoId) {
    case PseudoId::Before:
        *type = Protocol::DOM::PseudoType::Before;
        return true;
    case PseudoId::After:
        *type = Protocol::DOM::PseudoType::After;
        return true;
    default:
        return false;
    }
}

static Protocol::DOM::ShadowRootType shadowRootType(ShadowRootMode mode)
{
    switch (mode) {
    case ShadowRootMode::UserAgent:
        return Protocol::DOM::ShadowRootType::UserAgent;
    case ShadowRootMode::Closed:
        return Protocol::DOM::ShadowRootType::Closed;
    case ShadowRootMode::Open:
        return Protocol::DOM::ShadowRootType::Open;
    }

    ASSERT_NOT_REACHED();
    return Protocol::DOM::ShadowRootType::UserAgent;
}

static Protocol::DOM::CustomElementState customElementState(const Element& element)
{
    if (element.isDefinedCustomElement())
        return Protocol::DOM::CustomElementState::Custom;
    if (element.isFailedCustomElement())
        return Protocol::DOM::CustomElementState::Failed;
    if (element.isUndefinedCustomElement() || element.isCustomElementUpgradeCandidate())
        return Protocol::DOM::CustomElementState::Waiting;
    return Protocol::DOM::CustomElementState::Builtin;
}

static String computeContentSecurityPolicySHA256Hash(const Element& element)
{
    // FIXME: Compute the digest with respect to the raw bytes received from the page.
    // See <https://bugs.webkit.org/show_bug.cgi?id=155184>.
    PAL::TextEncoding documentEncoding = element.document().textEncoding();
    const PAL::TextEncoding& encodingToUse = documentEncoding.isValid() ? documentEncoding : PAL::UTF8Encoding();
    auto content = encodingToUse.encode(TextNodeTraversal::contentsAsString(element), PAL::UnencodableHandling::Entities);
    auto cryptoDigest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
    cryptoDigest->addBytes(content.data(), content.size());
    auto digest = cryptoDigest->computeHash();
    return makeString("sha256-", base64Encoded(digest.data(), digest.size()));
}

Ref<Protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth)
{
    auto id = bind(*node);
    String nodeName;
    String localName;
    String nodeValue;

    switch (node->nodeType()) {
    case Node::PROCESSING_INSTRUCTION_NODE:
        nodeName = node->nodeName();
        localName = node->localName();
        FALLTHROUGH;
    case Node::TEXT_NODE:
    case Node::COMMENT_NODE:
    case Node::CDATA_SECTION_NODE:
        nodeValue = node->nodeValue();
        if (nodeValue.length() > maxTextSize)
            nodeValue = makeString(StringView(nodeValue).left(maxTextSize), ellipsisUChar);
        break;
    case Node::ATTRIBUTE_NODE:
        localName = node->localName();
        break;
    case Node::DOCUMENT_FRAGMENT_NODE:
    case Node::DOCUMENT_NODE:
    case Node::ELEMENT_NODE:
    default:
        nodeName = node->nodeName();
        localName = node->localName();
        break;
    }

    auto value = Protocol::DOM::Node::create()
        .setNodeId(id)
        .setNodeType(static_cast<int>(node->nodeType()))
        .setNodeName(nodeName)
        .setLocalName(localName)
        .setNodeValue(nodeValue)
        .release();

    if (node->isContainerNode()) {
        int nodeCount = innerChildNodeCount(node);
        value->setChildNodeCount(nodeCount);
        auto children = buildArrayForContainerChildren(node, depth);
        if (children->length() > 0)
            value->setChildren(WTFMove(children));
    }
    
    if (auto layoutContextType = InspectorCSSAgent::layoutContextTypeForRenderer(node->renderer()))
        value->setLayoutContextType(layoutContextType.value());

    auto* pageAgent = m_instrumentingAgents.enabledPageAgent();
    if (pageAgent) {
        if (auto* frameView = node->document().view())
            value->setFrameId(pageAgent->frameId(&frameView->frame()));
    }

    if (is<Element>(*node)) {
        Element& element = downcast<Element>(*node);
        value->setAttributes(buildArrayForElementAttributes(&element));
        if (is<HTMLFrameOwnerElement>(element)) {
            if (auto* document = downcast<HTMLFrameOwnerElement>(element).contentDocument())
                value->setContentDocument(buildObjectForNode(document, 0));
        }

        if (ShadowRoot* root = element.shadowRoot()) {
            auto shadowRoots = JSON::ArrayOf<Protocol::DOM::Node>::create();
            shadowRoots->addItem(buildObjectForNode(root, 0));
            value->setShadowRoots(WTFMove(shadowRoots));
        }

        if (is<HTMLTemplateElement>(element))
            value->setTemplateContent(buildObjectForNode(&downcast<HTMLTemplateElement>(element).content(), 0));

        if (is<HTMLStyleElement>(element) || (is<HTMLScriptElement>(element) && !element.hasAttributeWithoutSynchronization(HTMLNames::srcAttr)))
            value->setContentSecurityPolicyHash(computeContentSecurityPolicySHA256Hash(element));

        auto state = customElementState(element);
        if (state != Protocol::DOM::CustomElementState::Builtin)
            value->setCustomElementState(state);

        if (element.pseudoId() != PseudoId::None) {
            Protocol::DOM::PseudoType pseudoType;
            if (pseudoElementType(element.pseudoId(), &pseudoType))
                value->setPseudoType(pseudoType);
        } else {
            if (auto pseudoElements = buildArrayForPseudoElements(element))
                value->setPseudoElements(pseudoElements.releaseNonNull());
        }
    } else if (is<Document>(*node)) {
        Document& document = downcast<Document>(*node);
        if (pageAgent)
            value->setFrameId(pageAgent->frameId(document.frame()));
        value->setDocumentURL(documentURLString(&document));
        value->setBaseURL(documentBaseURLString(&document));
        value->setXmlVersion(document.xmlVersion());
    } else if (is<DocumentType>(*node)) {
        DocumentType& docType = downcast<DocumentType>(*node);
        value->setPublicId(docType.publicId());
        value->setSystemId(docType.systemId());
    } else if (is<Attr>(*node)) {
        Attr& attribute = downcast<Attr>(*node);
        value->setName(attribute.name());
        value->setValue(attribute.value());
    } else if (is<ShadowRoot>(*node)) {
        ShadowRoot& shadowRoot = downcast<ShadowRoot>(*node);
        value->setShadowRootType(shadowRootType(shadowRoot.mode()));
    }

    return value;
}

Ref<JSON::ArrayOf<String>> InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
{
    auto attributesValue = JSON::ArrayOf<String>::create();
    // Go through all attributes and serialize them.
    if (!element->hasAttributes())
        return attributesValue;
    for (const Attribute& attribute : element->attributesIterator()) {
        // Add attribute pair
        attributesValue->addItem(attribute.name().toString());
        attributesValue->addItem(attribute.value());
    }
    return attributesValue;
}

Ref<JSON::ArrayOf<Protocol::DOM::Node>> InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth)
{
    auto children = JSON::ArrayOf<Protocol::DOM::Node>::create();
    if (depth == 0) {
        // Special-case the only text child - pretend that container's children have been requested.
        Node* firstChild = container->firstChild();
        if (firstChild && firstChild->nodeType() == Node::TEXT_NODE && !firstChild->nextSibling()) {
            children->addItem(buildObjectForNode(firstChild, 0));
            m_childrenRequested.add(bind(*container));
        }
        return children;
    }

    Node* child = innerFirstChild(container);
    depth--;
    m_childrenRequested.add(bind(*container));

    while (child) {
        children->addItem(buildObjectForNode(child, depth));
        child = innerNextSibling(child);
    }
    return children;
}

RefPtr<JSON::ArrayOf<Protocol::DOM::Node>> InspectorDOMAgent::buildArrayForPseudoElements(const Element& element)
{
    PseudoElement* beforeElement = element.beforePseudoElement();
    PseudoElement* afterElement = element.afterPseudoElement();
    if (!beforeElement && !afterElement)
        return nullptr;

    auto pseudoElements = JSON::ArrayOf<Protocol::DOM::Node>::create();
    if (beforeElement)
        pseudoElements->addItem(buildObjectForNode(beforeElement, 0));
    if (afterElement)
        pseudoElements->addItem(buildObjectForNode(afterElement, 0));
    return pseudoElements;
}

Ref<Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, Protocol::DOM::EventListenerId identifier, EventTarget& eventTarget, const AtomString& eventType, bool disabled, const RefPtr<JSC::Breakpoint>& breakpoint)
{
    Ref<EventListener> eventListener = registeredEventListener.callback();

    String handlerName;
    int lineNumber = 0;
    int columnNumber = 0;
    String scriptID;
    if (is<JSEventListener>(eventListener)) {
        auto& scriptListener = downcast<JSEventListener>(eventListener.get());

        Document* document = nullptr;
        if (auto* scriptExecutionContext = eventTarget.scriptExecutionContext()) {
            if (is<Document>(scriptExecutionContext))
                document = downcast<Document>(scriptExecutionContext);
        } else if (is<Node>(eventTarget))
            document = &downcast<Node>(eventTarget).document();

        JSC::JSObject* handlerObject = nullptr;
        JSC::JSGlobalObject* globalObject = nullptr;

        JSC::JSLockHolder lock(scriptListener.isolatedWorld().vm());

        if (document) {
            handlerObject = scriptListener.ensureJSFunction(*document);
            if (auto frame = document->frame()) {
                // FIXME: Why do we need the canExecuteScripts check here?
                if (frame->script().canExecuteScripts(NotAboutToExecuteScript))
                    globalObject = frame->script().globalObject(scriptListener.isolatedWorld());
            }
        }

        if (handlerObject && globalObject) {
            JSC::VM& vm = globalObject->vm();
            JSC::JSFunction* handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(handlerObject);

            if (!handlerFunction) {
                auto scope = DECLARE_CATCH_SCOPE(vm);

                // If the handler is not actually a function, see if it implements the EventListener interface and use that.
                auto handleEventValue = handlerObject->get(globalObject, JSC::Identifier::fromString(vm, "handleEvent"_s));

                if (UNLIKELY(scope.exception()))
                    scope.clearException();

                if (handleEventValue)
                    handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(handleEventValue);
            }

            if (handlerFunction && !handlerFunction->isHostOrBuiltinFunction()) {
                // If the listener implements the EventListener interface, use the class name instead of
                // "handleEvent", unless it is a plain object.
                if (handlerFunction != handlerObject)
                    handlerName = JSC::JSObject::calculatedClassName(handlerObject);
                if (handlerName.isEmpty() || handlerName == "Object"_s)
                    handlerName = handlerFunction->calculatedDisplayName(vm);

                if (auto executable = handlerFunction->jsExecutable()) {
                    lineNumber = executable->firstLine() - 1;
                    columnNumber = executable->startColumn() - 1;
                    scriptID = executable->sourceID() == JSC::SourceProvider::nullID ? emptyString() : String::number(executable->sourceID());
                }
            }
        }
    }

    auto value = Protocol::DOM::EventListener::create()
        .setEventListenerId(identifier)
        .setType(eventType)
        .setUseCapture(registeredEventListener.useCapture())
        .setIsAttribute(eventListener->isAttribute())
        .release();
    if (is<Node>(eventTarget))
        value->setNodeId(pushNodePathToFrontend(&downcast<Node>(eventTarget)));
    else if (is<DOMWindow>(eventTarget))
        value->setOnWindow(true);
    if (!scriptID.isNull()) {
        auto location = Protocol::Debugger::Location::create()
            .setScriptId(scriptID)
            .setLineNumber(lineNumber)
            .release();
        location->setColumnNumber(columnNumber);
        value->setLocation(WTFMove(location));
    }
    if (!handlerName.isEmpty())
        value->setHandlerName(handlerName);
    if (registeredEventListener.isPassive())
        value->setPassive(true);
    if (registeredEventListener.isOnce())
        value->setOnce(true);
    if (disabled)
        value->setDisabled(disabled);
    if (breakpoint)
        value->setHasBreakpoint(breakpoint);
    return value;
}

void InspectorDOMAgent::processAccessibilityChildren(AXCoreObject& axObject, JSON::ArrayOf<Protocol::DOM::NodeId>& childNodeIds)
{
    const auto& children = axObject.children();
    if (!children.size())
        return;

    for (const auto& childObject : children) {
        if (Node* childNode = childObject->node())
            childNodeIds.addItem(pushNodePathToFrontend(childNode));
        else
            processAccessibilityChildren(*childObject, childNodeIds);
    }
}
    
Ref<Protocol::DOM::AccessibilityProperties> InspectorDOMAgent::buildObjectForAccessibilityProperties(Node& node)
{
    if (!WebCore::AXObjectCache::accessibilityEnabled())
        WebCore::AXObjectCache::enableAccessibility();

    Node* activeDescendantNode = nullptr;
    bool busy = false;
    auto checked = Protocol::DOM::AccessibilityProperties::Checked::False;
    RefPtr<JSON::ArrayOf<Protocol::DOM::NodeId>> childNodeIds;
    RefPtr<JSON::ArrayOf<Protocol::DOM::NodeId>> controlledNodeIds;
    auto currentState = Protocol::DOM::AccessibilityProperties::Current::False;
    bool exists = false;
    bool expanded = false;
    bool disabled = false;
    RefPtr<JSON::ArrayOf<Protocol::DOM::NodeId>> flowedNodeIds;
    bool focused = false;
    bool ignored = true;
    bool ignoredByDefault = false;
    auto invalid = Protocol::DOM::AccessibilityProperties::Invalid::False;
    bool hidden = false;
    String label;
    bool liveRegionAtomic = false;
    RefPtr<JSON::ArrayOf<String>> liveRegionRelevant;
    auto liveRegionStatus = Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Off;
    Node* mouseEventNode = nullptr;
    RefPtr<JSON::ArrayOf<Protocol::DOM::NodeId>> ownedNodeIds;
    Node* parentNode = nullptr;
    bool pressed = false;
    bool readonly = false;
    bool required = false;
    String role;
    bool selected = false;
    RefPtr<JSON::ArrayOf<Protocol::DOM::NodeId>> selectedChildNodeIds;
    bool supportsChecked = false;
    bool supportsExpanded = false;
    bool supportsLiveRegion = false;
    bool supportsPressed = false;
    bool supportsRequired = false;
    bool supportsFocused = false;
    bool isPopupButton = false;
    int headingLevel = 0;
    unsigned hierarchicalLevel = 0;
    unsigned level = 0;

    if (auto* axObjectCache = node.document().axObjectCache()) {
        if (auto* axObject = axObjectCache->getOrCreate(&node)) {

            if (AXCoreObject* activeDescendant = axObject->activeDescendant())
                activeDescendantNode = activeDescendant->node();

            // An AX object is "busy" if it or any ancestor has aria-busy="true" set.
            AXCoreObject* current = axObject;
            while (!busy && current) {
                busy = current->isBusy();
                current = current->parentObject();
            }

            supportsChecked = axObject->supportsChecked();
            if (supportsChecked) {
                AccessibilityButtonState checkValue = axObject->checkboxOrRadioValue(); // Element using aria-checked.
                if (checkValue == AccessibilityButtonState::On)
                    checked = Protocol::DOM::AccessibilityProperties::Checked::True;
                else if (checkValue == AccessibilityButtonState::Mixed)
                    checked = Protocol::DOM::AccessibilityProperties::Checked::Mixed;
                else if (axObject->isChecked()) // Native checkbox.
                    checked = Protocol::DOM::AccessibilityProperties::Checked::True;
            }
            
            if (!axObject->children().isEmpty()) {
                childNodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
                processAccessibilityChildren(*axObject, *childNodeIds);
            }

            auto controlledElements = axObject->elementsFromAttribute(aria_controlsAttr);
            if (controlledElements.size()) {
                controlledNodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
                for (Element* controlledElement : controlledElements) {
                    if (auto controlledElementId = pushNodePathToFrontend(controlledElement))
                        controlledNodeIds->addItem(controlledElementId);
                }
            }
            
            switch (axObject->currentState()) {
            case AccessibilityCurrentState::False:
                currentState = Protocol::DOM::AccessibilityProperties::Current::False;
                break;
            case AccessibilityCurrentState::Page:
                currentState = Protocol::DOM::AccessibilityProperties::Current::Page;
                break;
            case AccessibilityCurrentState::Step:
                currentState = Protocol::DOM::AccessibilityProperties::Current::Step;
                break;
            case AccessibilityCurrentState::Location:
                currentState = Protocol::DOM::AccessibilityProperties::Current::Location;
                break;
            case AccessibilityCurrentState::Date:
                currentState = Protocol::DOM::AccessibilityProperties::Current::Date;
                break;
            case AccessibilityCurrentState::Time:
                currentState = Protocol::DOM::AccessibilityProperties::Current::Time;
                break;
            case AccessibilityCurrentState::True:
                currentState = Protocol::DOM::AccessibilityProperties::Current::True;
                break;
            }

            disabled = !axObject->isEnabled();
            exists = true;
            
            supportsExpanded = axObject->supportsExpanded();
            if (supportsExpanded)
                expanded = axObject->isExpanded();

            auto flowedElements = axObject->elementsFromAttribute(aria_flowtoAttr);
            if (flowedElements.size()) {
                flowedNodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
                for (Element* flowedElement : flowedElements) {
                    if (auto flowedElementId = pushNodePathToFrontend(flowedElement))
                        flowedNodeIds->addItem(flowedElementId);
                }
            }

            if (is<Element>(node)) {
                supportsFocused = axObject->canSetFocusAttribute();
                if (supportsFocused)
                    focused = axObject->isFocused();
            }

            ignored = axObject->accessibilityIsIgnored();
            ignoredByDefault = axObject->accessibilityIsIgnoredByDefault();
            
            String invalidValue = axObject->invalidStatus();
            if (invalidValue == "false"_s)
                invalid = Protocol::DOM::AccessibilityProperties::Invalid::False;
            else if (invalidValue == "grammar"_s)
                invalid = Protocol::DOM::AccessibilityProperties::Invalid::Grammar;
            else if (invalidValue == "spelling"_s)
                invalid = Protocol::DOM::AccessibilityProperties::Invalid::Spelling;
            else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size.
                invalid = Protocol::DOM::AccessibilityProperties::Invalid::True;
            
            if (axObject->isHidden())
                hidden = true;
            
            label = axObject->computedLabel();

            if (axObject->supportsLiveRegion()) {
                supportsLiveRegion = true;
                liveRegionAtomic = axObject->liveRegionAtomic();

                auto ariaRelevantAttrValue = axObject->liveRegionRelevant();
                if (!ariaRelevantAttrValue.isEmpty()) {
                    // FIXME: Pass enum values rather than strings once unblocked. http://webkit.org/b/133711
                    String ariaRelevantAdditions = Protocol::Helpers::getEnumConstantValue(Protocol::DOM::LiveRegionRelevant::Additions);
                    String ariaRelevantRemovals = Protocol::Helpers::getEnumConstantValue(Protocol::DOM::LiveRegionRelevant::Removals);
                    String ariaRelevantText = Protocol::Helpers::getEnumConstantValue(Protocol::DOM::LiveRegionRelevant::Text);
                    liveRegionRelevant = JSON::ArrayOf<String>::create();
                    SpaceSplitString values(AtomString { ariaRelevantAttrValue }, SpaceSplitString::ShouldFoldCase::Yes);
                    // @aria-relevant="all" is exposed as ["additions","removals","text"], in order.
                    // This order is controlled in WebCore and expected in WebInspectorUI.
                    if (values.contains("all"_s)) {
                        liveRegionRelevant->addItem(ariaRelevantAdditions);
                        liveRegionRelevant->addItem(ariaRelevantRemovals);
                        liveRegionRelevant->addItem(ariaRelevantText);
                    } else {
                        if (values.contains(AtomString { ariaRelevantAdditions }))
                            liveRegionRelevant->addItem(ariaRelevantAdditions);
                        if (values.contains(AtomString { ariaRelevantRemovals }))
                            liveRegionRelevant->addItem(ariaRelevantRemovals);
                        if (values.contains(AtomString { ariaRelevantText }))
                            liveRegionRelevant->addItem(ariaRelevantText);
                    }
                }

                String ariaLive = axObject->liveRegionStatus();
                if (ariaLive == "assertive"_s)
                    liveRegionStatus = Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Assertive;
                else if (ariaLive == "polite"_s)
                    liveRegionStatus = Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Polite;
            }

            if (is<AccessibilityNodeObject>(*axObject))
                mouseEventNode = downcast<AccessibilityNodeObject>(*axObject).mouseButtonListener(MouseButtonListenerResultFilter::IncludeBodyElement);

            if (axObject->supportsARIAOwns()) {
                auto ownedElements = axObject->elementsFromAttribute(aria_ownsAttr);
                if (ownedElements.size()) {
                    ownedNodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
                    for (Element* ownedElement : ownedElements) {
                        if (auto ownedElementId = pushNodePathToFrontend(ownedElement))
                            ownedNodeIds->addItem(ownedElementId);
                    }
                }
            }

            if (AXCoreObject* parentObject = axObject->parentObjectUnignored())
                parentNode = parentObject->node();

            supportsPressed = axObject->pressedIsPresent();
            if (supportsPressed)
                pressed = axObject->isPressed();
            
            if (axObject->isTextControl())
                readonly = !axObject->canSetValueAttribute();

            supportsRequired = axObject->supportsRequiredAttribute();
            if (supportsRequired)
                required = axObject->isRequired();
            
            role = axObject->computedRoleString();
            selected = axObject->isSelected();

            AXCoreObject::AccessibilityChildrenVector selectedChildren;
            axObject->selectedChildren(selectedChildren);
            if (selectedChildren.size()) {
                selectedChildNodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
                for (auto& selectedChildObject : selectedChildren) {
                    if (Node* selectedChildNode = selectedChildObject->node()) {
                        if (auto selectedChildNodeId = pushNodePathToFrontend(selectedChildNode))
                            selectedChildNodeIds->addItem(selectedChildNodeId);
                    }
                }
            }
            
            headingLevel = axObject->headingLevel();
            hierarchicalLevel = axObject->hierarchicalLevel();
            
            level = hierarchicalLevel ? hierarchicalLevel : headingLevel;
            isPopupButton = axObject->isPopUpButton() || axObject->hasPopup();
        }
    }
    
    auto value = Protocol::DOM::AccessibilityProperties::create()
        .setExists(exists)
        .setLabel(label)
        .setRole(role)
        .setNodeId(pushNodePathToFrontend(&node))
        .release();

    if (exists) {
        if (activeDescendantNode) {
            if (auto activeDescendantNodeId = pushNodePathToFrontend(activeDescendantNode))
                value->setActiveDescendantNodeId(activeDescendantNodeId);
        }
        if (busy)
            value->setBusy(busy);
        if (supportsChecked)
            value->setChecked(checked);
        if (childNodeIds)
            value->setChildNodeIds(childNodeIds.releaseNonNull());
        if (controlledNodeIds)
            value->setControlledNodeIds(controlledNodeIds.releaseNonNull());
        if (currentState != Protocol::DOM::AccessibilityProperties::Current::False)
            value->setCurrent(currentState);
        if (disabled)
            value->setDisabled(disabled);
        if (supportsExpanded)
            value->setExpanded(expanded);
        if (flowedNodeIds)
            value->setFlowedNodeIds(flowedNodeIds.releaseNonNull());
        if (supportsFocused)
            value->setFocused(focused);
        if (ignored)
            value->setIgnored(ignored);
        if (ignoredByDefault)
            value->setIgnoredByDefault(ignoredByDefault);
        if (invalid != Protocol::DOM::AccessibilityProperties::Invalid::False)
            value->setInvalid(invalid);
        if (hidden)
            value->setHidden(hidden);
        if (supportsLiveRegion) {
            value->setLiveRegionAtomic(liveRegionAtomic);
            if (liveRegionRelevant->length())
                value->setLiveRegionRelevant(liveRegionRelevant.releaseNonNull());
            value->setLiveRegionStatus(liveRegionStatus);
        }
        if (mouseEventNode) {
            if (auto mouseEventNodeId = pushNodePathToFrontend(mouseEventNode))
                value->setMouseEventNodeId(mouseEventNodeId);
        }
        if (ownedNodeIds)
            value->setOwnedNodeIds(ownedNodeIds.releaseNonNull());
        if (parentNode) {
            if (auto parentNodeId = pushNodePathToFrontend(parentNode))
                value->setParentNodeId(parentNodeId);
        }
        if (supportsPressed)
            value->setPressed(pressed);
        if (readonly)
            value->setReadonly(readonly);
        if (supportsRequired)
            value->setRequired(required);
        if (selected)
            value->setSelected(selected);
        if (selectedChildNodeIds)
            value->setSelectedChildNodeIds(selectedChildNodeIds.releaseNonNull());
        
        // H1 -- H6 always have a headingLevel property that can be complimented by a hierarchicalLevel
        // property when aria-level is set on the element, in which case we want to remain calling
        // this value the "Heading Level" in the inspector.
        // Also, we do not want it to say Hierarchy Level: 0
        if (headingLevel)
            value->setHeadingLevel(level);
        else if (level)
            value->setHierarchyLevel(level);
        if (isPopupButton)
            value->setIsPopUpButton(isPopupButton);
    }

    return value;
}

static bool containsOnlyHTMLWhitespace(Node* node)
{
    // FIXME: Respect ignoreWhitespace setting from inspector front end?
    return is<Text>(node) && downcast<Text>(*node).data().isAllSpecialCharacters<isHTMLSpace>();
}

Node* InspectorDOMAgent::innerFirstChild(Node* node)
{
    node = node->firstChild();
    while (containsOnlyHTMLWhitespace(node))
        node = node->nextSibling();
    return node;
}

Node* InspectorDOMAgent::innerNextSibling(Node* node)
{
    do {
        node = node->nextSibling();
    } while (containsOnlyHTMLWhitespace(node));
    return node;
}

Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
{
    do {
        node = node->previousSibling();
    } while (containsOnlyHTMLWhitespace(node));
    return node;
}

unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
{
    unsigned count = 0;
    for (Node* child = innerFirstChild(node); child; child = innerNextSibling(child))
        ++count;
    return count;
}

Node* InspectorDOMAgent::innerParentNode(Node* node)
{
    ASSERT(node);
    if (is<Document>(*node))
        return downcast<Document>(*node).ownerElement();
    if (is<ShadowRoot>(*node))
        return downcast<ShadowRoot>(*node).host();
    return node->parentNode();
}

void InspectorDOMAgent::didCommitLoad(Document* document)
{
    if (m_nodeToFocus && &m_nodeToFocus->document() == document)
        m_nodeToFocus = nullptr;

    if (m_mousedOverNode && &m_mousedOverNode->document() == document)
        m_mousedOverNode = nullptr;

    if (m_inspectedNode && &m_inspectedNode->document() == document)
        m_inspectedNode = nullptr;

    RefPtr<Element> frameOwner = document->ownerElement();
    if (!frameOwner)
        return;

    auto frameOwnerId = boundNodeId(frameOwner.get());
    if (!frameOwnerId)
        return;

    // Re-add frame owner element together with its new children.
    auto parentId = boundNodeId(innerParentNode(frameOwner.get()));
    m_frontendDispatcher->childNodeRemoved(parentId, frameOwnerId);
    unbind(*frameOwner);

    auto value = buildObjectForNode(frameOwner.get(), 0);
    Node* previousSibling = innerPreviousSibling(frameOwner.get());
    auto prevId = boundNodeId(previousSibling);
    m_frontendDispatcher->childNodeInserted(parentId, prevId, WTFMove(value));
}

Protocol::DOM::NodeId InspectorDOMAgent::identifierForNode(Node& node)
{
    return pushNodePathToFrontend(&node);
}

void InspectorDOMAgent::addEventListenersToNode(Node& node)
{
#if ENABLE(VIDEO)
    auto callback = EventFiredCallback::create(*this);

    auto createEventListener = [&] (const AtomString& eventName) {
        node.addEventListener(eventName, callback.copyRef(), false);
    };

#if ENABLE(FULLSCREEN_API)
    if (is<Document>(node) || is<HTMLMediaElement>(node))
        createEventListener(eventNames().webkitfullscreenchangeEvent);
#endif // ENABLE(FULLSCREEN_API)

    if (is<HTMLMediaElement>(node)) {
        createEventListener(eventNames().abortEvent);
        createEventListener(eventNames().canplayEvent);
        createEventListener(eventNames().canplaythroughEvent);
        createEventListener(eventNames().emptiedEvent);
        createEventListener(eventNames().endedEvent);
        createEventListener(eventNames().loadeddataEvent);
        createEventListener(eventNames().loadedmetadataEvent);
        createEventListener(eventNames().loadstartEvent);
        createEventListener(eventNames().pauseEvent);
        createEventListener(eventNames().playEvent);
        createEventListener(eventNames().playingEvent);
        createEventListener(eventNames().seekedEvent);
        createEventListener(eventNames().seekingEvent);
        createEventListener(eventNames().stalledEvent);
        createEventListener(eventNames().suspendEvent);
        createEventListener(eventNames().waitingEvent);

        if (!m_mediaMetricsTimer.isActive())
            m_mediaMetricsTimer.start(0_s, 1_s / 15.);
    }
#else
    UNUSED_PARAM(node);
#endif // ENABLE(VIDEO)
}

void InspectorDOMAgent::didInsertDOMNode(Node& node)
{
    if (containsOnlyHTMLWhitespace(&node))
        return;

    // We could be attaching existing subtree. Forget the bindings.
    unbind(node);

    ContainerNode* parent = node.parentNode();

    auto parentId = boundNodeId(parent);
    // Return if parent is not mapped yet.
    if (!parentId)
        return;

    if (!m_childrenRequested.contains(parentId)) {
        // No children are mapped yet -> only notify on changes of hasChildren.
        m_frontendDispatcher->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
    } else {
        // Children have been requested -> return value of a new child.
        Node* prevSibling = innerPreviousSibling(&node);
        auto prevId = boundNodeId(prevSibling);
        auto value = buildObjectForNode(&node, 0);
        m_frontendDispatcher->childNodeInserted(parentId, prevId, WTFMove(value));
    }
}

void InspectorDOMAgent::didRemoveDOMNode(Node& node)
{
    if (containsOnlyHTMLWhitespace(&node))
        return;

    ContainerNode* parent = node.parentNode();

    auto parentId = boundNodeId(parent);
    // If parent is not mapped yet -> ignore the event.
    if (!parentId)
        return;

    // FIXME: <webkit.org/b/189687> Preserve DOM.NodeId if a node is removed and re-added
    if (!m_childrenRequested.contains(parentId)) {
        // No children are mapped yet -> only notify on changes of hasChildren.
        if (innerChildNodeCount(parent) == 1)
            m_frontendDispatcher->childNodeCountUpdated(parentId, 0);
    } else
        m_frontendDispatcher->childNodeRemoved(parentId, boundNodeId(&node));
    unbind(node);
}

void InspectorDOMAgent::willDestroyDOMNode(Node& node)
{
    if (containsOnlyHTMLWhitespace(&node))
        return;

    auto nodeId = m_nodeToId.take(node);
    if (!nodeId)
        return;

    m_idToNode.remove(nodeId);
    m_childrenRequested.remove(nodeId);

    if (auto* cssAgent = m_instrumentingAgents.enabledCSSAgent())
        cssAgent->didRemoveDOMNode(node, nodeId);

    // This can be called in response to GC. Due to the single-process model used in WebKit1, the
    // event must be dispatched from a timer to prevent the frontend from making JS allocations
    // while the GC is still active.

    // FIXME: <webkit.org/b/189687> Unify m_destroyedAttachedNodeIdentifiers and m_destroyedDetachedNodeIdentifiers.
    if (auto parentId = boundNodeId(node.parentNode()))
        m_destroyedAttachedNodeIdentifiers.append({ parentId, nodeId });
    else
        m_destroyedDetachedNodeIdentifiers.append(nodeId);

    if (!m_destroyedNodesTimer.isActive())
        m_destroyedNodesTimer.startOneShot(0_s);
}

void InspectorDOMAgent::destroyedNodesTimerFired()
{
    for (auto& [parentId, nodeId] : std::exchange(m_destroyedAttachedNodeIdentifiers, { })) {
        if (!m_childrenRequested.contains(parentId)) {
            auto* parent = nodeForId(parentId);
            if (parent && innerChildNodeCount(parent) == 1)
                m_frontendDispatcher->childNodeCountUpdated(parentId, 0);
        } else
            m_frontendDispatcher->childNodeRemoved(parentId, nodeId);
    }
    
    for (auto nodeId : std::exchange(m_destroyedDetachedNodeIdentifiers, { }))
        m_frontendDispatcher->willDestroyDOMNode(nodeId);
}

void InspectorDOMAgent::willModifyDOMAttr(Element&, const AtomString& oldValue, const AtomString& newValue)
{
    m_suppressAttributeModifiedEvent = (oldValue == newValue);
}

void InspectorDOMAgent::didModifyDOMAttr(Element& element, const AtomString& name, const AtomString& value)
{
    bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
    m_suppressAttributeModifiedEvent = false;
    if (shouldSuppressEvent)
        return;

    auto id = boundNodeId(&element);
    if (!id)
        return;

    if (auto* cssAgent = m_instrumentingAgents.enabledCSSAgent())
        cssAgent->didModifyDOMAttr(element);

    m_frontendDispatcher->attributeModified(id, name, value);
}

void InspectorDOMAgent::didRemoveDOMAttr(Element& element, const AtomString& name)
{
    auto id = boundNodeId(&element);
    if (!id)
        return;

    if (auto* cssAgent = m_instrumentingAgents.enabledCSSAgent())
        cssAgent->didModifyDOMAttr(element);

    m_frontendDispatcher->attributeRemoved(id, name);
}

void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
{
    auto nodeIds = JSON::ArrayOf<Protocol::DOM::NodeId>::create();
    for (auto& element : elements) {
        auto id = boundNodeId(element);
        if (!id)
            continue;

        if (auto* cssAgent = m_instrumentingAgents.enabledCSSAgent())
            cssAgent->didModifyDOMAttr(*element);

        nodeIds->addItem(id);
    }
    m_frontendDispatcher->inlineStyleInvalidated(WTFMove(nodeIds));
}

void InspectorDOMAgent::characterDataModified(CharacterData& characterData)
{
    auto id = boundNodeId(&characterData);
    if (!id) {
        // Push text node if it is being created.
        didInsertDOMNode(characterData);
        return;
    }
    m_frontendDispatcher->characterDataModified(id, characterData.data());
}

void InspectorDOMAgent::didInvalidateStyleAttr(Element& element)
{
    auto id = boundNodeId(&element);
    if (!id)
        return;

    if (!m_revalidateStyleAttrTask)
        m_revalidateStyleAttrTask = makeUnique<RevalidateStyleAttributeTask>(this);
    m_revalidateStyleAttrTask->scheduleFor(&element);
}

void InspectorDOMAgent::didPushShadowRoot(Element& host, ShadowRoot& root)
{
    auto hostId = boundNodeId(&host);
    if (hostId)
        m_frontendDispatcher->shadowRootPushed(hostId, buildObjectForNode(&root, 0));
}

void InspectorDOMAgent::willPopShadowRoot(Element& host, ShadowRoot& root)
{
    auto hostId = boundNodeId(&host);
    auto rootId = boundNodeId(&root);
    if (hostId && rootId)
        m_frontendDispatcher->shadowRootPopped(hostId, rootId);
}

void InspectorDOMAgent::didChangeCustomElementState(Element& element)
{
    auto elementId = boundNodeId(&element);
    if (!elementId)
        return;

    m_frontendDispatcher->customElementStateChanged(elementId, customElementState(element));
}

void InspectorDOMAgent::frameDocumentUpdated(Frame& frame)
{
    Document* document = frame.document();
    if (!document)
        return;

    if (!frame.isMainFrame())
        return;

    // Only update the main frame document, nested frame document updates are not required
    // (will be handled by didCommitLoad()).
    setDocument(document);
}

void InspectorDOMAgent::pseudoElementCreated(PseudoElement& pseudoElement)
{
    Element* parent = pseudoElement.hostElement();
    if (!parent)
        return;

    auto parentId = boundNodeId(parent);
    if (!parentId)
        return;

    pushChildNodesToFrontend(parentId, 1);
    m_frontendDispatcher->pseudoElementAdded(parentId, buildObjectForNode(&pseudoElement, 0));
}

void InspectorDOMAgent::pseudoElementDestroyed(PseudoElement& pseudoElement)
{
    auto pseudoElementId = boundNodeId(&pseudoElement);
    if (!pseudoElementId)
        return;

    // If a PseudoElement is bound, its parent element must have been bound.
    Element* parent = pseudoElement.hostElement();
    ASSERT(parent);
    auto parentId = boundNodeId(parent);
    ASSERT(parentId);

    unbind(pseudoElement);
    m_frontendDispatcher->pseudoElementRemoved(parentId, pseudoElementId);
}

void InspectorDOMAgent::didAddEventListener(EventTarget& target)
{
    if (!is<Node>(target))
        return;

    auto& node = downcast<Node>(target);
    if (!node.contains(m_inspectedNode.get()))
        return;

    auto nodeId = boundNodeId(&node);
    if (!nodeId)
        return;

    if (m_suppressEventListenerChangedEvent)
        return;

    m_suppressEventListenerChangedEvent = true;

    m_frontendDispatcher->didAddEventListener(nodeId);
}

void InspectorDOMAgent::willRemoveEventListener(EventTarget& target, const AtomString& eventType, EventListener& listener, bool capture)
{
    if (!is<Node>(target))
        return;

    auto& node = downcast<Node>(target);
    if (!node.contains(m_inspectedNode.get()))
        return;

    auto nodeId = boundNodeId(&node);
    if (!nodeId)
        return;

    bool listenerExists = false;
    for (auto& item : node.eventListeners(eventType)) {
        if (item->callback() == listener && item->useCapture() == capture) {
            listenerExists = true;
            break;
        }
    }

    if (!listenerExists)
        return;

    m_eventListenerEntries.removeIf([&] (auto& entry) {
        return entry.value.matches(target, eventType, listener, capture);
    });

    if (m_suppressEventListenerChangedEvent)
        return;

    m_suppressEventListenerChangedEvent = true;

    m_frontendDispatcher->willRemoveEventListener(nodeId);
}

bool InspectorDOMAgent::isEventListenerDisabled(EventTarget& target, const AtomString& eventType, EventListener& listener, bool capture)
{
    for (auto& inspectorEventListener : m_eventListenerEntries.values()) {
        if (inspectorEventListener.matches(target, eventType, listener, capture))
            return inspectorEventListener.disabled;
    }
    return false;
}

void InspectorDOMAgent::eventDidResetAfterDispatch(const Event& event)
{
    m_dispatchedEvents.remove(&event);
}

void InspectorDOMAgent::flexibleBoxRendererBeganLayout(const RenderObject& renderer)
{
    m_flexibleBoxRendererCachedItemsAtStartOfLine.remove(renderer);
}

void InspectorDOMAgent::flexibleBoxRendererWrappedToNextLine(const RenderObject& renderer, size_t lineStartItemIndex)
{
    m_flexibleBoxRendererCachedItemsAtStartOfLine.ensure(renderer, [] {
        return Vector<size_t>();
    }).iterator->value.append(lineStartItemIndex);
}

Vector<size_t> InspectorDOMAgent::flexibleBoxRendererCachedItemsAtStartOfLine(const RenderObject& renderer)
{
    return m_flexibleBoxRendererCachedItemsAtStartOfLine.get(renderer);
}

RefPtr<JSC::Breakpoint> InspectorDOMAgent::breakpointForEventListener(EventTarget& target, const AtomString& eventType, EventListener& listener, bool capture)
{
    for (auto& inspectorEventListener : m_eventListenerEntries.values()) {
        if (inspectorEventListener.matches(target, eventType, listener, capture))
            return inspectorEventListener.breakpoint;
    }
    return nullptr;
}

Protocol::DOM::EventListenerId InspectorDOMAgent::idForEventListener(EventTarget& target, const AtomString& eventType, EventListener& listener, bool capture)
{
    for (auto& inspectorEventListener : m_eventListenerEntries.values()) {
        if (inspectorEventListener.matches(target, eventType, listener, capture))
            return inspectorEventListener.identifier;
    }
    return 0;
}

#if ENABLE(VIDEO)
void InspectorDOMAgent::mediaMetricsTimerFired()
{
    // FIXME: remove metrics information for any media element when it's destroyed

    if (HTMLMediaElement::allMediaElements().isEmpty()) {
        if (m_mediaMetricsTimer.isActive())
            m_mediaMetricsTimer.stop();
        m_mediaMetrics.clear();
        return;
    }

    for (auto* mediaElement : HTMLMediaElement::allMediaElements()) {
        if (!is<HTMLVideoElement>(mediaElement) || !mediaElement->isPlaying())
            continue;

        auto videoPlaybackQuality = mediaElement->getVideoPlaybackQuality();
        unsigned displayCompositedVideoFrames = videoPlaybackQuality->displayCompositedVideoFrames();

        auto iterator = m_mediaMetrics.find(*mediaElement);
        if (iterator == m_mediaMetrics.end()) {
            m_mediaMetrics.set(*mediaElement, MediaMetrics(displayCompositedVideoFrames));
            continue;
        }

        bool isPowerEfficient = (displayCompositedVideoFrames - iterator->value.displayCompositedFrames) > 0;
        if (iterator->value.isPowerEfficient != isPowerEfficient) {
            iterator->value.isPowerEfficient = isPowerEfficient;

            if (auto nodeId = pushNodePathToFrontend(mediaElement)) {
                auto timestamp = m_environment.executionStopwatch().elapsedTime().seconds();
                m_frontendDispatcher->powerEfficientPlaybackStateChanged(nodeId, timestamp, iterator->value.isPowerEfficient);
            }
        }

        iterator->value.displayCompositedFrames = displayCompositedVideoFrames;
    }

    m_mediaMetrics.removeIf([&] (auto& entry) {
        return !HTMLMediaElement::allMediaElements().contains(&entry.key);
    });
}
#endif

Node* InspectorDOMAgent::nodeForPath(const String& path)
{
    // The path is of form "1,HTML,2,BODY,1,DIV"
    if (!m_document)
        return nullptr;

    Node* node = m_document.get();
    auto pathTokens = StringView(path).split(',');
    auto it = pathTokens.begin();
    if (it == pathTokens.end())
        return nullptr;

    for (; it != pathTokens.end(); ++it) {
        auto childNumberView = *it;
        if (++it == pathTokens.end())
            break;
        auto childNumber = parseIntegerAllowingTrailingJunk<unsigned>(childNumberView);
        if (!childNumber)
            return nullptr;

        Node* child;
        if (is<HTMLFrameOwnerElement>(*node)) {
            ASSERT(!*childNumber);
            auto& frameOwner = downcast<HTMLFrameOwnerElement>(*node);
            child = frameOwner.contentDocument();
        } else {
            if (*childNumber >= innerChildNodeCount(node))
                return nullptr;
            child = innerFirstChild(node);
            for (size_t j = 0; child && j < *childNumber; ++j)
                child = innerNextSibling(child);
        }

        auto childName = *it;
        if (!child || child->nodeName() != childName)
            return nullptr;
        node = child;
    }

    return node;
}

Node* InspectorDOMAgent::nodeForObjectId(const Protocol::Runtime::RemoteObjectId& objectId)
{
    InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
    if (injectedScript.hasNoValue())
        return nullptr;

    return scriptValueAsNode(injectedScript.findObjectById(objectId));
}

Protocol::ErrorStringOr<Protocol::DOM::NodeId> InspectorDOMAgent::pushNodeByPathToFrontend(const String& path)
{
    Protocol::ErrorString errorString;

    if (Node* node = nodeForPath(path)) {
        if (auto nodeId = pushNodePathToFrontend(errorString, node))
            return nodeId;
        return makeUnexpected(errorString);
    }

    return makeUnexpected("Missing node for given path"_s);
}

RefPtr<Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
{
    Document* document = &node->document();
    if (auto* templateHost = document->templateDocumentHost())
        document = templateHost;
    auto* frame =  document->frame();
    if (!frame)
        return nullptr;

    auto& globalObject = mainWorldGlobalObject(*frame);
    auto injectedScript = m_injectedScriptManager.injectedScriptFor(&globalObject);
    if (injectedScript.hasNoValue())
        return nullptr;

    return injectedScript.wrapObject(nodeAsScriptValue(globalObject, node), objectGroup);
}

Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value)
{
    if (!value || !value.isObject())
        return nullptr;
    return JSNode::toWrapped(value.getObject()->vm(), value.getObject());
}

JSC::JSValue InspectorDOMAgent::nodeAsScriptValue(JSC::JSGlobalObject& state, Node* node)
{
    JSC::JSLockHolder lock(&state);
    return toJS(&state, deprecatedGlobalObjectForPrototype(&state), BindingSecurity::checkSecurityForNode(state, node));
}

Protocol::ErrorStringOr<void> InspectorDOMAgent::setAllowEditingUserAgentShadowTrees(bool allow)
{
    m_allowEditingUserAgentShadowTrees = allow;

    return { };
}

} // namespace WebCore
