/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * 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 "InspectorOverlay.h"

#include "CacheStorageProvider.h"
#include "DocumentLoader.h"
#include "EditorClient.h"
#include "Element.h"
#include "EmptyClients.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "InspectorClient.h"
#include "InspectorOverlayPage.h"
#include "LibWebRTCProvider.h"
#include "MainFrame.h"
#include "Node.h"
#include "Page.h"
#include "PageConfiguration.h"
#include "PolygonShape.h"
#include "PseudoElement.h"
#include "RTCController.h"
#include "RectangleShape.h"
#include "RenderBoxModelObject.h"
#include "RenderElement.h"
#include "RenderInline.h"
#include "RenderView.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
#include "Settings.h"
#include "SocketProvider.h"
#include "StyledElement.h"
#include <JavaScriptCore/InspectorProtocolObjects.h>
#include <wtf/JSONValues.h>


namespace WebCore {

using namespace Inspector;

static void contentsQuadToCoordinateSystem(const FrameView* mainView, const FrameView* view, FloatQuad& quad, InspectorOverlay::CoordinateSystem coordinateSystem)
{
    quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
    quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
    quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
    quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));

    if (coordinateSystem == InspectorOverlay::CoordinateSystem::View)
        quad += toIntSize(mainView->scrollPosition());
}

static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
{
    contentsQuadToCoordinateSystem(mainView, view, quad, InspectorOverlay::CoordinateSystem::View);
}

static void buildRendererHighlight(RenderObject* renderer, const HighlightConfig& highlightConfig, Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
{
    Frame* containingFrame = renderer->document().frame();
    if (!containingFrame)
        return;

    highlight.setDataFromConfig(highlightConfig);
    FrameView* containingView = containingFrame->view();
    FrameView* mainView = containingFrame->page()->mainFrame().view();

    // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
    bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();

    if (isSVGRenderer) {
        highlight.type = HighlightType::Rects;
        renderer->absoluteQuads(highlight.quads);
        for (auto& quad : highlight.quads)
            contentsQuadToCoordinateSystem(mainView, containingView, quad, coordinateSystem);
    } else if (is<RenderBox>(*renderer) || is<RenderInline>(*renderer)) {
        LayoutRect contentBox;
        LayoutRect paddingBox;
        LayoutRect borderBox;
        LayoutRect marginBox;

        if (is<RenderBox>(*renderer)) {
            auto& renderBox = downcast<RenderBox>(*renderer);

            LayoutBoxExtent margins(renderBox.marginTop(), renderBox.marginRight(), renderBox.marginBottom(), renderBox.marginLeft());
            paddingBox = renderBox.clientBoxRect();
            contentBox = LayoutRect(paddingBox.x() + renderBox.paddingLeft(), paddingBox.y() + renderBox.paddingTop(),
                paddingBox.width() - renderBox.paddingLeft() - renderBox.paddingRight(), paddingBox.height() - renderBox.paddingTop() - renderBox.paddingBottom());
            borderBox = LayoutRect(paddingBox.x() - renderBox.borderLeft(), paddingBox.y() - renderBox.borderTop(),
                paddingBox.width() + renderBox.borderLeft() + renderBox.borderRight(), paddingBox.height() + renderBox.borderTop() + renderBox.borderBottom());
            marginBox = LayoutRect(borderBox.x() - margins.left(), borderBox.y() - margins.top(),
                borderBox.width() + margins.left() + margins.right(), borderBox.height() + margins.top() + margins.bottom());
        } else {
            auto& renderInline = downcast<RenderInline>(*renderer);

            // RenderInline's bounding box includes paddings and borders, excludes margins.
            borderBox = renderInline.linesBoundingBox();
            paddingBox = LayoutRect(borderBox.x() + renderInline.borderLeft(), borderBox.y() + renderInline.borderTop(),
                borderBox.width() - renderInline.borderLeft() - renderInline.borderRight(), borderBox.height() - renderInline.borderTop() - renderInline.borderBottom());
            contentBox = LayoutRect(paddingBox.x() + renderInline.paddingLeft(), paddingBox.y() + renderInline.paddingTop(),
                paddingBox.width() - renderInline.paddingLeft() - renderInline.paddingRight(), paddingBox.height() - renderInline.paddingTop() - renderInline.paddingBottom());
            // Ignore marginTop and marginBottom for inlines.
            marginBox = LayoutRect(borderBox.x() - renderInline.marginLeft(), borderBox.y(),
                borderBox.width() + renderInline.horizontalMarginExtent(), borderBox.height());
        }

        FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
        FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
        FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
        FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));

        contentsQuadToCoordinateSystem(mainView, containingView, absContentQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absPaddingQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absBorderQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absMarginQuad, coordinateSystem);

        highlight.type = HighlightType::Node;
        highlight.quads.append(absMarginQuad);
        highlight.quads.append(absBorderQuad);
        highlight.quads.append(absPaddingQuad);
        highlight.quads.append(absContentQuad);
    }
}

static void buildNodeHighlight(Node& node, const HighlightConfig& highlightConfig, Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
{
    RenderObject* renderer = node.renderer();
    if (!renderer)
        return;

    buildRendererHighlight(renderer, highlightConfig, highlight, coordinateSystem);
}

static void buildQuadHighlight(const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight& highlight)
{
    highlight.setDataFromConfig(highlightConfig);
    highlight.type = HighlightType::Rects;
    highlight.quads.append(quad);
}

InspectorOverlay::InspectorOverlay(Page& page, InspectorClient* client)
    : m_page(page)
    , m_client(client)
    , m_paintRectUpdateTimer(*this, &InspectorOverlay::updatePaintRectsTimerFired)
{
}

InspectorOverlay::~InspectorOverlay() = default;

void InspectorOverlay::paint(GraphicsContext& context)
{
    if (!shouldShowOverlay())
        return;

    GraphicsContextStateSaver stateSaver(context);
    FrameView* view = overlayPage()->mainFrame().view();
    view->updateLayoutAndStyleIfNeededRecursive();
    view->paint(context, IntRect(0, 0, view->width(), view->height()));
}

void InspectorOverlay::getHighlight(Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem) const
{
    if (!m_highlightNode && !m_highlightQuad && !m_highlightNodeList)
        return;

    highlight.type = HighlightType::Rects;
    if (m_highlightNode)
        buildNodeHighlight(*m_highlightNode, m_nodeHighlightConfig, highlight, coordinateSystem);
    else if (m_highlightNodeList) {
        highlight.setDataFromConfig(m_nodeHighlightConfig);
        for (unsigned i = 0; i < m_highlightNodeList->length(); ++i) {
            Highlight nodeHighlight;
            buildNodeHighlight(*(m_highlightNodeList->item(i)), m_nodeHighlightConfig, nodeHighlight, coordinateSystem);
            if (nodeHighlight.type == HighlightType::Node)
                highlight.quads.appendVector(nodeHighlight.quads);
        }
        highlight.type = HighlightType::NodeList;
    } else
        buildQuadHighlight(*m_highlightQuad, m_quadHighlightConfig, highlight);
}

void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
{
    m_pausedInDebuggerMessage = message ? *message : String();
    update();
}

void InspectorOverlay::hideHighlight()
{
    m_highlightNode = nullptr;
    m_highlightNodeList = nullptr;
    m_highlightQuad = nullptr;
    update();
}

void InspectorOverlay::highlightNodeList(RefPtr<NodeList>&& nodes, const HighlightConfig& highlightConfig)
{
    m_nodeHighlightConfig = highlightConfig;
    m_highlightNodeList = WTFMove(nodes);
    m_highlightNode = nullptr;
    update();
}

void InspectorOverlay::highlightNode(Node* node, const HighlightConfig& highlightConfig)
{
    m_nodeHighlightConfig = highlightConfig;
    m_highlightNode = node;
    m_highlightNodeList = nullptr;
    update();
}

void InspectorOverlay::highlightQuad(std::unique_ptr<FloatQuad> quad, const HighlightConfig& highlightConfig)
{
    if (highlightConfig.usePageCoordinates)
        *quad -= toIntSize(m_page.mainFrame().view()->scrollPosition());

    m_quadHighlightConfig = highlightConfig;
    m_highlightQuad = WTFMove(quad);
    update();
}

Node* InspectorOverlay::highlightedNode() const
{
    return m_highlightNode.get();
}

void InspectorOverlay::didSetSearchingForNode(bool enabled)
{
    m_client->didSetSearchingForNode(enabled);
}

void InspectorOverlay::setIndicating(bool indicating)
{
    m_indicating = indicating;

    if (m_indicating)
        evaluateInOverlay(ASCIILiteral("showPageIndication"));
    else
        evaluateInOverlay(ASCIILiteral("hidePageIndication"));

    update();
}

bool InspectorOverlay::shouldShowOverlay() const
{
    return m_highlightNode || m_highlightNodeList || m_highlightQuad || m_indicating || m_showingPaintRects || !m_pausedInDebuggerMessage.isNull();
}

void InspectorOverlay::update()
{
    if (!shouldShowOverlay()) {
        m_client->hideHighlight();
        return;
    }

    FrameView* view = m_page.mainFrame().view();
    if (!view)
        return;

    FrameView* overlayView = overlayPage()->mainFrame().view();
    IntSize viewportSize = view->sizeForVisibleContent();
    IntSize frameViewFullSize = view->sizeForVisibleContent(ScrollableArea::IncludeScrollbars);
    overlayView->resize(frameViewFullSize);

    // Clear canvas and paint things.
    // FIXME: Remove extra parameter?
    reset(viewportSize, IntSize());

    // Include scrollbars to avoid masking them by the gutter.
    drawGutter();
    drawNodeHighlight();
    drawQuadHighlight();
    drawPausedInDebuggerMessage();
    drawPaintRects();

    // Position DOM elements.
    overlayPage()->mainFrame().document()->resolveStyle(Document::ResolveStyleType::Rebuild);
    if (overlayView->needsLayout())
        overlayView->layoutContext().layout();

    forcePaint();
}

static Ref<Inspector::Protocol::OverlayTypes::Point> buildObjectForPoint(const FloatPoint& point)
{
    return Inspector::Protocol::OverlayTypes::Point::create()
        .setX(point.x())
        .setY(point.y())
        .release();
}

static Ref<Inspector::Protocol::OverlayTypes::Rect> buildObjectForRect(const FloatRect& rect)
{
    return Inspector::Protocol::OverlayTypes::Rect::create()
        .setX(rect.x())
        .setY(rect.y())
        .setWidth(rect.width())
        .setHeight(rect.height())
        .release();
}

static Ref<Inspector::Protocol::OverlayTypes::Quad> buildArrayForQuad(const FloatQuad& quad)
{
    auto array = Inspector::Protocol::OverlayTypes::Quad::create();
    array->addItem(buildObjectForPoint(quad.p1()));
    array->addItem(buildObjectForPoint(quad.p2()));
    array->addItem(buildObjectForPoint(quad.p3()));
    array->addItem(buildObjectForPoint(quad.p4()));
    return array;
}

static Ref<Inspector::Protocol::OverlayTypes::FragmentHighlightData> buildObjectForHighlight(const Highlight& highlight)
{
    auto arrayOfQuads = JSON::ArrayOf<Inspector::Protocol::OverlayTypes::Quad>::create();
    for (auto& quad : highlight.quads)
        arrayOfQuads->addItem(buildArrayForQuad(quad));

    return Inspector::Protocol::OverlayTypes::FragmentHighlightData::create()
        .setQuads(WTFMove(arrayOfQuads))
        .setContentColor(highlight.contentColor.serialized())
        .setContentOutlineColor(highlight.contentOutlineColor.serialized())
        .setPaddingColor(highlight.paddingColor.serialized())
        .setBorderColor(highlight.borderColor.serialized())
        .setMarginColor(highlight.marginColor.serialized())
        .release();
}

static Ref<Inspector::Protocol::OverlayTypes::Size> buildObjectForSize(const IntSize& size)
{
    return Inspector::Protocol::OverlayTypes::Size::create()
        .setWidth(size.width())
        .setHeight(size.height())
        .release();
}

void InspectorOverlay::setShowingPaintRects(bool showingPaintRects)
{
    if (m_showingPaintRects == showingPaintRects)
        return;

    m_showingPaintRects = showingPaintRects;
    if (!m_showingPaintRects) {
        m_paintRects.clear();
        m_paintRectUpdateTimer.stop();
        drawPaintRects();
        forcePaint();
    }
}

void InspectorOverlay::showPaintRect(const FloatRect& rect)
{
    if (!m_showingPaintRects)
        return;

    IntRect rootRect = m_page.mainFrame().view()->contentsToRootView(enclosingIntRect(rect));

    const auto removeDelay = 250_ms;

    MonotonicTime removeTime = MonotonicTime::now() + removeDelay;
    m_paintRects.append(TimeRectPair(removeTime, rootRect));

    if (!m_paintRectUpdateTimer.isActive()) {
        const Seconds paintRectsUpdateInterval { 32_ms };
        m_paintRectUpdateTimer.startRepeating(paintRectsUpdateInterval);
    }

    drawPaintRects();
    forcePaint();
}

void InspectorOverlay::updatePaintRectsTimerFired()
{
    MonotonicTime now = MonotonicTime::now();
    bool rectsChanged = false;
    while (!m_paintRects.isEmpty() && m_paintRects.first().first < now) {
        m_paintRects.removeFirst();
        rectsChanged = true;
    }

    if (m_paintRects.isEmpty())
        m_paintRectUpdateTimer.stop();

    if (rectsChanged) {
        drawPaintRects();
        forcePaint();
    }
}

void InspectorOverlay::drawPaintRects()
{
    auto arrayOfRects = JSON::ArrayOf<Inspector::Protocol::OverlayTypes::Rect>::create();
    for (const auto& pair : m_paintRects)
        arrayOfRects->addItem(buildObjectForRect(pair.second));

    evaluateInOverlay(ASCIILiteral("updatePaintRects"), WTFMove(arrayOfRects));
}

void InspectorOverlay::drawGutter()
{
    evaluateInOverlay(ASCIILiteral("drawGutter"));
}

static RefPtr<JSON::ArrayOf<Inspector::Protocol::OverlayTypes::FragmentHighlightData>> buildArrayForRendererFragments(RenderObject* renderer, const HighlightConfig& config)
{
    auto arrayOfFragments = JSON::ArrayOf<Inspector::Protocol::OverlayTypes::FragmentHighlightData>::create();

    Highlight highlight;
    buildRendererHighlight(renderer, config, highlight, InspectorOverlay::CoordinateSystem::View);
    arrayOfFragments->addItem(buildObjectForHighlight(highlight));

    return WTFMove(arrayOfFragments);
}

static FloatPoint localPointToRoot(RenderObject* renderer, const FrameView* mainView, const FrameView* view, const FloatPoint& point)
{
    FloatPoint result = renderer->localToAbsolute(point);
    result = view->contentsToRootView(roundedIntPoint(result));
    result += toIntSize(mainView->scrollPosition());
    return result;
}

struct PathApplyInfo {
    FrameView* rootView;
    FrameView* view;
    Inspector::Protocol::OverlayTypes::DisplayPath* pathArray;
    RenderObject* renderer;
    const ShapeOutsideInfo* shapeOutsideInfo;
};

static void appendPathCommandAndPoints(PathApplyInfo& info, const String& command, const FloatPoint points[], unsigned length)
{
    FloatPoint point;
    info.pathArray->addItem(command);
    for (unsigned i = 0; i < length; i++) {
        point = info.shapeOutsideInfo->shapeToRendererPoint(points[i]);
        point = localPointToRoot(info.renderer, info.rootView, info.view, point);
        info.pathArray->addItem(point.x());
        info.pathArray->addItem(point.y());
    }
}

static void appendPathSegment(PathApplyInfo& pathApplyInfo, const PathElement& pathElement)
{
    FloatPoint point;
    switch (pathElement.type) {
    // The points member will contain 1 value.
    case PathElementMoveToPoint:
        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("M"), pathElement.points, 1);
        break;
    // The points member will contain 1 value.
    case PathElementAddLineToPoint:
        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("L"), pathElement.points, 1);
        break;
    // The points member will contain 3 values.
    case PathElementAddCurveToPoint:
        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("C"), pathElement.points, 3);
        break;
    // The points member will contain 2 values.
    case PathElementAddQuadCurveToPoint:
        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("Q"), pathElement.points, 2);
        break;
    // The points member will contain no values.
    case PathElementCloseSubpath:
        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("Z"), nullptr, 0);
        break;
    }
}

static RefPtr<Inspector::Protocol::OverlayTypes::ShapeOutsideData> buildObjectForShapeOutside(Frame* containingFrame, RenderBox* renderer)
{
    const ShapeOutsideInfo* shapeOutsideInfo = renderer->shapeOutsideInfo();
    if (!shapeOutsideInfo)
        return nullptr;

    LayoutRect shapeBounds = shapeOutsideInfo->computedShapePhysicalBoundingBox();
    FloatQuad shapeQuad = renderer->localToAbsoluteQuad(FloatRect(shapeBounds));
    contentsQuadToPage(containingFrame->page()->mainFrame().view(), containingFrame->view(), shapeQuad);

    auto shapeObject = Inspector::Protocol::OverlayTypes::ShapeOutsideData::create()
        .setBounds(buildArrayForQuad(shapeQuad))
        .release();

    Shape::DisplayPaths paths;
    shapeOutsideInfo->computedShape().buildDisplayPaths(paths);

    if (paths.shape.length()) {
        auto shapePath = Inspector::Protocol::OverlayTypes::DisplayPath::create();
        PathApplyInfo info;
        info.rootView = containingFrame->page()->mainFrame().view();
        info.view = containingFrame->view();
        info.pathArray = &shapePath.get();
        info.renderer = renderer;
        info.shapeOutsideInfo = shapeOutsideInfo;

        paths.shape.apply([&info](const PathElement& pathElement) {
            appendPathSegment(info, pathElement);
        });

        shapeObject->setShape(shapePath.copyRef());

        if (paths.marginShape.length()) {
            auto marginShapePath = Inspector::Protocol::OverlayTypes::DisplayPath::create();
            info.pathArray = &marginShapePath.get();

            paths.marginShape.apply([&info](const PathElement& pathElement) {
                appendPathSegment(info, pathElement);
            });

            shapeObject->setMarginShape(marginShapePath.copyRef());
        }
    }

    return WTFMove(shapeObject);
}

static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElementData(Node* node, HighlightType)
{
    if (!is<Element>(node) || !node->document().frame())
        return nullptr;

    Element* effectiveElement = downcast<Element>(node);
    if (node->isPseudoElement()) {
        Element* hostElement = downcast<PseudoElement>(*node).hostElement();
        if (!hostElement)
            return nullptr;
        effectiveElement = hostElement;
    }

    Element& element = *effectiveElement;
    bool isXHTML = element.document().isXHTMLDocument();
    auto elementData = Inspector::Protocol::OverlayTypes::ElementData::create()
        .setTagName(isXHTML ? element.nodeName() : element.nodeName().convertToASCIILowercase())
        .setIdValue(element.getIdAttribute())
        .release();

    if (element.hasClass() && is<StyledElement>(element)) {
        auto classes = JSON::ArrayOf<String>::create();
        HashSet<AtomicString> usedClassNames;
        const SpaceSplitString& classNamesString = downcast<StyledElement>(element).classNames();
        for (size_t i = 0; i < classNamesString.size(); ++i) {
            const AtomicString& className = classNamesString[i];
            if (usedClassNames.contains(className))
                continue;

            usedClassNames.add(className);
            classes->addItem(className);
        }
        elementData->setClasses(WTFMove(classes));
    }

    if (node->isPseudoElement()) {
        if (node->pseudoId() == BEFORE)
            elementData->setPseudoElement("before");
        else if (node->pseudoId() == AFTER)
            elementData->setPseudoElement("after");
    }

    RenderElement* renderer = element.renderer();
    if (!renderer)
        return nullptr;

    Frame* containingFrame = node->document().frame();
    FrameView* containingView = containingFrame->view();
    IntRect boundingBox = snappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
    RenderBoxModelObject* modelObject = is<RenderBoxModelObject>(*renderer) ? downcast<RenderBoxModelObject>(renderer) : nullptr;
    auto sizeObject = Inspector::Protocol::OverlayTypes::Size::create()
        .setWidth(modelObject ? adjustForAbsoluteZoom(roundToInt(modelObject->offsetWidth()), *modelObject) : boundingBox.width())
        .setHeight(modelObject ? adjustForAbsoluteZoom(roundToInt(modelObject->offsetHeight()), *modelObject) : boundingBox.height())
        .release();
    elementData->setSize(WTFMove(sizeObject));

    if (is<RenderBox>(*renderer)) {
        auto& renderBox = downcast<RenderBox>(*renderer);
        if (RefPtr<Inspector::Protocol::OverlayTypes::ShapeOutsideData> shapeObject = buildObjectForShapeOutside(containingFrame, &renderBox))
            elementData->setShapeOutsideData(WTFMove(shapeObject));
    }

    // Need to enable AX to get the computed role.
    if (!WebCore::AXObjectCache::accessibilityEnabled())
        WebCore::AXObjectCache::enableAccessibility();

    if (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
        if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node))
            elementData->setRole(axObject->computedRoleString());
    }

    return WTFMove(elementData);
}

RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorOverlay::buildHighlightObjectForNode(Node* node, HighlightType type) const
{
    if (!node)
        return nullptr;

    RenderObject* renderer = node->renderer();
    if (!renderer)
        return nullptr;

    RefPtr<JSON::ArrayOf<Inspector::Protocol::OverlayTypes::FragmentHighlightData>> arrayOfFragmentHighlights = buildArrayForRendererFragments(renderer, m_nodeHighlightConfig);
    if (!arrayOfFragmentHighlights)
        return nullptr;

    // The main view's scroll offset is shared across all quads.
    FrameView* mainView = m_page.mainFrame().view();

    auto nodeHighlightObject = Inspector::Protocol::OverlayTypes::NodeHighlightData::create()
        .setScrollOffset(buildObjectForPoint(!mainView->delegatesScrolling() ? mainView->visibleContentRect().location() : FloatPoint()))
        .setFragments(WTFMove(arrayOfFragmentHighlights))
        .release();

    if (m_nodeHighlightConfig.showInfo) {
        if (RefPtr<Inspector::Protocol::OverlayTypes::ElementData> elementData = buildObjectForElementData(node, type))
            nodeHighlightObject->setElementData(WTFMove(elementData));
    }

    return WTFMove(nodeHighlightObject);
}

Ref<JSON::ArrayOf<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorOverlay::buildObjectForHighlightedNodes() const
{
    auto highlights = JSON::ArrayOf<Inspector::Protocol::OverlayTypes::NodeHighlightData>::create();

    if (m_highlightNode) {
        if (RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> nodeHighlightData = buildHighlightObjectForNode(m_highlightNode.get(), HighlightType::Node))
            highlights->addItem(WTFMove(nodeHighlightData));
    } else if (m_highlightNodeList) {
        for (unsigned i = 0; i < m_highlightNodeList->length(); ++i) {
            if (RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> nodeHighlightData = buildHighlightObjectForNode(m_highlightNodeList->item(i), HighlightType::NodeList))
                highlights->addItem(WTFMove(nodeHighlightData));
        }
    }

    return highlights;
}

void InspectorOverlay::drawNodeHighlight()
{
    if (m_highlightNode || m_highlightNodeList)
        evaluateInOverlay("drawNodeHighlight", buildObjectForHighlightedNodes());
}

void InspectorOverlay::drawQuadHighlight()
{
    if (!m_highlightQuad)
        return;

    Highlight highlight;
    buildQuadHighlight(*m_highlightQuad, m_quadHighlightConfig, highlight);
    evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
}

void InspectorOverlay::drawPausedInDebuggerMessage()
{
    if (!m_pausedInDebuggerMessage.isNull())
        evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
}

Page* InspectorOverlay::overlayPage()
{
    if (m_overlayPage)
        return m_overlayPage.get();

    PageConfiguration pageConfiguration(
        createEmptyEditorClient(),
        SocketProvider::create(),
        LibWebRTCProvider::create(),
        CacheStorageProvider::create()
    );
    fillWithEmptyClients(pageConfiguration);
    m_overlayPage = std::make_unique<Page>(WTFMove(pageConfiguration));
    m_overlayPage->setDeviceScaleFactor(m_page.deviceScaleFactor());

    Settings& settings = m_page.settings();
    Settings& overlaySettings = m_overlayPage->settings();

    overlaySettings.setStandardFontFamily(settings.standardFontFamily());
    overlaySettings.setSerifFontFamily(settings.serifFontFamily());
    overlaySettings.setSansSerifFontFamily(settings.sansSerifFontFamily());
    overlaySettings.setCursiveFontFamily(settings.cursiveFontFamily());
    overlaySettings.setFantasyFontFamily(settings.fantasyFontFamily());
    overlaySettings.setPictographFontFamily(settings.pictographFontFamily());
    overlaySettings.setMinimumFontSize(settings.minimumFontSize());
    overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
    overlaySettings.setMediaEnabled(false);
    overlaySettings.setScriptEnabled(true);
    overlaySettings.setPluginsEnabled(false);

    Frame& frame = m_overlayPage->mainFrame();
    frame.setView(FrameView::create(frame));
    frame.init();
    FrameLoader& loader = frame.loader();
    frame.view()->setCanHaveScrollbars(false);
    frame.view()->setTransparent(true);
    ASSERT(loader.activeDocumentLoader());
    loader.activeDocumentLoader()->writer().setMIMEType("text/html");
    loader.activeDocumentLoader()->writer().begin();
    loader.activeDocumentLoader()->writer().addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
    loader.activeDocumentLoader()->writer().end();

#if OS(WINDOWS)
    evaluateInOverlay("setPlatform", "windows");
#elif OS(MAC_OS_X)
    evaluateInOverlay("setPlatform", "mac");
#elif OS(UNIX)
    evaluateInOverlay("setPlatform", "linux");
#endif

    return m_overlayPage.get();
}

void InspectorOverlay::forcePaint()
{
    // This overlay page is very weird and doesn't automatically paint. We have to force paints manually.
    m_client->highlight();
}

void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize)
{
    auto configObject = Inspector::Protocol::OverlayTypes::OverlayConfiguration::create()
        .setDeviceScaleFactor(m_page.deviceScaleFactor())
        .setViewportSize(buildObjectForSize(viewportSize))
        .setFrameViewFullSize(buildObjectForSize(frameViewFullSize))
        .release();
    evaluateInOverlay("reset", WTFMove(configObject));
}

static void evaluateCommandInOverlay(Page* page, Ref<JSON::Array>&& command)
{
    page->mainFrame().script().evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ')')));
}

void InspectorOverlay::evaluateInOverlay(const String& method)
{
    Ref<JSON::Array> command = JSON::Array::create();
    command->pushString(method);

    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
}

void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
{
    Ref<JSON::Array> command = JSON::Array::create();
    command->pushString(method);
    command->pushString(argument);

    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
}

void InspectorOverlay::evaluateInOverlay(const String& method, RefPtr<JSON::Value>&& argument)
{
    Ref<JSON::Array> command = JSON::Array::create();
    command->pushString(method);
    command->pushValue(WTFMove(argument));

    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
}

void InspectorOverlay::freePage()
{
    m_overlayPage = nullptr;
}

} // namespace WebCore
