/*
 * Copyright (C) 2009-2019 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 "Attr.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSPropertyNames.h"
#include "CSSPropertySourceData.h"
#include "CSSRule.h"
#include "CSSRuleList.h"
#include "CSSStyleRule.h"
#include "CSSStyleSheet.h"
#include "CharacterData.h"
#include "CommandLineAPIHost.h"
#include "ContainerNode.h"
#include "Cookie.h"
#include "CookieJar.h"
#include "DOMEditor.h"
#include "DOMException.h"
#include "DOMPatchSupport.h"
#include "DOMWindow.h"
#include "Document.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 "InspectorOverlay.h"
#include "InspectorPageAgent.h"
#include "InstrumentingAgents.h"
#include "IntRect.h"
#include "JSDOMBindingSecurity.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 "RenderStyle.h"
#include "RenderStyleConstants.h"
#include "ScriptState.h"
#include "ShadowRoot.h"
#include "StaticNodeList.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
#include "StyleSheetList.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/JSCInlines.h>
#include <pal/crypto/CryptoDigest.h>
#include <wtf/text/Base64.h>
#include <wtf/text/CString.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 Color parseColor(const JSON::Object* colorObject)
{
    if (!colorObject)
        return Color::transparent;

    int r = 0;
    int g = 0;
    int b = 0;
    if (!colorObject->getInteger("r", r) || !colorObject->getInteger("g", g) || !colorObject->getInteger("b", b))
        return Color::transparent;

    double a = 1.0;
    if (!colorObject->getDouble("a", a))
        return Color(r, g, b);

    // Clamp alpha to the [0..1] range.
    if (a < 0)
        a = 0;
    else if (a > 1)
        a = 1;

    return Color(r, g, b, static_cast<int>(a * 255));
}

static Color parseConfigColor(const String& fieldName, const JSON::Object* configObject)
{
    RefPtr<JSON::Object> colorObject;
    configObject->getObject(fieldName, colorObject);

    return parseColor(colorObject.get());
}

static bool parseQuad(const 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) {
        if (!quadArray.get(i)->asDouble(*(coordinates + i)))
            return false;
    }
    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());
        int 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)
#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.setInspectorDOMAgent(this);
    m_document = m_inspectedPage.mainFrame().document();

#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;

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

    m_instrumentingAgents.setInspectorDOMAgent(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;
}

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

    reset();

    m_document = document;

    if (!m_documentRequested)
        return;

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

void InspectorDOMAgent::releaseDanglingNodes()
{
    m_danglingNodeToIdMaps.clear();
}

int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
{
    int id = nodesMap->get(node);
    if (id)
        return id;
    id = m_lastNodeId++;
    nodesMap->set(node, id);
    m_idToNode.set(id, node);
    m_idToNodesMap.set(id, nodesMap);
    return id;
}

void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
{
    int id = nodesMap->get(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, nodesMap);
    }

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

    nodesMap->remove(node);

    if (auto* cssAgent = m_instrumentingAgents.inspectorCSSAgent())
        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, nodesMap);
    }
}

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

Document* InspectorDOMAgent::assertDocument(ErrorString& errorString, int 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(ErrorString& errorString, int 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(ErrorString& errorString, int 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(ErrorString& errorString, int 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);
}

void InspectorDOMAgent::getDocument(ErrorString& errorString, RefPtr<Inspector::Protocol::DOM::Node>& root)
{
    m_documentRequested = true;

    if (!m_document) {
        errorString = "Internal error: missing document"_s;
        return;
    }

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

    root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);

    if (m_nodeToFocus)
        focusNode();
}

void InspectorDOMAgent::pushChildNodesToFrontend(int 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;

    NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);

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

        depth--;

        for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
            int childNodeId = nodeMap->get(node);
            ASSERT(childNodeId);
            pushChildNodesToFrontend(childNodeId, depth);
        }

        return;
    }

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

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

int InspectorDOMAgent::pushNodeToFrontend(ErrorString& errorString, int 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(nodeToPush);
}

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

    return m_idToNode.get(id);
}

void InspectorDOMAgent::requestChildNodes(ErrorString& errorString, int nodeId, const int* depth)
{
    int sanitizedDepth;

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

    pushChildNodesToFrontend(nodeId, sanitizedDepth);
}

void InspectorDOMAgent::querySelector(ErrorString& errorString, int nodeId, const String& selectors, int* elementId)
{
    *elementId = 0;
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;
    if (!is<ContainerNode>(*node)) {
        assertElement(errorString, nodeId);
        return;
    }

    auto queryResult = downcast<ContainerNode>(*node).querySelector(selectors);
    if (queryResult.hasException()) {
        errorString = "DOM Error while querying with given selectors"_s;
        return;
    }

    if (auto* element = queryResult.releaseReturnValue())
        *elementId = pushNodePathToFrontend(element);
}

void InspectorDOMAgent::querySelectorAll(ErrorString& errorString, int nodeId, const String& selectors, RefPtr<JSON::ArrayOf<int>>& result)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;
    if (!is<ContainerNode>(*node)) {
        assertElement(errorString, nodeId);
        return;
    }

    auto queryResult = downcast<ContainerNode>(*node).querySelectorAll(selectors);
    if (queryResult.hasException()) {
        errorString = "DOM Error while querying with given selectors"_s;
        return;
    }

    auto nodes = queryResult.releaseReturnValue();
    result = JSON::ArrayOf<int>::create();
    for (unsigned i = 0; i < nodes->length(); ++i)
        result->addItem(pushNodePathToFrontend(nodes->item(i)));
}

int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
{
    ASSERT(nodeToPush);  // Invalid input

    if (!m_document)
        return 0;
    if (!m_documentNodeToIdMap.contains(m_document))
        return 0;

    // Return id in case the node is known.
    int result = m_documentNodeToIdMap.get(nodeToPush);
    if (result)
        return result;

    Node* node = nodeToPush;
    Vector<Node*> path;
    NodeToIdMap* danglingMap = 0;

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

    NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
    for (int i = path.size() - 1; i >= 0; --i) {
        int nodeId = map->get(path.at(i));
        ASSERT(nodeId);
        pushChildNodesToFrontend(nodeId);
    }
    return map->get(nodeToPush);
}

int InspectorDOMAgent::boundNodeId(const Node* node)
{
    return m_documentNodeToIdMap.get(const_cast<Node*>(node));
}

void InspectorDOMAgent::setAttributeValue(ErrorString& errorString, int elementId, const String& name, const String& value)
{
    Element* element = assertEditableElement(errorString, elementId);
    if (!element)
        return;

    m_domEditor->setAttribute(*element, name, value, errorString);
}

void InspectorDOMAgent::setAttributesAsText(ErrorString& errorString, int elementId, const String& text, const String* name)
{
    Element* element = assertEditableElement(errorString, elementId);
    if (!element)
        return;

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

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

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

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

    if (!foundOriginalAttribute && name && !name->stripWhiteSpace().isEmpty())
        m_domEditor->removeAttribute(*element, *name, errorString);
}

void InspectorDOMAgent::removeAttribute(ErrorString& errorString, int elementId, const String& name)
{
    Element* element = assertEditableElement(errorString, elementId);
    if (!element)
        return;

    m_domEditor->removeAttribute(*element, name, errorString);
}

void InspectorDOMAgent::removeNode(ErrorString& errorString, int nodeId)
{
    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return;

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

    m_domEditor->removeChild(*parentNode, *node, errorString);
}

void InspectorDOMAgent::setNodeName(ErrorString& errorString, int nodeId, const String& tagName, int* newId)
{
    *newId = 0;

    RefPtr<Node> oldNode = nodeForId(nodeId);
    if (!is<Element>(oldNode))
        return;

    auto createElementResult = oldNode->document().createElementForBindings(tagName);
    if (createElementResult.hasException())
        return;
    auto newElement = createElementResult.releaseReturnValue();

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

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

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

    *newId = pushNodePathToFrontend(newElement.ptr());
    if (m_childrenRequested.contains(nodeId))
        pushChildNodesToFrontend(*newId);
}

void InspectorDOMAgent::getOuterHTML(ErrorString& errorString, int nodeId, WTF::String* outerHTML)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;

    *outerHTML = serializeFragment(*node, SerializedNodes::SubtreeIncludingNode);
}

void InspectorDOMAgent::setOuterHTML(ErrorString& errorString, int nodeId, const String& outerHTML)
{
    if (!nodeId) {
        DOMPatchSupport { *m_domEditor, *m_document }.patchDocument(outerHTML);
        return;
    }

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

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

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

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

    int newId = pushNodePathToFrontend(newNode);

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

void InspectorDOMAgent::insertAdjacentHTML(ErrorString& errorString, int nodeId, const String& position, const String& html)
{
    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return;

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

    m_domEditor->insertAdjacentHTML(downcast<Element>(*node), position, html, errorString);
}

void InspectorDOMAgent::setNodeValue(ErrorString& errorString, int nodeId, const String& value)
{
    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return;

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

    m_domEditor->replaceWholeText(downcast<Text>(*node), value, errorString);
}

void InspectorDOMAgent::getSupportedEventNames(ErrorString&, RefPtr<JSON::ArrayOf<String>>& eventNames)
{
    eventNames = JSON::ArrayOf<String>::create();

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

void InspectorDOMAgent::getDataBindingsForNode(ErrorString& errorString, int /* nodeId */, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::DataBinding>>& /* dataBindings */)
{
    errorString = "Not supported"_s;
}

void InspectorDOMAgent::getAssociatedDataForNode(ErrorString& errorString, int /* nodeId */, Optional<String>& /* associatedData */)
{
    errorString = "Not supported"_s;
}

void InspectorDOMAgent::getEventListenersForNode(ErrorString& errorString, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray)
{
    listenersArray = JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>::create();

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

    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 addListener = [&] (RegisteredEventListener& listener, const EventListenerInfo& info) {
        int identifier = 0;
        bool disabled = false;
        bool hasBreakpoint = false;

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

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

            identifier = inspectorEventListener.identifier;
            disabled = inspectorEventListener.disabled;
            hasBreakpoint = inspectorEventListener.hasBreakpoint;

            m_eventListenerEntries.add(identifier, inspectorEventListener);
        }

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

    // 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;
}

void InspectorDOMAgent::setEventListenerDisabled(ErrorString& errorString, int eventListenerId, bool disabled)
{
    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end()) {
        errorString = "Missing event listener for given eventListenerId"_s;
        return;
    }

    it->value.disabled = disabled;
}

void InspectorDOMAgent::setBreakpointForEventListener(ErrorString& errorString, int eventListenerId)
{
    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end()) {
        errorString = "Missing event listener for given eventListenerId"_s;
        return;
    }

    it->value.hasBreakpoint = true;
}

void InspectorDOMAgent::removeBreakpointForEventListener(ErrorString& errorString, int eventListenerId)
{
    auto it = m_eventListenerEntries.find(eventListenerId);
    if (it == m_eventListenerEntries.end()) {
        errorString = "Missing event listener for given eventListenerId"_s;
        return;
    }

    it->value.hasBreakpoint = false;
}

void InspectorDOMAgent::getAccessibilityPropertiesForNode(ErrorString& errorString, int nodeId, RefPtr<Inspector::Protocol::DOM::AccessibilityProperties>& axProperties)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;

    axProperties = buildObjectForAccessibilityProperties(node);
}

void InspectorDOMAgent::performSearch(ErrorString& errorString, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount)
{
    // 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) {
            if (!nodeValue) {
                errorString = "Unexpected non-integer item in given nodeIds"_s;
                return;
            }
            int nodeId = 0;
            if (!nodeValue->asInteger(nodeId)) {
                errorString = "Unexpected non-integer item in given nodeIds"_s;
                return;
            }
            Node* node = assertNode(errorString, nodeId);
            if (!node) {
                // assertNode should have filled the errorString for us.
                ASSERT(errorString.length());
                return;
            }
            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());
    }

    *searchId = IdentifiersFactory::createIdentifier();

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

    *resultCount = resultsVector.size();
}

void InspectorDOMAgent::getSearchResults(ErrorString& errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<JSON::ArrayOf<int>>& nodeIds)
{
    SearchResults::iterator it = m_searchResults.find(searchId);
    if (it == m_searchResults.end()) {
        errorString = "Missing search result for given searchId"_s;
        return;
    }

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

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

void InspectorDOMAgent::discardSearchResults(ErrorString&, const String& searchId)
{
    m_searchResults.remove(searchId);
}

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)
{
    ErrorString ignored;
    RefPtr<Node> node = inspectedNode;
    setSearchingForNode(ignored, false, nullptr, false);

    if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
        node = node->parentNode();
    m_nodeToFocus = node;

    if (!m_nodeToFocus)
        return;

    focusNode();
}

void InspectorDOMAgent::focusNode()
{
    if (!m_documentRequested)
        return;

    ASSERT(m_nodeToFocus);

    RefPtr<Node> node = m_nodeToFocus.get();
    m_nodeToFocus = nullptr;

    Frame* frame = node->document().frame();
    if (!frame)
        return;

    JSC::JSGlobalObject* scriptState = mainWorldExecState(frame);
    InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(scriptState);
    if (injectedScript.hasNoValue())
        return;

    injectedScript.inspectObject(nodeAsScriptValue(*scriptState, 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();
    while (node && node->nodeType() == Node::TEXT_NODE)
        node = node->parentNode();
    if (node && m_inspectModeHighlightConfig)
        m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
}

void InspectorDOMAgent::setSearchingForNode(ErrorString& errorString, bool enabled, const 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, highlightInspectorObject);
        if (!m_inspectModeHighlightConfig)
            return;
        highlightMousedOverNode();
    } else
        hideHighlight(errorString);

    m_overlay->didSetSearchingForNode(m_searchingForNode);

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

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

    auto highlightConfig = makeUnique<HighlightConfig>();
    bool showInfo = false; // Default: false (do not show a tooltip).
    highlightInspectorObject->getBoolean("showInfo", showInfo);
    highlightConfig->showInfo = showInfo;
    highlightConfig->content = parseConfigColor("contentColor", highlightInspectorObject);
    highlightConfig->contentOutline = parseConfigColor("contentOutlineColor", highlightInspectorObject);
    highlightConfig->padding = parseConfigColor("paddingColor", highlightInspectorObject);
    highlightConfig->border = parseConfigColor("borderColor", highlightInspectorObject);
    highlightConfig->margin = parseConfigColor("marginColor", highlightInspectorObject);
    return highlightConfig;
}

void InspectorDOMAgent::setInspectModeEnabled(ErrorString& errorString, bool enabled, const JSON::Object* highlightConfig, const bool* showRulers)
{
    setSearchingForNode(errorString, enabled, highlightConfig ? highlightConfig : nullptr, showRulers && *showRulers);
}

void InspectorDOMAgent::highlightRect(ErrorString&, int x, int y, int width, int height, const JSON::Object* color, const JSON::Object* outlineColor, const bool* usePageCoordinates)
{
    auto quad = makeUnique<FloatQuad>(FloatRect(x, y, width, height));
    innerHighlightQuad(WTFMove(quad), color, outlineColor, usePageCoordinates);
}

void InspectorDOMAgent::highlightQuad(ErrorString& errorString, const JSON::Array& quadArray, const JSON::Object* color, const JSON::Object* outlineColor, const bool* usePageCoordinates)
{
    auto quad = makeUnique<FloatQuad>();
    if (!parseQuad(quadArray, quad.get())) {
        errorString = "Unexpected invalid quadArray"_s;
        return;
    }
    innerHighlightQuad(WTFMove(quad), color, outlineColor, usePageCoordinates);
}

void InspectorDOMAgent::innerHighlightQuad(std::unique_ptr<FloatQuad> quad, const JSON::Object* color, const JSON::Object* outlineColor, const bool* usePageCoordinates)
{
    auto highlightConfig = makeUnique<HighlightConfig>();
    highlightConfig->content = parseColor(color);
    highlightConfig->contentOutline = parseColor(outlineColor);
    highlightConfig->usePageCoordinates = usePageCoordinates ? *usePageCoordinates : false;
    m_overlay->highlightQuad(WTFMove(quad), *highlightConfig);
}

void InspectorDOMAgent::highlightSelector(ErrorString& errorString, const JSON::Object& highlightInspectorObject, const String& selectorString, const String* frameId)
{
    RefPtr<Document> document;

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

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

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

    if (!document) {
        errorString = "Missing document of frame for given frameId"_s;
        return;
    }

    auto queryResult = document->querySelectorAll(selectorString);
    // FIXME: <https://webkit.org/b/146161> Web Inspector: DOM.highlightSelector should work for "a:visited"
    if (queryResult.hasException()) {
        errorString = "DOM Error while querying with given selectorString"_s;
        return;
    }

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

    m_overlay->highlightNodeList(queryResult.releaseReturnValue(), *highlightConfig);
}

void InspectorDOMAgent::highlightNode(ErrorString& errorString, const JSON::Object& highlightInspectorObject, const int* nodeId, const String* objectId)
{
    Node* node = nullptr;
    if (nodeId)
        node = assertNode(errorString, *nodeId);
    else if (objectId) {
        node = nodeForObjectId(*objectId);
        if (!node)
            errorString = "Missing node for given objectId"_s;
    } else
        errorString = "Either nodeId or objectId must be specified"_s;

    if (!node)
        return;

    std::unique_ptr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, &highlightInspectorObject);
    if (!highlightConfig)
        return;

    m_overlay->highlightNode(node, *highlightConfig);
}

void InspectorDOMAgent::highlightNodeList(ErrorString& errorString, const JSON::Array& nodeIds, const JSON::Object& highlightInspectorObject)
{
    Vector<Ref<Node>> nodes;
    for (auto& nodeValue : nodeIds) {
        if (!nodeValue) {
            errorString = "Unexpected non-integer item in given nodeIds"_s;
            return;
        }

        int nodeId = 0;
        if (!nodeValue->asInteger(nodeId)) {
            errorString = "Unexpected non-integer item in given nodeIds"_s;
            return;
        }

        // 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. 
        ErrorString ignored;
        Node* node = assertNode(ignored, nodeId);
        if (!node)
            continue;

        nodes.append(*node);
    }

    std::unique_ptr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, &highlightInspectorObject);
    if (!highlightConfig)
        return;

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

void InspectorDOMAgent::highlightFrame(ErrorString& errorString, const String& frameId, const JSON::Object* color, const JSON::Object* outlineColor)
{
    auto* pageAgent = m_instrumentingAgents.inspectorPageAgent();
    if (!pageAgent) {
        errorString = "Page domain must be enabled"_s;
        return;
    }

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

    if (frame->ownerElement()) {
        auto highlightConfig = makeUnique<HighlightConfig>();
        highlightConfig->showInfo = true; // Always show tooltips for frames.
        highlightConfig->content = parseColor(color);
        highlightConfig->contentOutline = parseColor(outlineColor);
        m_overlay->highlightNode(frame->ownerElement(), *highlightConfig);
    }
}

void InspectorDOMAgent::hideHighlight(ErrorString&)
{
    m_overlay->hideHighlight();
}

void InspectorDOMAgent::moveTo(ErrorString& errorString, int nodeId, int targetElementId, const int* anchorNodeId, int* newNodeId)
{
    Node* node = assertEditableNode(errorString, nodeId);
    if (!node)
        return;

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

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

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

    *newNodeId = pushNodePathToFrontend(node);
}

void InspectorDOMAgent::undo(ErrorString& errorString)
{
    auto result = m_history->undo();
    if (result.hasException())
        errorString = toErrorString(result.releaseException());
}

void InspectorDOMAgent::redo(ErrorString& errorString)
{
    auto result = m_history->redo();
    if (result.hasException())
        errorString = toErrorString(result.releaseException());
}

void InspectorDOMAgent::markUndoableState(ErrorString&)
{
    m_history->markUndoableState();
}

void InspectorDOMAgent::focus(ErrorString& errorString, int nodeId)
{
    Element* element = assertElement(errorString, nodeId);
    if (!element)
        return;
    if (!element->isFocusable()) {
        errorString = "Element for given nodeId is not focusable"_s;
        return;
    }
    element->focus();
}

void InspectorDOMAgent::setInspectedNode(ErrorString& errorString, int nodeId)
{
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;

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

    m_inspectedNode = node;

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

    m_suppressEventListenerChangedEvent = false;
}

void InspectorDOMAgent::resolveNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
{
    String objectGroupName = objectGroup ? *objectGroup : emptyString();
    Node* node = assertNode(errorString, nodeId);
    if (!node)
        return;
    RefPtr<Inspector::Protocol::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
    if (!object) {
        errorString = "Missing injected script for given nodeId"_s;
        return;
    }
    result = object;
}

void InspectorDOMAgent::getAttributes(ErrorString& errorString, int nodeId, RefPtr<JSON::ArrayOf<String>>& result)
{
    Element* element = assertElement(errorString, nodeId);
    if (!element)
        return;

    result = buildArrayForElementAttributes(element);
}

void InspectorDOMAgent::requestNode(ErrorString&, const String& objectId, int* nodeId)
{
    Node* node = nodeForObjectId(objectId);
    if (node)
        *nodeId = pushNodePathToFrontend(node);
    else
        *nodeId = 0;
}

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, Inspector::Protocol::DOM::PseudoType* type)
{
    switch (pseudoId) {
    case PseudoId::Before:
        *type = Inspector::Protocol::DOM::PseudoType::Before;
        return true;
    case PseudoId::After:
        *type = Inspector::Protocol::DOM::PseudoType::After;
        return true;
    default:
        return false;
    }
}

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

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

static Inspector::Protocol::DOM::CustomElementState customElementState(const Element& element)
{
    if (element.isDefinedCustomElement())
        return Inspector::Protocol::DOM::CustomElementState::Custom;
    if (element.isFailedCustomElement())
        return Inspector::Protocol::DOM::CustomElementState::Failed;
    if (element.isUndefinedCustomElement() || element.isCustomElementUpgradeCandidate())
        return Inspector::Protocol::DOM::CustomElementState::Waiting;
    return Inspector::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>.
    TextEncoding documentEncoding = element.document().textEncoding();
    const TextEncoding& encodingToUse = documentEncoding.isValid() ? documentEncoding : UTF8Encoding();
    auto content = encodingToUse.encode(TextNodeTraversal::contentsAsString(element), 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-", base64Encode(digest.data(), digest.size()));
}

Ref<Inspector::Protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
{
    int id = bind(node, nodesMap);
    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 = nodeValue.left(maxTextSize);
            nodeValue.append(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 = Inspector::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);
        Ref<JSON::ArrayOf<Inspector::Protocol::DOM::Node>> children = buildArrayForContainerChildren(node, depth, nodesMap);
        if (children->length() > 0)
            value->setChildren(WTFMove(children));
    }

    auto* pageAgent = m_instrumentingAgents.inspectorPageAgent();
    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, nodesMap));
        }

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

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

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

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

        if (element.pseudoId() != PseudoId::None) {
            Inspector::Protocol::DOM::PseudoType pseudoType;
            if (pseudoElementType(element.pseudoId(), &pseudoType))
                value->setPseudoType(pseudoType);
        } else {
            if (auto pseudoElements = buildArrayForPseudoElements(element, nodesMap))
                value->setPseudoElements(WTFMove(pseudoElements));
        }
    } 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<Inspector::Protocol::DOM::Node>> InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
{
    auto children = JSON::ArrayOf<Inspector::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, nodesMap));
            m_childrenRequested.add(bind(container, nodesMap));
        }
        return children;
    }

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

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

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

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

Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, int identifier, EventTarget& eventTarget, const AtomString& eventType, bool disabled, bool hasBreakpoint)
{
    Ref<EventListener> eventListener = registeredEventListener.callback();

    String handlerName;
    int lineNumber = 0;
    int columnNumber = 0;
    String scriptID;
    if (is<JSEventListener>(eventListener.get())) {
        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* exec = nullptr;

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

        if (document) {
            handlerObject = scriptListener.jsFunction(*document);
            exec = execStateFromNode(scriptListener.isolatedWorld(), document);
        }

        if (handlerObject && exec) {
            JSC::VM& vm = exec->vm();
            JSC::JSFunction* handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(vm, 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(exec, JSC::Identifier::fromString(vm, "handleEvent"));

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

                if (handleEventValue)
                    handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(vm, 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 = Inspector::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 = Inspector::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 (hasBreakpoint)
        value->setHasBreakpoint(hasBreakpoint);
    return value;
}

void InspectorDOMAgent::processAccessibilityChildren(AccessibilityObject& axObject, JSON::ArrayOf<int>& 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);
    }
}
    
RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> InspectorDOMAgent::buildObjectForAccessibilityProperties(Node* node)
{
    ASSERT(node);
    if (!node)
        return nullptr;

    if (!WebCore::AXObjectCache::accessibilityEnabled())
        WebCore::AXObjectCache::enableAccessibility();

    Node* activeDescendantNode = nullptr;
    bool busy = false;
    auto checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::False;
    RefPtr<JSON::ArrayOf<int>> childNodeIds;
    RefPtr<JSON::ArrayOf<int>> controlledNodeIds;
    auto currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::False;
    bool exists = false;
    bool expanded = false;
    bool disabled = false;
    RefPtr<JSON::ArrayOf<int>> flowedNodeIds;
    bool focused = false;
    bool ignored = true;
    bool ignoredByDefault = false;
    auto invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False;
    bool hidden = false;
    String label;
    bool liveRegionAtomic = false;
    RefPtr<JSON::ArrayOf<String>> liveRegionRelevant;
    auto liveRegionStatus = Inspector::Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Off;
    Node* mouseEventNode = nullptr;
    RefPtr<JSON::ArrayOf<int>> ownedNodeIds;
    Node* parentNode = nullptr;
    bool pressed = false;
    bool readonly = false;
    bool required = false;
    String role;
    bool selected = false;
    RefPtr<JSON::ArrayOf<int>> 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 (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
        if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node)) {

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

            // An AX object is "busy" if it or any ancestor has aria-busy="true" set.
            AccessibilityObject* 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 = Inspector::Protocol::DOM::AccessibilityProperties::Checked::True;
                else if (checkValue == AccessibilityButtonState::Mixed)
                    checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::Mixed;
                else if (axObject->isChecked()) // Native checkbox.
                    checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::True;
            }
            
            if (!axObject->children().isEmpty()) {
                childNodeIds = JSON::ArrayOf<int>::create();
                processAccessibilityChildren(*axObject, *childNodeIds);
            }
            
            Vector<Element*> controlledElements;
            axObject->elementsFromAttribute(controlledElements, aria_controlsAttr);
            if (controlledElements.size()) {
                controlledNodeIds = JSON::ArrayOf<int>::create();
                for (Element* controlledElement : controlledElements)
                    controlledNodeIds->addItem(pushNodePathToFrontend(controlledElement));
            }
            
            switch (axObject->currentState()) {
            case AccessibilityCurrentState::False:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::False;
                break;
            case AccessibilityCurrentState::Page:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::Page;
                break;
            case AccessibilityCurrentState::Step:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::Step;
                break;
            case AccessibilityCurrentState::Location:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::Location;
                break;
            case AccessibilityCurrentState::Date:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::Date;
                break;
            case AccessibilityCurrentState::Time:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::Time;
                break;
            case AccessibilityCurrentState::True:
                currentState = Inspector::Protocol::DOM::AccessibilityProperties::Current::True;
                break;
            }

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

            Vector<Element*> flowedElements;
            axObject->elementsFromAttribute(flowedElements, aria_flowtoAttr);
            if (flowedElements.size()) {
                flowedNodeIds = JSON::ArrayOf<int>::create();
                for (Element* flowedElement : flowedElements)
                    flowedNodeIds->addItem(pushNodePathToFrontend(flowedElement));
            }
            
            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")
                invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False;
            else if (invalidValue == "grammar")
                invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::Grammar;
            else if (invalidValue == "spelling")
                invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::Spelling;
            else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size.
                invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::True;
            
            if (axObject->isAXHidden() || axObject->isDOMHidden())
                hidden = true;
            
            label = axObject->computedLabel();

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

                String ariaRelevantAttrValue = axObject->liveRegionRelevant();
                if (!ariaRelevantAttrValue.isEmpty()) {
                    // FIXME: Pass enum values rather than strings once unblocked. http://webkit.org/b/133711
                    String ariaRelevantAdditions = Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Additions);
                    String ariaRelevantRemovals = Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Removals);
                    String ariaRelevantText = Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Text);
                    liveRegionRelevant = JSON::ArrayOf<String>::create();
                    const SpaceSplitString& values = SpaceSplitString(ariaRelevantAttrValue, true);
                    // @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")) {
                        liveRegionRelevant->addItem(ariaRelevantAdditions);
                        liveRegionRelevant->addItem(ariaRelevantRemovals);
                        liveRegionRelevant->addItem(ariaRelevantText);
                    } else {
                        if (values.contains(ariaRelevantAdditions))
                            liveRegionRelevant->addItem(ariaRelevantAdditions);
                        if (values.contains(ariaRelevantRemovals))
                            liveRegionRelevant->addItem(ariaRelevantRemovals);
                        if (values.contains(ariaRelevantText))
                            liveRegionRelevant->addItem(ariaRelevantText);
                    }
                }

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

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

            if (axObject->supportsARIAOwns()) {
                Vector<Element*> ownedElements;
                axObject->elementsFromAttribute(ownedElements, aria_ownsAttr);
                if (ownedElements.size()) {
                    ownedNodeIds = JSON::ArrayOf<int>::create();
                    for (Element* ownedElement : ownedElements)
                        ownedNodeIds->addItem(pushNodePathToFrontend(ownedElement));
                }
            }

            if (AccessibilityObject* 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();

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

    if (exists) {
        if (activeDescendantNode)
            value->setActiveDescendantNodeId(pushNodePathToFrontend(activeDescendantNode));
        if (busy)
            value->setBusy(busy);
        if (supportsChecked)
            value->setChecked(checked);
        if (childNodeIds)
            value->setChildNodeIds(childNodeIds);
        if (controlledNodeIds)
            value->setControlledNodeIds(controlledNodeIds);
        if (currentState != Inspector::Protocol::DOM::AccessibilityProperties::Current::False)
            value->setCurrent(currentState);
        if (disabled)
            value->setDisabled(disabled);
        if (supportsExpanded)
            value->setExpanded(expanded);
        if (flowedNodeIds)
            value->setFlowedNodeIds(flowedNodeIds);
        if (supportsFocused)
            value->setFocused(focused);
        if (ignored)
            value->setIgnored(ignored);
        if (ignoredByDefault)
            value->setIgnoredByDefault(ignoredByDefault);
        if (invalid != Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False)
            value->setInvalid(invalid);
        if (hidden)
            value->setHidden(hidden);
        if (supportsLiveRegion) {
            value->setLiveRegionAtomic(liveRegionAtomic);
            if (liveRegionRelevant->length())
                value->setLiveRegionRelevant(liveRegionRelevant);
            value->setLiveRegionStatus(liveRegionStatus);
        }
        if (mouseEventNode)
            value->setMouseEventNodeId(pushNodePathToFrontend(mouseEventNode));
        if (ownedNodeIds)
            value->setOwnedNodeIds(ownedNodeIds);
        if (parentNode)
            value->setParentNodeId(pushNodePathToFrontend(parentNode));
        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);
        
        // 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;

    int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
    if (!frameOwnerId)
        return;

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

    Ref<Inspector::Protocol::DOM::Node> value = buildObjectForNode(frameOwner.get(), 0, &m_documentNodeToIdMap);
    Node* previousSibling = innerPreviousSibling(frameOwner.get());
    int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
    m_frontendDispatcher->childNodeInserted(parentId, prevId, WTFMove(value));
}

int 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, &m_documentNodeToIdMap);

    ContainerNode* parent = node.parentNode();
    if (!parent)
        return;

    int parentId = m_documentNodeToIdMap.get(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);
        int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
        Ref<Inspector::Protocol::DOM::Node> value = buildObjectForNode(&node, 0, &m_documentNodeToIdMap);
        m_frontendDispatcher->childNodeInserted(parentId, prevId, WTFMove(value));
    }
}

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

    ContainerNode* parent = node.parentNode();

    // If parent is not mapped yet -> ignore the event.
    if (!m_documentNodeToIdMap.contains(parent))
        return;

    int parentId = m_documentNodeToIdMap.get(parent);

    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, m_documentNodeToIdMap.get(&node));
    unbind(&node, &m_documentNodeToIdMap);
}

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;

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

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

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

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

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

    m_frontendDispatcher->attributeRemoved(id, name);
}

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

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

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

void InspectorDOMAgent::characterDataModified(CharacterData& characterData)
{
    int id = m_documentNodeToIdMap.get(&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)
{
    int id = m_documentNodeToIdMap.get(&element);
    if (!id)
        return;

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

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

void InspectorDOMAgent::willPopShadowRoot(Element& host, ShadowRoot& root)
{
    int hostId = m_documentNodeToIdMap.get(&host);
    int rootId = m_documentNodeToIdMap.get(&root);
    if (hostId && rootId)
        m_frontendDispatcher->shadowRootPopped(hostId, rootId);
}

void InspectorDOMAgent::didChangeCustomElementState(Element& element)
{
    int elementId = m_documentNodeToIdMap.get(&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;

    int parentId = m_documentNodeToIdMap.get(parent);
    if (!parentId)
        return;

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

void InspectorDOMAgent::pseudoElementDestroyed(PseudoElement& pseudoElement)
{
    int pseudoElementId = m_documentNodeToIdMap.get(&pseudoElement);
    if (!pseudoElementId)
        return;

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

    unbind(&pseudoElement, &m_documentNodeToIdMap);
    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;

    int 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;

    int 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);
}

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

int 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;

            int nodeId = pushNodePathToFrontend(mediaElement);
            if (nodeId) {
                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();
    Vector<String> pathTokens = path.split(',');
    if (!pathTokens.size())
        return nullptr;

    for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
        bool success = true;
        unsigned childNumber = pathTokens[i].toUInt(&success);
        if (!success)
            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);
        }

        const auto& childName = pathTokens[i + 1];
        if (!child || child->nodeName() != childName)
            return nullptr;
        node = child;
    }
    return node;
}

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

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

void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString& errorString, const String& path, int* nodeId)
{
    if (Node* node = nodeForPath(path))
        *nodeId = pushNodePathToFrontend(node);
    else
        errorString = "Missing node for given path"_s;
}

RefPtr<Inspector::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& state = *mainWorldExecState(frame);
    auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
    if (injectedScript.hasNoValue())
        return nullptr;

    return injectedScript.wrapObject(nodeAsScriptValue(state, 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));
}

void InspectorDOMAgent::setAllowEditingUserAgentShadowTrees(ErrorString&, bool allow)
{
    m_allowEditingUserAgentShadowTrees = allow;
}

} // namespace WebCore
