Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / inspector / InspectorOverlay.cpp
index 64aaec9..bceb8f0 100644 (file)
@@ -10,7 +10,7 @@
  * 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 Computer, Inc. ("Apple") nor the names of
+ * 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.
  *
  */
 
 #include "config.h"
-
-#if ENABLE(INSPECTOR)
-
 #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 "RenderFlowThread.h"
 #include "RenderInline.h"
-#include "RenderNamedFlowFragment.h"
-#include "RenderNamedFlowThread.h"
-#include "RenderRegion.h"
 #include "RenderView.h"
 #include "ScriptController.h"
 #include "ScriptSourceCode.h"
 #include "Settings.h"
+#include "SocketProvider.h"
 #include "StyledElement.h"
-#include <bindings/ScriptValue.h>
+#include <inspector/InspectorProtocolObjects.h>
 #include <inspector/InspectorValues.h>
-#include <wtf/text/StringBuilder.h>
 
-using namespace Inspector;
 
 namespace WebCore {
+using namespace Inspector;
+using namespace std::literals::chrono_literals;
 
-namespace {
-
-Path quadToPath(const FloatQuad& quad)
-{
-    Path quadPath;
-    quadPath.moveTo(quad.p1());
-    quadPath.addLineTo(quad.p2());
-    quadPath.addLineTo(quad.p3());
-    quadPath.addLineTo(quad.p4());
-    quadPath.closeSubpath();
-    return quadPath;
-}
-
-void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
+static void contentsQuadToCoordinateSystem(const FrameView* mainView, const FrameView* view, FloatQuad& quad, InspectorOverlay::CoordinateSystem coordinateSystem)
 {
-    static const int outlineThickness = 2;
-
-    Path quadPath = quadToPath(quad);
-
-    // Clip out the quad, then draw with a 2px stroke to get a pixel
-    // of outline (because inflating a quad is hard)
-    {
-        context->save();
-        context->clipOut(quadPath);
-
-        context->setStrokeThickness(outlineThickness);
-        context->setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
-        context->strokePath(quadPath);
-
-        context->restore();
-    }
+    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())));
 
-    // Now do the fill
-    context->setFillColor(fillColor, ColorSpaceDeviceRGB);
-    context->fillPath(quadPath);
+    if (coordinateSystem == InspectorOverlay::CoordinateSystem::View)
+        quad += toIntSize(mainView->scrollPosition());
 }
 
 static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
 {
-    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())));
-    quad += mainView->scrollOffset();
+    contentsQuadToCoordinateSystem(mainView, view, quad, InspectorOverlay::CoordinateSystem::View);
 }
 
-static void buildRendererHighlight(RenderObject* renderer, RenderRegion* region, const HighlightConfig& highlightConfig, Highlight* highlight)
+static void buildRendererHighlight(RenderObject* renderer, const HighlightConfig& highlightConfig, Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
 {
     Frame* containingFrame = renderer->document().frame();
     if (!containingFrame)
         return;
 
-    highlight->setDataFromConfig(highlightConfig);
+    highlight.setDataFromConfig(highlightConfig);
     FrameView* containingView = containingFrame->view();
     FrameView* mainView = containingFrame->page()->mainFrame().view();
 
@@ -124,125 +94,83 @@ static void buildRendererHighlight(RenderObject* renderer, RenderRegion* region,
     bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
 
     if (isSVGRenderer) {
-        highlight->type = HighlightTypeRects;
-        renderer->absoluteQuads(highlight->quads);
-        for (size_t i = 0; i < highlight->quads.size(); ++i)
-            contentsQuadToPage(mainView, containingView, highlight->quads[i]);
-    } else if (renderer->isBox() || renderer->isRenderInline()) {
+        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 (renderer->isBox()) {
-            RenderBox* renderBox = toRenderBox(renderer);
+        if (is<RenderBox>(*renderer)) {
+            auto& renderBox = downcast<RenderBox>(*renderer);
 
-            LayoutBoxExtent margins(renderBox->marginTop(), renderBox->marginRight(), renderBox->marginBottom(), renderBox->marginLeft());
-
-            if (!renderBox->isOutOfFlowPositioned() && region) {
-                RenderBox::LogicalExtentComputedValues computedValues;
-                renderBox->computeLogicalWidthInRegion(computedValues, region);
-                margins.mutableLogicalLeft(renderBox->style().writingMode()) = computedValues.m_margins.m_start;
-                margins.mutableLogicalRight(renderBox->style().writingMode()) = computedValues.m_margins.m_end;
-            }
-
-            paddingBox = renderBox->clientBoxRectInRegion(region);
-            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());
+            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 {
-            RenderInline* renderInline = toRenderInline(renderer);
+            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());
+            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());
+            marginBox = LayoutRect(borderBox.x() - renderInline.marginLeft(), borderBox.y(),
+                borderBox.width() + renderInline.horizontalMarginExtent(), borderBox.height());
         }
 
-        FloatQuad absContentQuad;
-        FloatQuad absPaddingQuad;
-        FloatQuad absBorderQuad;
-        FloatQuad absMarginQuad;
-
-        if (region) {
-            RenderFlowThread* flowThread = region->flowThread();
-
-            // Figure out the quads in the space of the RenderFlowThread.
-            absContentQuad = renderer->localToContainerQuad(FloatRect(contentBox), flowThread);
-            absPaddingQuad = renderer->localToContainerQuad(FloatRect(paddingBox), flowThread);
-            absBorderQuad = renderer->localToContainerQuad(FloatRect(borderBox), flowThread);
-            absMarginQuad = renderer->localToContainerQuad(FloatRect(marginBox), flowThread);
-
-            // Move the quad relative to the space of the current region.
-            LayoutRect flippedRegionRect(region->flowThreadPortionRect());
-            flowThread->flipForWritingMode(flippedRegionRect);
-
-            FloatSize delta = region->contentBoxRect().location() - flippedRegionRect.location();
-            absContentQuad.move(delta);
-            absPaddingQuad.move(delta);
-            absBorderQuad.move(delta);
-            absMarginQuad.move(delta);
-
-            // Resolve the absolute quads starting from the current region.
-            absContentQuad = region->localToAbsoluteQuad(absContentQuad);
-            absPaddingQuad = region->localToAbsoluteQuad(absPaddingQuad);
-            absBorderQuad = region->localToAbsoluteQuad(absBorderQuad);
-            absMarginQuad = region->localToAbsoluteQuad(absMarginQuad);
-        } else {
-            absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
-            absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
-            absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
-            absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
-        }
-
-        contentsQuadToPage(mainView, containingView, absContentQuad);
-        contentsQuadToPage(mainView, containingView, absPaddingQuad);
-        contentsQuadToPage(mainView, containingView, absBorderQuad);
-        contentsQuadToPage(mainView, containingView, absMarginQuad);
-
-        highlight->type = HighlightTypeNode;
-        highlight->quads.append(absMarginQuad);
-        highlight->quads.append(absBorderQuad);
-        highlight->quads.append(absPaddingQuad);
-        highlight->quads.append(absContentQuad);
+        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, RenderRegion* region, const HighlightConfig& highlightConfig, Highlight* highlight)
+static void buildNodeHighlight(Node& node, const HighlightConfig& highlightConfig, Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
 {
-    RenderObject* renderer = node->renderer();
+    RenderObject* renderer = node.renderer();
     if (!renderer)
         return;
-    buildRendererHighlight(renderer, region, highlightConfig, highlight);
+
+    buildRendererHighlight(renderer, highlightConfig, highlight, coordinateSystem);
 }
 
-static void buildQuadHighlight(const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
+static void buildQuadHighlight(const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlighthighlight)
 {
-    highlight->setDataFromConfig(highlightConfig);
-    highlight->type = HighlightTypeRects;
-    highlight->quads.append(quad);
+    highlight.setDataFromConfig(highlightConfig);
+    highlight.type = HighlightType::Rects;
+    highlight.quads.append(quad);
 }
 
-} // anonymous namespace
-
 InspectorOverlay::InspectorOverlay(Page& page, InspectorClient* client)
     : m_page(page)
     , m_client(client)
-    , m_indicating(false)
+    , m_paintRectUpdateTimer(*this, &InspectorOverlay::updatePaintRectsTimerFired)
 {
 }
 
-InspectorOverlay::~InspectorOverlay()
-{
-}
+InspectorOverlay::~InspectorOverlay() = default;
 
 void InspectorOverlay::paint(GraphicsContext& context)
 {
@@ -252,24 +180,27 @@ void InspectorOverlay::paint(GraphicsContext& context)
     GraphicsContextStateSaver stateSaver(context);
     FrameView* view = overlayPage()->mainFrame().view();
     view->updateLayoutAndStyleIfNeededRecursive();
-    view->paint(&context, IntRect(0, 0, view->width(), view->height()));
-}
-
-void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
-{
-    FloatRect outlineRect = rect;
-    drawOutlinedQuad(context, outlineRect, Color(), color);
+    view->paint(context, IntRect(0, 0, view->width(), view->height()));
 }
 
-void InspectorOverlay::getHighlight(Highlight* highlight) const
+void InspectorOverlay::getHighlight(Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem) const
 {
-    if (!m_highlightNode && !m_highlightQuad)
+    if (!m_highlightNode && !m_highlightQuad && !m_highlightNodeList)
         return;
 
-    highlight->type = HighlightTypeRects;
+    highlight.type = HighlightType::Rects;
     if (m_highlightNode)
-        buildNodeHighlight(m_highlightNode.get(), nullptr, m_nodeHighlightConfig, highlight);
-    else
+        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);
 }
 
@@ -281,8 +212,17 @@ void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
 
 void InspectorOverlay::hideHighlight()
 {
-    m_highlightNode.clear();
-    m_highlightQuad.reset();
+    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();
 }
 
@@ -290,16 +230,17 @@ void InspectorOverlay::highlightNode(Node* node, const HighlightConfig& highligh
 {
     m_nodeHighlightConfig = highlightConfig;
     m_highlightNode = node;
+    m_highlightNodeList = nullptr;
     update();
 }
 
 void InspectorOverlay::highlightQuad(std::unique_ptr<FloatQuad> quad, const HighlightConfig& highlightConfig)
 {
-    if (m_quadHighlightConfig.usePageCoordinates)
-        *quad -= m_page.mainFrame().view()->scrollOffset();
+    if (highlightConfig.usePageCoordinates)
+        *quad -= toIntSize(m_page.mainFrame().view()->scrollPosition());
 
     m_quadHighlightConfig = highlightConfig;
-    m_highlightQuad = std::move(quad);
+    m_highlightQuad = WTFMove(quad);
     update();
 }
 
@@ -327,7 +268,7 @@ void InspectorOverlay::setIndicating(bool indicating)
 
 bool InspectorOverlay::shouldShowOverlay() const
 {
-    return m_highlightNode || m_highlightNode || m_indicating || !m_pausedInDebuggerMessage.isNull();
+    return m_highlightNode || m_highlightNodeList || m_highlightQuad || m_indicating || m_showingPaintRects || !m_pausedInDebuggerMessage.isNull();
 }
 
 void InspectorOverlay::update()
@@ -342,10 +283,8 @@ void InspectorOverlay::update()
         return;
 
     FrameView* overlayView = overlayPage()->mainFrame().view();
-    IntSize viewportSize = view->visibleContentRect().size();
-    IntSize frameViewFullSize = view->visibleContentRectIncludingScrollbars().size();
-    overlayPage()->setPageScaleFactor(m_page.pageScaleFactor(), IntPoint());
-    frameViewFullSize.scale(m_page.pageScaleFactor());
+    IntSize viewportSize = view->sizeForVisibleContent();
+    IntSize frameViewFullSize = view->sizeForVisibleContent(ScrollableArea::IncludeScrollbars);
     overlayView->resize(frameViewFullSize);
 
     // Clear canvas and paint things.
@@ -357,240 +296,193 @@ void InspectorOverlay::update()
     drawNodeHighlight();
     drawQuadHighlight();
     drawPausedInDebuggerMessage();
+    drawPaintRects();
 
     // Position DOM elements.
-    overlayPage()->mainFrame().document()->recalcStyle(Style::Force);
+    overlayPage()->mainFrame().document()->resolveStyle(Document::ResolveStyleType::Rebuild);
     if (overlayView->needsLayout())
         overlayView->layout();
 
-    // Kick paint.
-    m_client->highlight();
+    forcePaint();
 }
 
-static PassRefPtr<InspectorObject> buildObjectForPoint(const FloatPoint& point)
+static Ref<Inspector::Protocol::OverlayTypes::Point> buildObjectForPoint(const FloatPoint& point)
 {
-    RefPtr<InspectorObject> object = InspectorObject::create();
-    object->setNumber("x", point.x());
-    object->setNumber("y", point.y());
-    return object.release();
+    return Inspector::Protocol::OverlayTypes::Point::create()
+        .setX(point.x())
+        .setY(point.y())
+        .release();
 }
 
-static PassRefPtr<InspectorArray> buildArrayForQuad(const FloatQuad& quad)
+static Ref<Inspector::Protocol::OverlayTypes::Rect> buildObjectForRect(const FloatRect& rect)
 {
-    RefPtr<InspectorArray> array = InspectorArray::create();
-    array->pushObject(buildObjectForPoint(quad.p1()));
-    array->pushObject(buildObjectForPoint(quad.p2()));
-    array->pushObject(buildObjectForPoint(quad.p3()));
-    array->pushObject(buildObjectForPoint(quad.p4()));
-    return array.release();
+    return Inspector::Protocol::OverlayTypes::Rect::create()
+        .setX(rect.x())
+        .setY(rect.y())
+        .setWidth(rect.width())
+        .setHeight(rect.height())
+        .release();
 }
 
-static PassRefPtr<InspectorObject> buildObjectForHighlight(const Highlight& highlight)
+static Ref<Inspector::Protocol::OverlayTypes::Quad> buildArrayForQuad(const FloatQuad& quad)
 {
-    RefPtr<InspectorObject> object = InspectorObject::create();
-    RefPtr<InspectorArray> array = InspectorArray::create();
-    for (size_t i = 0; i < highlight.quads.size(); ++i)
-        array->pushArray(buildArrayForQuad(highlight.quads[i]));
-    object->setArray("quads", array.release());
-    object->setBoolean("showRulers", highlight.showRulers);
-    object->setString("contentColor", highlight.contentColor.serialized());
-    object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
-    object->setString("paddingColor", highlight.paddingColor.serialized());
-    object->setString("borderColor", highlight.borderColor.serialized());
-    object->setString("marginColor", highlight.marginColor.serialized());
-    return object.release();
+    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 PassRefPtr<InspectorObject> buildObjectForRegionHighlight(FrameView* mainView, RenderRegion* region)
+static Ref<Inspector::Protocol::OverlayTypes::FragmentHighlightData> buildObjectForHighlight(const Highlight& highlight)
 {
-    FrameView* containingView = region->frame().view();
-    if (!containingView)
-        return nullptr;
-
-    RenderBlockFlow* regionContainer = toRenderBlockFlow(region->parent());
-    LayoutRect borderBox = regionContainer->borderBoxRect();
-    borderBox.setWidth(borderBox.width() + regionContainer->verticalScrollbarWidth());
-    borderBox.setHeight(borderBox.height() + regionContainer->horizontalScrollbarHeight());
-
-    // Create incoming and outgoing boxes that we use to chain the regions toghether.
-    const LayoutSize linkBoxSize(10, 10);
-    const LayoutSize linkBoxMidpoint(linkBoxSize.width() / 2, linkBoxSize.height() / 2);
-    
-    LayoutRect incomingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint, linkBoxSize);
-    LayoutRect outgoingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint + borderBox.size(), linkBoxSize);
+    auto arrayOfQuads = Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::Quad>::create();
+    for (auto& quad : highlight.quads)
+        arrayOfQuads->addItem(buildArrayForQuad(quad));
 
-    // Move the link boxes slightly inside the region border box.
-    LayoutUnit maxUsableHeight = std::max(LayoutUnit(), borderBox.height() - linkBoxMidpoint.height());
-    LayoutUnit linkBoxVerticalOffset = std::min(LayoutUnit::fromPixel(15), maxUsableHeight);
-    incomingRectBox.move(0, linkBoxVerticalOffset);
-    outgoingRectBox.move(0, -linkBoxVerticalOffset);
-
-    FloatQuad borderRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(borderBox));
-    FloatQuad incomingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(incomingRectBox));
-    FloatQuad outgoingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(outgoingRectBox));
-
-    contentsQuadToPage(mainView, containingView, borderRectQuad);
-    contentsQuadToPage(mainView, containingView, incomingRectQuad);
-    contentsQuadToPage(mainView, containingView, outgoingRectQuad);
+    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();
+}
 
-    RefPtr<InspectorObject> regionObject = InspectorObject::create();
+static Ref<Inspector::Protocol::OverlayTypes::Size> buildObjectForSize(const IntSize& size)
+{
+    return Inspector::Protocol::OverlayTypes::Size::create()
+        .setWidth(size.width())
+        .setHeight(size.height())
+        .release();
+}
 
-    regionObject->setArray("borderQuad", buildArrayForQuad(borderRectQuad));
-    regionObject->setArray("incomingQuad", buildArrayForQuad(incomingRectQuad));
-    regionObject->setArray("outgoingQuad", buildArrayForQuad(outgoingRectQuad));
+void InspectorOverlay::setShowingPaintRects(bool showingPaintRects)
+{
+    if (m_showingPaintRects == showingPaintRects)
+        return;
 
-    return regionObject.release();
+    m_showingPaintRects = showingPaintRects;
+    if (!m_showingPaintRects) {
+        m_paintRects.clear();
+        m_paintRectUpdateTimer.stop();
+        drawPaintRects();
+        forcePaint();
+    }
 }
 
-static PassRefPtr<InspectorArray> buildObjectForCSSRegionsHighlight(RenderRegion* region, RenderFlowThread* flowThread)
+void InspectorOverlay::showPaintRect(const FloatRect& rect)
 {
-    FrameView* mainFrameView = region->document().page()->mainFrame().view();
+    if (!m_showingPaintRects)
+        return;
 
-    RefPtr<InspectorArray> array = InspectorArray::create();
+    IntRect rootRect = m_page.mainFrame().view()->contentsToRootView(enclosingIntRect(rect));
 
-    const RenderRegionList& regionList = flowThread->renderRegionList();
-    for (auto& iterRegion : regionList) {
-        if (!iterRegion->isValid())
-            continue;
-        RefPtr<InspectorObject> regionHighlightObject = buildObjectForRegionHighlight(mainFrameView, iterRegion);
-        if (!regionHighlightObject)
-            continue;
-        if (region == iterRegion) {
-            // Let the script know that this is the currently highlighted node.
-            regionHighlightObject->setBoolean("isHighlighted", true);
-        }
-        array->pushObject(regionHighlightObject.release());
-    }
+    const auto removeDelay = 250ms;
 
-    return array.release();
-}
+    std::chrono::steady_clock::time_point removeTime = std::chrono::steady_clock::now() + removeDelay;
+    m_paintRects.append(TimeRectPair(removeTime, rootRect));
 
-static PassRefPtr<InspectorObject> buildObjectForSize(const IntSize& size)
-{
-    RefPtr<InspectorObject> result = InspectorObject::create();
-    result->setNumber("width", size.width());
-    result->setNumber("height", size.height());
-    return result.release();
+    if (!m_paintRectUpdateTimer.isActive()) {
+        const Seconds paintRectsUpdateInterval { 32_ms };
+        m_paintRectUpdateTimer.startRepeating(paintRectsUpdateInterval);
+    }
+
+    drawPaintRects();
+    forcePaint();
 }
 
-static PassRefPtr<InspectorObject> buildObjectForCSSRegionContentClip(RenderRegion* region)
+void InspectorOverlay::updatePaintRectsTimerFired()
 {
-    Frame* containingFrame = region->document().frame();
-    if (!containingFrame)
-        return nullptr;
+    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+    bool rectsChanged = false;
+    while (!m_paintRects.isEmpty() && m_paintRects.first().first < now) {
+        m_paintRects.removeFirst();
+        rectsChanged = true;
+    }
 
-    FrameView* containingView = containingFrame->view();
-    FrameView* mainView = containingFrame->page()->mainFrame().view();
-    RenderFlowThread* flowThread = region->flowThread();
+    if (m_paintRects.isEmpty())
+        m_paintRectUpdateTimer.stop();
 
-    // Get the clip box of the current region and covert it into an absolute quad.
-    LayoutRect flippedRegionRect(region->flowThreadPortionOverflowRect());
-    flowThread->flipForWritingMode(flippedRegionRect);
+    if (rectsChanged) {
+        drawPaintRects();
+        forcePaint();
+    }
+}
 
-    // Apply any border or padding of the region.
-    flippedRegionRect.setLocation(region->contentBoxRect().location());
-    
-    FloatQuad clipQuad = region->localToAbsoluteQuad(FloatRect(flippedRegionRect));
-    contentsQuadToPage(mainView, containingView, clipQuad);
+void InspectorOverlay::drawPaintRects()
+{
+    auto arrayOfRects = Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::Rect>::create();
+    for (const auto& pair : m_paintRects)
+        arrayOfRects->addItem(buildObjectForRect(pair.second));
 
-    RefPtr<InspectorObject> regionObject = InspectorObject::create();
-    regionObject->setArray("quad", buildArrayForQuad(clipQuad));
-    return regionObject.release();
+    evaluateInOverlay(ASCIILiteral("updatePaintRects"), WTFMove(arrayOfRects));
 }
 
 void InspectorOverlay::drawGutter()
 {
-    evaluateInOverlay("drawGutter");
+    evaluateInOverlay(ASCIILiteral("drawGutter"));
 }
 
-static PassRefPtr<InspectorArray> buildObjectForRendererFragments(RenderObject* renderer, const HighlightConfig& config)
+static RefPtr<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::FragmentHighlightData>> buildArrayForRendererFragments(RenderObject* renderer, const HighlightConfig& config)
 {
-    RefPtr<InspectorArray> fragmentsArray = InspectorArray::create();
+    auto arrayOfFragments = Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::FragmentHighlightData>::create();
 
-    RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock();
-    if (!containingFlowThread) {
-        Highlight highlight;
-        buildRendererHighlight(renderer, nullptr, config, &highlight);
-        fragmentsArray->pushObject(buildObjectForHighlight(highlight));
-    } else {
-        RenderBox* enclosingBox = renderer->enclosingBox();
-        RenderRegion* startRegion = nullptr;
-        RenderRegion* endRegion = nullptr;
-        containingFlowThread->getRegionRangeForBox(enclosingBox, startRegion, endRegion);
-        if (!startRegion) {
-            // The flow has no visible regions. The renderer is not visible on screen.
-            return nullptr;
-        }
-        const RenderRegionList& regionList = containingFlowThread->renderRegionList();
-        for (RenderRegionList::const_iterator iter = regionList.find(startRegion); iter != regionList.end(); ++iter) {
-            RenderRegion* region = *iter;
-            if (region->isValid()) {
-                // Compute the highlight of the fragment inside the current region.
-                Highlight highlight;
-                buildRendererHighlight(renderer, region, config, &highlight);
-                RefPtr<InspectorObject> fragmentObject = buildObjectForHighlight(highlight);
-
-                // Compute the clipping area of the region.
-                fragmentObject->setObject("region", buildObjectForCSSRegionContentClip(region));
-                fragmentsArray->pushObject(fragmentObject.release());
-            }
-            if (region == endRegion)
-                break;
-        }
-    }
+    Highlight highlight;
+    buildRendererHighlight(renderer, config, highlight, InspectorOverlay::CoordinateSystem::View);
+    arrayOfFragments->addItem(buildObjectForHighlight(highlight));
 
-    return fragmentsArray.release();
+    return WTFMove(arrayOfFragments);
 }
 
-#if ENABLE(CSS_SHAPES)
 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 += mainView->scrollOffset();
+    result += toIntSize(mainView->scrollPosition());
     return result;
 }
 
 struct PathApplyInfo {
     FrameView* rootView;
     FrameView* view;
-    InspectorArray* array;
+    Inspector::Protocol::OverlayTypes::DisplayPath* pathArray;
     RenderObject* renderer;
     const ShapeOutsideInfo* shapeOutsideInfo;
 };
 
-static void appendPathCommandAndPoints(PathApplyInfo* info, const String& command, const FloatPoint points[], unsigned length)
+static void appendPathCommandAndPoints(PathApplyInfo& info, const String& command, const FloatPoint points[], unsigned length)
 {
     FloatPoint point;
-    info->array->pushString(command);
+    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->array->pushNumber(point.x());
-        info->array->pushNumber(point.y());
+        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(void* info, const PathElement* pathElement)
+static void appendPathSegment(PathApplyInfo& pathApplyInfo, const PathElement& pathElement)
 {
-    PathApplyInfo* pathApplyInfo = static_cast<PathApplyInfo*>(info);
     FloatPoint point;
-    switch (pathElement->type) {
+    switch (pathElement.type) {
     // The points member will contain 1 value.
     case PathElementMoveToPoint:
-        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("M"), pathElement->points, 1);
+        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("M"), pathElement.points, 1);
         break;
     // The points member will contain 1 value.
     case PathElementAddLineToPoint:
-        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("L"), pathElement->points, 1);
+        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("L"), pathElement.points, 1);
         break;
     // The points member will contain 3 values.
     case PathElementAddCurveToPoint:
-        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("C"), pathElement->points, 3);
+        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("C"), pathElement.points, 3);
         break;
     // The points member will contain 2 values.
     case PathElementAddQuadCurveToPoint:
-        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("Q"), pathElement->points, 2);
+        appendPathCommandAndPoints(pathApplyInfo, ASCIILiteral("Q"), pathElement.points, 2);
         break;
     // The points member will contain no values.
     case PathElementCloseSubpath:
@@ -599,149 +491,177 @@ static void appendPathSegment(void* info, const PathElement* pathElement)
     }
 }
 
-static PassRefPtr<InspectorObject> buildObjectForShapeOutside(Frame* containingFrame, RenderBox* renderer)
+static RefPtr<Inspector::Protocol::OverlayTypes::ShapeOutsideData> buildObjectForShapeOutside(Frame* containingFrame, RenderBox* renderer)
 {
     const ShapeOutsideInfo* shapeOutsideInfo = renderer->shapeOutsideInfo();
     if (!shapeOutsideInfo)
         return nullptr;
 
-    RefPtr<InspectorObject> shapeObject = InspectorObject::create();
     LayoutRect shapeBounds = shapeOutsideInfo->computedShapePhysicalBoundingBox();
     FloatQuad shapeQuad = renderer->localToAbsoluteQuad(FloatRect(shapeBounds));
     contentsQuadToPage(containingFrame->page()->mainFrame().view(), containingFrame->view(), shapeQuad);
-    shapeObject->setArray(ASCIILiteral("bounds"), buildArrayForQuad(shapeQuad));
+
+    auto shapeObject = Inspector::Protocol::OverlayTypes::ShapeOutsideData::create()
+        .setBounds(buildArrayForQuad(shapeQuad))
+        .release();
 
     Shape::DisplayPaths paths;
     shapeOutsideInfo->computedShape().buildDisplayPaths(paths);
 
     if (paths.shape.length()) {
-        RefPtr<InspectorArray> shapePath = InspectorArray::create();
+        auto shapePath = Inspector::Protocol::OverlayTypes::DisplayPath::create();
         PathApplyInfo info;
         info.rootView = containingFrame->page()->mainFrame().view();
         info.view = containingFrame->view();
-        info.array = shapePath.get();
+        info.pathArray = &shapePath.get();
         info.renderer = renderer;
         info.shapeOutsideInfo = shapeOutsideInfo;
 
-        paths.shape.apply(&info, &appendPathSegment);
+        paths.shape.apply([&info](const PathElement& pathElement) {
+            appendPathSegment(info, pathElement);
+        });
 
-        shapeObject->setArray(ASCIILiteral("shape"), shapePath.release());
+        shapeObject->setShape(shapePath.copyRef());
 
         if (paths.marginShape.length()) {
-            shapePath = InspectorArray::create();
-            info.array = shapePath.get();
+            auto marginShapePath = Inspector::Protocol::OverlayTypes::DisplayPath::create();
+            info.pathArray = &marginShapePath.get();
 
-            paths.marginShape.apply(&info, &appendPathSegment);
+            paths.marginShape.apply([&info](const PathElement& pathElement) {
+                appendPathSegment(info, pathElement);
+            });
 
-            shapeObject->setArray(ASCIILiteral("marginShape"), shapePath.release());
+            shapeObject->setMarginShape(marginShapePath.copyRef());
         }
     }
 
-    return shapeObject.release();
+    return WTFMove(shapeObject);
 }
-#endif
 
-static PassRefPtr<InspectorObject> buildObjectForElementInfo(Node* node)
+static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElementData(Node* node, HighlightType)
 {
-    if (!node->isElementNode() || !node->document().frame())
+    if (!is<Element>(node) || !node->document().frame())
         return nullptr;
 
-    RefPtr<InspectorObject> elementInfo = InspectorObject::create();
-
-    Element* element = toElement(node);
-    bool isXHTML = element->document().isXHTMLDocument();
-    elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower());
-    elementInfo->setString("idValue", element->getIdAttribute());
-    HashSet<AtomicString> usedClassNames;
-    if (element->hasClass() && element->isStyledElement()) {
-        StringBuilder classNames;
-        const SpaceSplitString& classNamesString = toStyledElement(element)->classNames();
-        size_t classNameCount = classNamesString.size();
-        for (size_t i = 0; i < classNameCount; ++i) {
+    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 = Inspector::Protocol::Array<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);
-            classNames.append('.');
-            classNames.append(className);
+            classes->addItem(className);
         }
-        elementInfo->setString("className", classNames.toString());
+        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();
+    RenderElement* renderer = element.renderer();
+    if (!renderer)
+        return nullptr;
+
     Frame* containingFrame = node->document().frame();
     FrameView* containingView = containingFrame->view();
-    IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
-    RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : nullptr;
-    elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), *modelObject) : boundingBox.width()));
-    elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), *modelObject) : boundingBox.height()));
-    
-    if (renderer->isRenderNamedFlowFragmentContainer()) {
-        RenderNamedFlowFragment* region = toRenderBlockFlow(renderer)->renderNamedFlowFragment();
-        RenderFlowThread* flowThread = region->flowThread();
-        if (flowThread && flowThread->isRenderNamedFlowThread()) {
-            RefPtr<InspectorObject> regionFlowInfo = InspectorObject::create();
-            regionFlowInfo->setString("name", toRenderNamedFlowThread(flowThread)->flowThreadName());
-            regionFlowInfo->setArray("regions", buildObjectForCSSRegionsHighlight(region, flowThread));
-            elementInfo->setObject("regionFlowInfo", regionFlowInfo.release());
-        }
+    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));
     }
 
-    RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock();
-    if (containingFlowThread && containingFlowThread->isRenderNamedFlowThread()) {
-        RefPtr<InspectorObject> contentFlowInfo = InspectorObject::create();
-        contentFlowInfo->setString("name", toRenderNamedFlowThread(containingFlowThread)->flowThreadName());
-        elementInfo->setObject("contentFlowInfo", contentFlowInfo.release());
-    }
+    // Need to enable AX to get the computed role.
+    if (!WebCore::AXObjectCache::accessibilityEnabled())
+        WebCore::AXObjectCache::enableAccessibility();
 
-#if ENABLE(CSS_SHAPES)
-    if (renderer->isBox()) {
-        RenderBox* renderBox = toRenderBox(renderer);
-        if (RefPtr<InspectorObject> shapeObject = buildObjectForShapeOutside(containingFrame, renderBox))
-            elementInfo->setObject("shapeOutsideInfo", shapeObject.release());
+    if (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
+        if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node))
+            elementData->setRole(axObject->computedRoleString());
     }
-#endif
 
-    return elementInfo.release();
+    return WTFMove(elementData);
 }
 
-PassRefPtr<InspectorObject> InspectorOverlay::buildObjectForHighlightedNode() const
+RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorOverlay::buildHighlightObjectForNode(Node* node, HighlightType type) const
 {
-    if (!m_highlightNode)
+    if (!node)
         return nullptr;
 
-    Node* node = m_highlightNode.get();
     RenderObject* renderer = node->renderer();
     if (!renderer)
         return nullptr;
 
-    RefPtr<InspectorArray> highlightFragments = buildObjectForRendererFragments(renderer, m_nodeHighlightConfig);
-    if (!highlightFragments)
+    RefPtr<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::FragmentHighlightData>> arrayOfFragmentHighlights = buildArrayForRendererFragments(renderer, m_nodeHighlightConfig);
+    if (!arrayOfFragmentHighlights)
         return nullptr;
 
-    RefPtr<InspectorObject> highlightObject = InspectorObject::create();
-
     // The main view's scroll offset is shared across all quads.
     FrameView* mainView = m_page.mainFrame().view();
-    highlightObject->setObject("scroll", buildObjectForPoint(!mainView->delegatesScrolling() ? mainView->visibleContentRect().location() : FloatPoint()));
 
-    highlightObject->setArray("fragments", highlightFragments.release());
+    auto nodeHighlightObject = Inspector::Protocol::OverlayTypes::NodeHighlightData::create()
+        .setScrollOffset(buildObjectForPoint(!mainView->delegatesScrolling() ? mainView->visibleContentRect().location() : FloatPoint()))
+        .setFragments(WTFMove(arrayOfFragmentHighlights))
+        .release();
 
     if (m_nodeHighlightConfig.showInfo) {
-        RefPtr<InspectorObject> elementInfo = buildObjectForElementInfo(node);
-        if (elementInfo)
-            highlightObject->setObject("elementInfo", elementInfo.release());
+        if (RefPtr<Inspector::Protocol::OverlayTypes::ElementData> elementData = buildObjectForElementData(node, type))
+            nodeHighlightObject->setElementData(WTFMove(elementData));
     }
-        
-    return highlightObject.release();
+
+    return WTFMove(nodeHighlightObject);
+}
+
+Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorOverlay::buildObjectForHighlightedNodes() const
+{
+    auto highlights = Inspector::Protocol::Array<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()
 {
-    RefPtr<InspectorObject> highlightObject = buildObjectForHighlightedNode();
-    if (!highlightObject)
-        return;
-    evaluateInOverlay("drawNodeHighlight", highlightObject);
+    if (m_highlightNode || m_highlightNodeList)
+        evaluateInOverlay("drawNodeHighlight", buildObjectForHighlightedNodes());
 }
 
 void InspectorOverlay::drawQuadHighlight()
@@ -750,7 +670,7 @@ void InspectorOverlay::drawQuadHighlight()
         return;
 
     Highlight highlight;
-    buildQuadHighlight(*m_highlightQuad, m_quadHighlightConfig, &highlight);
+    buildQuadHighlight(*m_highlightQuad, m_quadHighlightConfig, highlight);
     evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
 }
 
@@ -765,9 +685,15 @@ Page* InspectorOverlay::overlayPage()
     if (m_overlayPage)
         return m_overlayPage.get();
 
-    Page::PageClients pageClients;
-    fillWithEmptyClients(pageClients);
-    m_overlayPage = std::make_unique<Page>(pageClients);
+    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();
@@ -807,43 +733,56 @@ Page* InspectorOverlay::overlayPage()
     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)
 {
-    RefPtr<InspectorObject> resetData = InspectorObject::create();
-    resetData->setNumber("deviceScaleFactor", m_page.deviceScaleFactor());
-    resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
-    resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
-    evaluateInOverlay("reset", resetData.release());
+    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<InspectorArray>&& command)
+{
+    page->mainFrame().script().evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ')')));
 }
 
 void InspectorOverlay::evaluateInOverlay(const String& method)
 {
-    RefPtr<InspectorArray> command = InspectorArray::create();
+    Ref<InspectorArray> command = InspectorArray::create();
     command->pushString(method);
-    overlayPage()->mainFrame().script().evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
+
+    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
 }
 
 void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
 {
-    RefPtr<InspectorArray> command = InspectorArray::create();
+    Ref<InspectorArray> command = InspectorArray::create();
     command->pushString(method);
     command->pushString(argument);
-    overlayPage()->mainFrame().script().evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
+
+    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
 }
 
-void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument)
+void InspectorOverlay::evaluateInOverlay(const String& method, RefPtr<InspectorValue>&& argument)
 {
-    RefPtr<InspectorArray> command = InspectorArray::create();
+    Ref<InspectorArray> command = InspectorArray::create();
     command->pushString(method);
-    command->pushValue(argument);
-    overlayPage()->mainFrame().script().evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
+    command->pushValue(WTFMove(argument));
+
+    evaluateCommandInOverlay(overlayPage(), WTFMove(command));
 }
 
 void InspectorOverlay::freePage()
 {
-    m_overlayPage.reset();
+    m_overlayPage = nullptr;
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(INSPECTOR)