Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorOverlay.cpp
index 6853e99..da39849 100644 (file)
 #include "config.h"
 #include "core/inspector/InspectorOverlay.h"
 
-#include "InspectorOverlayPage.h"
-#include "V8InspectorOverlayHost.h"
-#include "bindings/v8/ScriptController.h"
-#include "bindings/v8/ScriptSourceCode.h"
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/ScriptSourceCode.h"
+#include "bindings/core/v8/V8InspectorOverlayHost.h"
 #include "core/dom/Element.h"
 #include "core/dom/Node.h"
 #include "core/dom/PseudoElement.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/Settings.h"
 #include "core/inspector/InspectorClient.h"
 #include "core/inspector/InspectorOverlayHost.h"
 #include "core/loader/EmptyClients.h"
 #include "core/page/Chrome.h"
 #include "core/page/EventHandler.h"
 #include "core/page/Page.h"
-#include "core/frame/Settings.h"
+#include "core/rendering/RenderBox.h"
 #include "core/rendering/RenderBoxModelObject.h"
 #include "core/rendering/RenderInline.h"
 #include "core/rendering/RenderObject.h"
+#include "core/rendering/shapes/ShapeOutsideInfo.h"
 #include "core/rendering/style/RenderStyleConstants.h"
 #include "platform/JSONValues.h"
 #include "platform/PlatformMouseEvent.h"
+#include "platform/ScriptForbiddenScope.h"
 #include "platform/graphics/GraphicsContextStateSaver.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebData.h"
+#include "wtf/Vector.h"
 #include "wtf/text/StringBuilder.h"
+#include <v8.h>
 
-namespace WebCore {
+namespace blink {
 
 namespace {
 
+class PathBuilder {
+    WTF_MAKE_NONCOPYABLE(PathBuilder);
+public:
+    PathBuilder() : m_path(TypeBuilder::Array<JSONValue>::create()) { }
+    virtual ~PathBuilder() { }
+
+    PassRefPtr<TypeBuilder::Array<JSONValue> > path() const { return m_path; }
+    void appendPath(const Path& path)
+    {
+        path.apply(this, &PathBuilder::appendPathElement);
+    }
+
+protected:
+    virtual FloatPoint translatePoint(const FloatPoint& point) { return point; }
+
+private:
+    static void appendPathElement(void* pathBuilder, const PathElement* pathElement)
+    {
+        static_cast<PathBuilder*>(pathBuilder)->appendPathElement(pathElement);
+    }
+
+    void appendPathElement(const PathElement*);
+    void appendPathCommandAndPoints(const char* command, const FloatPoint points[], size_t length);
+
+    RefPtr<TypeBuilder::Array<JSONValue> > m_path;
+};
+
+class ShapePathBuilder : public PathBuilder {
+public:
+    ShapePathBuilder(FrameView& view, RenderObject& renderer, const ShapeOutsideInfo& shapeOutsideInfo)
+        : m_view(view)
+        , m_renderer(renderer)
+        , m_shapeOutsideInfo(shapeOutsideInfo) { }
+
+    static PassRefPtr<TypeBuilder::Array<JSONValue> > buildPath(FrameView& view, RenderObject& renderer, const ShapeOutsideInfo& shapeOutsideInfo, const Path& path)
+    {
+        ShapePathBuilder builder(view, renderer, shapeOutsideInfo);
+        builder.appendPath(path);
+        return builder.path();
+    }
+
+protected:
+    virtual FloatPoint translatePoint(const FloatPoint& point)
+    {
+        FloatPoint rendererPoint = m_shapeOutsideInfo.shapeToRendererPoint(point);
+        return m_view.contentsToRootView(roundedIntPoint(m_renderer.localToAbsolute(rendererPoint)));
+    }
+
+private:
+    FrameView& m_view;
+    RenderObject& m_renderer;
+    const ShapeOutsideInfo& m_shapeOutsideInfo;
+};
+
 class InspectorOverlayChromeClient FINAL: public EmptyChromeClient {
 public:
     InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay* overlay)
@@ -91,7 +151,7 @@ private:
     InspectorOverlay* m_overlay;
 };
 
-Path quadToPath(const FloatQuad& quad)
+static Path quadToPath(const FloatQuad& quad)
 {
     Path quadPath;
     quadPath.moveTo(quad.p1());
@@ -126,36 +186,74 @@ void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Col
     context->fillPath(quadPath);
 }
 
-static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
+class Highlight {
+public:
+    Highlight()
+        : m_showRulers(false)
+        , m_showExtensionLines(false)
+        , m_highlightPaths(JSONArray::create())
+    { }
+
+    void setDataFromConfig(const HighlightConfig& highlightConfig)
+    {
+        m_showRulers = highlightConfig.showRulers;
+        m_showExtensionLines = highlightConfig.showExtensionLines;
+    }
+
+    void setElementInfo(PassRefPtr<JSONObject> elementInfo)
+    {
+        m_elementInfo = elementInfo;
+    }
+
+    void appendQuad(const FloatQuad& quad, const Color& fillColor, const Color& outlineColor = Color::transparent)
+    {
+        Path path = quadToPath(quad);
+        PathBuilder builder;
+        builder.appendPath(path);
+        appendPath(builder.path(), fillColor, outlineColor);
+    }
+
+    void appendPath(PassRefPtr<JSONArrayBase> path, const Color& fillColor, const Color& outlineColor)
+    {
+        RefPtr<JSONObject> object = JSONObject::create();
+        object->setValue("path", path);
+        object->setString("fillColor", fillColor.serialized());
+        if (outlineColor != Color::transparent)
+            object->setString("outlineColor", outlineColor.serialized());
+        m_highlightPaths->pushObject(object.release());
+    }
+
+    PassRefPtr<JSONObject> asJSONObject() const
+    {
+        RefPtr<JSONObject> object = JSONObject::create();
+        object->setArray("paths", m_highlightPaths);
+        object->setBoolean("showRulers", m_showRulers);
+        object->setBoolean("showExtensionLines", m_showExtensionLines);
+        if (m_elementInfo)
+            object->setObject("elementInfo", m_elementInfo);
+        return object.release();
+    }
+
+private:
+    bool m_showRulers;
+    bool m_showExtensionLines;
+    RefPtr<JSONObject> m_elementInfo;
+    RefPtr<JSONArray> m_highlightPaths;
+};
+
+static void contentsQuadToScreen(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();
 }
 
-static bool buildNodeQuads(Node* node, Vector<FloatQuad>& quads)
+static bool buildNodeQuads(RenderObject* renderer, FloatQuad* content, FloatQuad* padding, FloatQuad* border, FloatQuad* margin)
 {
-    RenderObject* renderer = node->renderer();
-    LocalFrame* containingFrame = node->document().frame();
-
-    if (!renderer || !containingFrame)
+    FrameView* containingView = renderer->frameView();
+    if (!containingView)
         return false;
-
-    FrameView* containingView = containingFrame->view();
-    FrameView* mainView = containingFrame->page()->mainFrame()->view();
-    IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
-    boundingBox.move(mainView->scrollOffset());
-
-    // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
-    if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot()) {
-        renderer->absoluteQuads(quads);
-        for (size_t i = 0; i < quads.size(); ++i)
-            contentsQuadToPage(mainView, containingView, quads[i]);
-        return false;
-    }
-
     if (!renderer->isBox() && !renderer->isRenderInline())
         return false;
 
@@ -192,49 +290,43 @@ static bool buildNodeQuads(Node* node, Vector<FloatQuad>& quads)
             borderBox.width() + renderInline->marginWidth(), 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));
+    *content = renderer->localToAbsoluteQuad(FloatRect(contentBox));
+    *padding = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
+    *border = renderer->localToAbsoluteQuad(FloatRect(borderBox));
+    *margin = renderer->localToAbsoluteQuad(FloatRect(marginBox));
 
-    contentsQuadToPage(mainView, containingView, absContentQuad);
-    contentsQuadToPage(mainView, containingView, absPaddingQuad);
-    contentsQuadToPage(mainView, containingView, absBorderQuad);
-    contentsQuadToPage(mainView, containingView, absMarginQuad);
-
-    quads.append(absMarginQuad);
-    quads.append(absBorderQuad);
-    quads.append(absPaddingQuad);
-    quads.append(absContentQuad);
+    contentsQuadToScreen(containingView, *content);
+    contentsQuadToScreen(containingView, *padding);
+    contentsQuadToScreen(containingView, *border);
+    contentsQuadToScreen(containingView, *margin);
 
     return true;
 }
 
-static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
+static void buildNodeHighlight(Node& node, const HighlightConfig& highlightConfig, Highlight* highlight)
 {
-    RenderObject* renderer = node->renderer();
-    LocalFrame* containingFrame = node->document().frame();
-
-    if (!renderer || !containingFrame)
+    RenderObject* renderer = node.renderer();
+    if (!renderer)
         return;
 
     highlight->setDataFromConfig(highlightConfig);
 
     // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
-    if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot())
-        highlight->type = HighlightTypeRects;
-    else if (renderer->isBox() || renderer->isRenderInline())
-        highlight->type = HighlightTypeNode;
-    buildNodeQuads(node, highlight->quads);
-}
+    if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot()) {
+        Vector<FloatQuad> quads;
+        renderer->absoluteQuads(quads);
+        for (size_t i = 0; i < quads.size(); ++i)
+            highlight->appendQuad(quads[i], highlightConfig.content, highlightConfig.contentOutline);
+        return;
+    }
 
-static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
-{
-    if (!page)
+    FloatQuad content, padding, border, margin;
+    if (!buildNodeQuads(renderer, &content, &padding, &border, &margin))
         return;
-    highlight->setDataFromConfig(highlightConfig);
-    highlight->type = HighlightTypeRects;
-    highlight->quads.append(quad);
+    highlight->appendQuad(content, highlightConfig.content, highlightConfig.contentOutline);
+    highlight->appendQuad(padding, highlightConfig.padding);
+    highlight->appendQuad(border, highlightConfig.border);
+    highlight->appendQuad(margin, highlightConfig.margin);
 }
 
 } // anonymous namespace
@@ -246,6 +338,7 @@ InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
     , m_overlayHost(InspectorOverlayHost::create())
     , m_drawViewSize(false)
     , m_drawViewSizeWithGrid(false)
+    , m_omitTooltip(false)
     , m_timer(this, &InspectorOverlay::onTimer)
     , m_activeProfilerCount(0)
 {
@@ -253,6 +346,7 @@ InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
 
 InspectorOverlay::~InspectorOverlay()
 {
+    ASSERT(!m_overlayPage);
 }
 
 void InspectorOverlay::paint(GraphicsContext& context)
@@ -260,7 +354,7 @@ void InspectorOverlay::paint(GraphicsContext& context)
     if (isEmpty())
         return;
     GraphicsContextStateSaver stateSaver(context);
-    FrameView* view = overlayPage()->mainFrame()->view();
+    FrameView* view = toLocalFrame(overlayPage()->mainFrame())->view();
     ASSERT(!view->needsLayout());
     view->paint(&context, IntRect(0, 0, view->width(), view->height()));
 }
@@ -275,7 +369,7 @@ bool InspectorOverlay::handleGestureEvent(const PlatformGestureEvent& event)
     if (isEmpty())
         return false;
 
-    return overlayPage()->mainFrame()->eventHandler().handleGestureEvent(event);
+    return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleGestureEvent(event);
 }
 
 bool InspectorOverlay::handleMouseEvent(const PlatformMouseEvent& event)
@@ -283,24 +377,17 @@ bool InspectorOverlay::handleMouseEvent(const PlatformMouseEvent& event)
     if (isEmpty())
         return false;
 
-    EventHandler& eventHandler = overlayPage()->mainFrame()->eventHandler();
-    bool result;
+    EventHandler& eventHandler = toLocalFrame(overlayPage()->mainFrame())->eventHandler();
     switch (event.type()) {
     case PlatformEvent::MouseMoved:
-        result = eventHandler.handleMouseMoveEvent(event);
-        break;
+        return eventHandler.handleMouseMoveEvent(event);
     case PlatformEvent::MousePressed:
-        result = eventHandler.handleMousePressEvent(event);
-        break;
+        return eventHandler.handleMousePressEvent(event);
     case PlatformEvent::MouseReleased:
-        result = eventHandler.handleMouseReleaseEvent(event);
-        break;
+        return eventHandler.handleMouseReleaseEvent(event);
     default:
         return false;
     }
-
-    overlayPage()->mainFrame()->document()->updateLayout();
-    return result;
 }
 
 bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event)
@@ -308,7 +395,7 @@ bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event)
     if (isEmpty())
         return false;
 
-    return overlayPage()->mainFrame()->eventHandler().handleTouchEvent(event);
+    return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleTouchEvent(event);
 }
 
 bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event)
@@ -316,7 +403,7 @@ bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event)
     if (isEmpty())
         return false;
 
-    return overlayPage()->mainFrame()->eventHandler().keyEvent(event);
+    return toLocalFrame(overlayPage()->mainFrame())->eventHandler().keyEvent(event);
 }
 
 void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
@@ -325,24 +412,6 @@ void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& r
     drawOutlinedQuad(context, outlineRect, Color(), color);
 }
 
-void InspectorOverlay::getHighlight(Highlight* highlight) const
-{
-    if (!m_highlightNode && !m_highlightQuad)
-        return;
-
-    highlight->type = HighlightTypeRects;
-    if (m_highlightNode)
-        buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight);
-    else
-        buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, highlight);
-}
-
-void InspectorOverlay::resize(const IntSize& size)
-{
-    m_size = size;
-    update();
-}
-
 void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
 {
     m_pausedInDebuggerMessage = message ? *message : String();
@@ -363,11 +432,12 @@ void InspectorOverlay::hideHighlight()
     update();
 }
 
-void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig)
+void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig, bool omitTooltip)
 {
     m_nodeHighlightConfig = highlightConfig;
     m_highlightNode = node;
     m_eventTargetNode = eventTarget;
+    m_omitTooltip = omitTooltip;
     update();
 }
 
@@ -375,6 +445,7 @@ void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const Highlight
 {
     m_quadHighlightConfig = highlightConfig;
     m_highlightQuad = quad;
+    m_omitTooltip = false;
     update();
 }
 
@@ -395,7 +466,7 @@ bool InspectorOverlay::isEmpty()
 {
     if (m_activeProfilerCount)
         return true;
-    bool hasAlwaysVisibleElements = m_highlightNode || m_eventTargetNode || m_highlightQuad || !m_size.isEmpty() || m_drawViewSize;
+    bool hasAlwaysVisibleElements = m_highlightNode || m_eventTargetNode || m_highlightQuad  || m_drawViewSize;
     bool hasInvisibleInInspectModeElements = !m_pausedInDebuggerMessage.isNull();
     return !(hasAlwaysVisibleElements || (hasInvisibleInInspectModeElements && !m_inspectModeEnabled));
 }
@@ -407,19 +478,17 @@ void InspectorOverlay::update()
         return;
     }
 
-    FrameView* view = m_page->mainFrame()->view();
+    FrameView* view = m_page->deprecatedLocalMainFrame()->view();
     if (!view)
         return;
-    IntRect viewRect = view->visibleContentRect();
 
     // Include scrollbars to avoid masking them by the gutter.
-    IntSize frameViewFullSize = view->visibleContentRect(IncludeScrollbars).size();
-    IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
-    size.scale(m_page->pageScaleFactor());
-    overlayPage()->mainFrame()->view()->resize(size);
+    IntSize size = view->unscaledVisibleContentSize(IncludeScrollbars);
+    toLocalFrame(overlayPage()->mainFrame())->view()->resize(size);
 
     // Clear canvas and paint things.
-    reset(size, m_size.isEmpty() ? IntSize() : frameViewFullSize, viewRect.x(), viewRect.y());
+    IntRect viewRect = view->visibleContentRect();
+    reset(size, viewRect.x(), viewRect.y());
 
     drawNodeHighlight();
     drawQuadHighlight();
@@ -427,11 +496,8 @@ void InspectorOverlay::update()
         drawPausedInDebuggerMessage();
     drawViewSize();
 
-    // Position DOM elements.
-    overlayPage()->mainFrame()->document()->setNeedsStyleRecalc(SubtreeStyleChange);
-    overlayPage()->mainFrame()->document()->updateLayout();
+    toLocalFrame(overlayPage()->mainFrame())->view()->updateLayoutAndStyleForPainting();
 
-    // Kick paint.
     m_client->highlight();
 }
 
@@ -442,53 +508,152 @@ void InspectorOverlay::hide()
     m_eventTargetNode.clear();
     m_highlightQuad.clear();
     m_pausedInDebuggerMessage = String();
-    m_size = IntSize();
     m_drawViewSize = false;
     m_drawViewSizeWithGrid = false;
     update();
 }
 
-static PassRefPtr<JSONObject> buildObjectForPoint(const FloatPoint& point)
+static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size)
 {
-    RefPtr<JSONObject> object = JSONObject::create();
-    object->setNumber("x", point.x());
-    object->setNumber("y", point.y());
-    return object.release();
+    RefPtr<JSONObject> result = JSONObject::create();
+    result->setNumber("width", size.width());
+    result->setNumber("height", size.height());
+    return result.release();
 }
 
-static PassRefPtr<JSONArray> buildArrayForQuad(const FloatQuad& quad)
+void PathBuilder::appendPathCommandAndPoints(const char* command, const FloatPoint points[], size_t length)
 {
-    RefPtr<JSONArray> array = JSONArray::create();
-    array->pushObject(buildObjectForPoint(quad.p1()));
-    array->pushObject(buildObjectForPoint(quad.p2()));
-    array->pushObject(buildObjectForPoint(quad.p3()));
-    array->pushObject(buildObjectForPoint(quad.p4()));
+    m_path->addItem(JSONString::create(command));
+    for (size_t i = 0; i < length; i++) {
+        FloatPoint point = translatePoint(points[i]);
+        m_path->addItem(JSONBasicValue::create(point.x()));
+        m_path->addItem(JSONBasicValue::create(point.y()));
+    }
+}
+
+void PathBuilder::appendPathElement(const PathElement* pathElement)
+{
+    switch (pathElement->type) {
+    // The points member will contain 1 value.
+    case PathElementMoveToPoint:
+        appendPathCommandAndPoints("M", pathElement->points, 1);
+        break;
+    // The points member will contain 1 value.
+    case PathElementAddLineToPoint:
+        appendPathCommandAndPoints("L", pathElement->points, 1);
+        break;
+    // The points member will contain 3 values.
+    case PathElementAddCurveToPoint:
+        appendPathCommandAndPoints("C", pathElement->points, 3);
+        break;
+    // The points member will contain 2 values.
+    case PathElementAddQuadCurveToPoint:
+        appendPathCommandAndPoints("Q", pathElement->points, 2);
+        break;
+    // The points member will contain no values.
+    case PathElementCloseSubpath:
+        appendPathCommandAndPoints("Z", 0, 0);
+        break;
+    }
+}
+
+static RefPtr<TypeBuilder::Array<double> > buildArrayForQuad(const FloatQuad& quad)
+{
+    RefPtr<TypeBuilder::Array<double> > array = TypeBuilder::Array<double>::create();
+    array->addItem(quad.p1().x());
+    array->addItem(quad.p1().y());
+    array->addItem(quad.p2().x());
+    array->addItem(quad.p2().y());
+    array->addItem(quad.p3().x());
+    array->addItem(quad.p3().y());
+    array->addItem(quad.p4().x());
+    array->addItem(quad.p4().y());
     return array.release();
 }
 
-static PassRefPtr<JSONObject> buildObjectForHighlight(const Highlight& highlight)
+static const ShapeOutsideInfo* shapeOutsideInfoForNode(Node* node, Shape::DisplayPaths* paths, FloatQuad* bounds)
 {
-    RefPtr<JSONObject> object = JSONObject::create();
-    RefPtr<JSONArray> array = JSONArray::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());
-    object->setString("eventTargetColor", highlight.eventTargetColor.serialized());
-    return object.release();
+    RenderObject* renderer = node->renderer();
+    if (!renderer || !renderer->isBox() || !toRenderBox(renderer)->shapeOutsideInfo())
+        return 0;
+
+    FrameView* containingView = node->document().view();
+    RenderBox* renderBox = toRenderBox(renderer);
+    const ShapeOutsideInfo* shapeOutsideInfo = renderBox->shapeOutsideInfo();
+
+    shapeOutsideInfo->computedShape().buildDisplayPaths(*paths);
+
+    LayoutRect shapeBounds = shapeOutsideInfo->computedShapePhysicalBoundingBox();
+    *bounds = renderBox->localToAbsoluteQuad(FloatRect(shapeBounds));
+    contentsQuadToScreen(containingView, *bounds);
+
+    return shapeOutsideInfo;
 }
 
-static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size)
+static void appendPathsForShapeOutside(Highlight& highlight, const HighlightConfig& config, Node* node)
 {
-    RefPtr<JSONObject> result = JSONObject::create();
-    result->setNumber("width", size.width());
-    result->setNumber("height", size.height());
-    return result.release();
+    Shape::DisplayPaths paths;
+    FloatQuad boundsQuad;
+
+    const ShapeOutsideInfo* shapeOutsideInfo = shapeOutsideInfoForNode(node, &paths, &boundsQuad);
+    if (!shapeOutsideInfo)
+        return;
+
+    if (!paths.shape.length()) {
+        highlight.appendQuad(boundsQuad, config.shape);
+        return;
+    }
+
+    highlight.appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->renderer(), *shapeOutsideInfo, paths.shape), config.shape, Color::transparent);
+    if (paths.marginShape.length())
+        highlight.appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->renderer(), *shapeOutsideInfo, paths.marginShape), config.shapeMargin, Color::transparent);
+}
+
+PassRefPtr<JSONObject> buildElementInfo(Element* element)
+{
+    RefPtr<JSONObject> elementInfo = JSONObject::create();
+    Element* realElement = element;
+    PseudoElement* pseudoElement = 0;
+    if (element->isPseudoElement()) {
+        pseudoElement = toPseudoElement(element);
+        realElement = element->parentOrShadowHostElement();
+    }
+    bool isXHTML = realElement->document().isXHTMLDocument();
+    elementInfo->setString("tagName", isXHTML ? realElement->nodeName() : realElement->nodeName().lower());
+    elementInfo->setString("idValue", realElement->getIdAttribute());
+    StringBuilder classNames;
+    if (realElement->hasClass() && realElement->isStyledElement()) {
+        HashSet<AtomicString> usedClassNames;
+        const SpaceSplitString& classNamesString = realElement->classNames();
+        size_t classNameCount = classNamesString.size();
+        for (size_t i = 0; i < classNameCount; ++i) {
+            const AtomicString& className = classNamesString[i];
+            if (!usedClassNames.add(className).isNewEntry)
+                continue;
+            classNames.append('.');
+            classNames.append(className);
+        }
+    }
+    if (pseudoElement) {
+        if (pseudoElement->pseudoId() == BEFORE)
+            classNames.appendLiteral("::before");
+        else if (pseudoElement->pseudoId() == AFTER)
+            classNames.appendLiteral("::after");
+    }
+    if (!classNames.isEmpty())
+        elementInfo->setString("className", classNames.toString());
+
+    RenderObject* renderer = element->renderer();
+    FrameView* containingView = element->document().view();
+    if (!renderer || !containingView)
+        return elementInfo;
+
+    IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
+    RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
+    elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
+    elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
+
+    return elementInfo;
 }
 
 void InspectorOverlay::drawNodeHighlight()
@@ -497,59 +662,19 @@ void InspectorOverlay::drawNodeHighlight()
         return;
 
     Highlight highlight;
-    buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
-    if (m_eventTargetNode) {
-        Highlight eventTargetHighlight;
-        buildNodeHighlight(m_eventTargetNode.get(), m_nodeHighlightConfig, &eventTargetHighlight);
-        highlight.quads.append(eventTargetHighlight.quads[1]); // Add border from eventTargetNode to highlight.
-    }
-    RefPtr<JSONObject> highlightObject = buildObjectForHighlight(highlight);
-
-    Node* node = m_highlightNode.get();
-    if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document().frame()) {
-        RefPtr<JSONObject> elementInfo = JSONObject::create();
-        Element* element = toElement(node);
-        Element* realElement = element;
-        PseudoElement* pseudoElement = 0;
-        if (element->isPseudoElement()) {
-            pseudoElement = toPseudoElement(element);
-            realElement = element->parentOrShadowHostElement();
-        }
-        bool isXHTML = realElement->document().isXHTMLDocument();
-        elementInfo->setString("tagName", isXHTML ? realElement->nodeName() : realElement->nodeName().lower());
-        elementInfo->setString("idValue", realElement->getIdAttribute());
-        StringBuilder classNames;
-        if (realElement->hasClass() && realElement->isStyledElement()) {
-            HashSet<AtomicString> usedClassNames;
-            const SpaceSplitString& classNamesString = realElement->classNames();
-            size_t classNameCount = classNamesString.size();
-            for (size_t i = 0; i < classNameCount; ++i) {
-                const AtomicString& className = classNamesString[i];
-                if (!usedClassNames.add(className).isNewEntry)
-                    continue;
-                classNames.append('.');
-                classNames.append(className);
-            }
-        }
-        if (pseudoElement) {
-            if (pseudoElement->pseudoId() == BEFORE)
-                classNames.append("::before");
-            else if (pseudoElement->pseudoId() == AFTER)
-                classNames.append("::after");
-        }
-        if (!classNames.isEmpty())
-            elementInfo->setString("className", classNames.toString());
-
-        RenderObject* renderer = node->renderer();
-        LocalFrame* containingFrame = node->document().frame();
-        FrameView* containingView = containingFrame->view();
-        IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
-        RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
-        elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
-        elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
-        highlightObject->setObject("elementInfo", elementInfo.release());
+    appendPathsForShapeOutside(highlight, m_nodeHighlightConfig, m_highlightNode.get());
+    buildNodeHighlight(*m_highlightNode, m_nodeHighlightConfig, &highlight);
+
+    if (m_eventTargetNode && m_eventTargetNode->renderer()) {
+        FloatQuad border, unused;
+        if (buildNodeQuads(m_eventTargetNode->renderer(), &unused, &unused, &border, &unused))
+            highlight.appendQuad(border, m_nodeHighlightConfig.eventTarget);
     }
-    evaluateInOverlay("drawNodeHighlight", highlightObject);
+
+    if (m_highlightNode->isElementNode() && !m_omitTooltip && m_nodeHighlightConfig.showInfo && m_highlightNode->renderer() && m_highlightNode->document().frame())
+        highlight.setElementInfo(buildElementInfo(toElement(m_highlightNode.get())));
+
+    evaluateInOverlay("drawHighlight", highlight.asJSONObject());
 }
 
 void InspectorOverlay::drawQuadHighlight()
@@ -558,8 +683,8 @@ void InspectorOverlay::drawQuadHighlight()
         return;
 
     Highlight highlight;
-    buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
-    evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
+    highlight.appendQuad(*m_highlightQuad, m_quadHighlightConfig.content, m_quadHighlightConfig.contentOutline);
+    evaluateInOverlay("drawHighlight", highlight.asJSONObject());
 }
 
 void InspectorOverlay::drawPausedInDebuggerMessage()
@@ -579,45 +704,51 @@ Page* InspectorOverlay::overlayPage()
     if (m_overlayPage)
         return m_overlayPage.get();
 
+    ScriptForbiddenScope::AllowUserAgentScript allowScript;
+
     static FrameLoaderClient* dummyFrameLoaderClient =  new EmptyFrameLoaderClient;
     Page::PageClients pageClients;
     fillWithEmptyClients(pageClients);
     ASSERT(!m_overlayChromeClient);
     m_overlayChromeClient = adoptPtr(new InspectorOverlayChromeClient(m_page->chrome().client(), this));
     pageClients.chromeClient = m_overlayChromeClient.get();
-    m_overlayPage = adoptPtr(new Page(pageClients));
+    m_overlayPage = adoptPtrWillBeNoop(new Page(pageClients));
 
     Settings& settings = m_page->settings();
     Settings& overlaySettings = m_overlayPage->settings();
 
-    overlaySettings.genericFontFamilySettings().setStandard(settings.genericFontFamilySettings().standard());
-    overlaySettings.genericFontFamilySettings().setSerif(settings.genericFontFamilySettings().serif());
-    overlaySettings.genericFontFamilySettings().setSansSerif(settings.genericFontFamilySettings().sansSerif());
-    overlaySettings.genericFontFamilySettings().setCursive(settings.genericFontFamilySettings().cursive());
-    overlaySettings.genericFontFamilySettings().setFantasy(settings.genericFontFamilySettings().fantasy());
-    overlaySettings.genericFontFamilySettings().setPictograph(settings.genericFontFamilySettings().pictograph());
+    overlaySettings.genericFontFamilySettings().updateStandard(settings.genericFontFamilySettings().standard());
+    overlaySettings.genericFontFamilySettings().updateSerif(settings.genericFontFamilySettings().serif());
+    overlaySettings.genericFontFamilySettings().updateSansSerif(settings.genericFontFamilySettings().sansSerif());
+    overlaySettings.genericFontFamilySettings().updateCursive(settings.genericFontFamilySettings().cursive());
+    overlaySettings.genericFontFamilySettings().updateFantasy(settings.genericFontFamilySettings().fantasy());
+    overlaySettings.genericFontFamilySettings().updatePictograph(settings.genericFontFamilySettings().pictograph());
     overlaySettings.setMinimumFontSize(settings.minimumFontSize());
     overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
     overlaySettings.setScriptEnabled(true);
     overlaySettings.setPluginsEnabled(false);
     overlaySettings.setLoadsImagesAutomatically(true);
+    // FIXME: http://crbug.com/363843. Inspector should probably create its
+    // own graphics layers and attach them to the tree rather than going
+    // through some non-composited paint function.
+    overlaySettings.setAcceleratedCompositingEnabled(false);
 
-    RefPtr<LocalFrame> frame = LocalFrame::create(dummyFrameLoaderClient, &m_overlayPage->frameHost(), 0);
+    RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(dummyFrameLoaderClient, &m_overlayPage->frameHost(), 0);
     frame->setView(FrameView::create(frame.get()));
     frame->init();
     FrameLoader& loader = frame->loader();
     frame->view()->setCanHaveScrollbars(false);
     frame->view()->setTransparent(true);
 
-    RefPtr<SharedBuffer> data = SharedBuffer::create(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
+    const blink::WebData& overlayPageHTMLResource = blink::Platform::current()->loadResource("InspectorOverlayPage.html");
+    RefPtr<SharedBuffer> data = SharedBuffer::create(overlayPageHTMLResource.data(), overlayPageHTMLResource.size());
     loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
     v8::Isolate* isolate = toIsolate(frame.get());
-    v8::HandleScope handleScope(isolate);
-    v8::Handle<v8::Context> frameContext = toV8Context(isolate, frame.get(), DOMWrapperWorld::mainWorld());
-    ASSERT(!frameContext.IsEmpty());
-    v8::Context::Scope contextScope(frameContext);
-    v8::Handle<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), v8::Handle<v8::Object>(), isolate);
-    v8::Handle<v8::Object> global = frameContext->Global();
+    ScriptState* scriptState = ScriptState::forMainWorld(frame.get());
+    ASSERT(!scriptState->contextIsValid());
+    ScriptState::Scope scope(scriptState);
+    v8::Handle<v8::Object> global = scriptState->context()->Global();
+    v8::Handle<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), global, isolate);
     global->Set(v8::String::NewFromUtf8(isolate, "InspectorOverlayHost"), overlayHostObj);
 
 #if OS(WIN)
@@ -631,14 +762,13 @@ Page* InspectorOverlay::overlayPage()
     return m_overlayPage.get();
 }
 
-void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize, int scrollX, int scrollY)
+void InspectorOverlay::reset(const IntSize& viewportSize, int scrollX, int scrollY)
 {
     RefPtr<JSONObject> resetData = JSONObject::create();
-    resetData->setNumber("pageScaleFactor", m_page->pageScaleFactor());
+    resetData->setNumber("pageScaleFactor", m_page->settings().pinchVirtualViewportEnabled() ? 1 : m_page->pageScaleFactor());
     resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
     resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
-    resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
-    resetData->setNumber("pageZoomFactor", m_page->mainFrame()->pageZoomFactor());
+    resetData->setNumber("pageZoomFactor", m_page->deprecatedLocalMainFrame()->pageZoomFactor());
     resetData->setNumber("scrollX", scrollX);
     resetData->setNumber("scrollY", scrollY);
     evaluateInOverlay("reset", resetData.release());
@@ -646,18 +776,20 @@ void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameVi
 
 void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
 {
+    ScriptForbiddenScope::AllowUserAgentScript allowScript;
     RefPtr<JSONArray> command = JSONArray::create();
     command->pushString(method);
     command->pushString(argument);
-    overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
+    toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
 }
 
 void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<JSONValue> argument)
 {
+    ScriptForbiddenScope::AllowUserAgentScript allowScript;
     RefPtr<JSONArray> command = JSONArray::create();
     command->pushString(method);
     command->pushValue(argument);
-    overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
+    toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
 }
 
 void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
@@ -666,21 +798,52 @@ void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
     update();
 }
 
-bool InspectorOverlay::getBoxModel(Node* node, Vector<FloatQuad>* quads)
+bool InspectorOverlay::getBoxModel(Node* node, RefPtr<TypeBuilder::DOM::BoxModel>& model)
 {
-    return buildNodeQuads(node, *quads);
+    RenderObject* renderer = node->renderer();
+    FrameView* view = node->document().view();
+    if (!renderer || !view)
+        return false;
+
+    FloatQuad content, padding, border, margin;
+    if (!buildNodeQuads(node->renderer(), &content, &padding, &border, &margin))
+        return false;
+
+    IntRect boundingBox = pixelSnappedIntRect(view->contentsToRootView(renderer->absoluteBoundingBoxRect()));
+    RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
+
+    model = TypeBuilder::DOM::BoxModel::create()
+        .setContent(buildArrayForQuad(content))
+        .setPadding(buildArrayForQuad(padding))
+        .setBorder(buildArrayForQuad(border))
+        .setMargin(buildArrayForQuad(margin))
+        .setWidth(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width())
+        .setHeight(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height());
+
+    Shape::DisplayPaths paths;
+    FloatQuad boundsQuad;
+    if (const ShapeOutsideInfo* shapeOutsideInfo = shapeOutsideInfoForNode(node, &paths, &boundsQuad)) {
+        RefPtr<TypeBuilder::DOM::ShapeOutsideInfo> shapeTypeBuilder = TypeBuilder::DOM::ShapeOutsideInfo::create()
+            .setBounds(buildArrayForQuad(boundsQuad))
+            .setShape(ShapePathBuilder::buildPath(*view, *renderer, *shapeOutsideInfo, paths.shape))
+            .setMarginShape(ShapePathBuilder::buildPath(*view, *renderer, *shapeOutsideInfo, paths.marginShape));
+        model->setShapeOutside(shapeTypeBuilder);
+    }
+
+    return true;
 }
 
 void InspectorOverlay::freePage()
 {
     if (m_overlayPage) {
-        // FIXME: This logic is duplicated in SVGImage and WebViewImpl. Perhaps it can be combined
-        // into Page's destructor.
-        m_overlayPage->mainFrame()->loader().frameDetached();
+        m_overlayPage->willBeDestroyed();
         m_overlayPage.clear();
     }
     m_overlayChromeClient.clear();
     m_timer.stop();
+
+    // This will clear internal structures and issue update to the client. Safe to call last.
+    hideHighlight();
 }
 
 void InspectorOverlay::startedRecordingProfile()
@@ -689,4 +852,4 @@ void InspectorOverlay::startedRecordingProfile()
         freePage();
 }
 
-} // namespace WebCore
+} // namespace blink