#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)
InspectorOverlay* m_overlay;
};
-Path quadToPath(const FloatQuad& quad)
+static Path quadToPath(const FloatQuad& quad)
{
Path quadPath;
quadPath.moveTo(quad.p1());
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;
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
, m_overlayHost(InspectorOverlayHost::create())
, m_drawViewSize(false)
, m_drawViewSizeWithGrid(false)
+ , m_omitTooltip(false)
, m_timer(this, &InspectorOverlay::onTimer)
, m_activeProfilerCount(0)
{
InspectorOverlay::~InspectorOverlay()
{
+ ASSERT(!m_overlayPage);
}
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()));
}
if (isEmpty())
return false;
- return overlayPage()->mainFrame()->eventHandler().handleGestureEvent(event);
+ return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleGestureEvent(event);
}
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)
if (isEmpty())
return false;
- return overlayPage()->mainFrame()->eventHandler().handleTouchEvent(event);
+ return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleTouchEvent(event);
}
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)
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();
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();
}
{
m_quadHighlightConfig = highlightConfig;
m_highlightQuad = quad;
+ m_omitTooltip = false;
update();
}
{
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));
}
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();
drawPausedInDebuggerMessage();
drawViewSize();
- // Position DOM elements.
- overlayPage()->mainFrame()->document()->setNeedsStyleRecalc(SubtreeStyleChange);
- overlayPage()->mainFrame()->document()->updateLayout();
+ toLocalFrame(overlayPage()->mainFrame())->view()->updateLayoutAndStyleForPainting();
- // Kick paint.
m_client->highlight();
}
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()
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()
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()
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)
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());
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>*)
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()
freePage();
}
-} // namespace WebCore
+} // namespace blink