2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "core/inspector/InspectorOverlay.h"
32 #include "bindings/core/v8/V8InspectorOverlayHost.h"
33 #include "bindings/v8/ScriptController.h"
34 #include "bindings/v8/ScriptSourceCode.h"
35 #include "core/InspectorOverlayPage.h"
36 #include "core/dom/Element.h"
37 #include "core/dom/Node.h"
38 #include "core/dom/PseudoElement.h"
39 #include "core/frame/FrameView.h"
40 #include "core/frame/LocalFrame.h"
41 #include "core/inspector/InspectorClient.h"
42 #include "core/inspector/InspectorOverlayHost.h"
43 #include "core/loader/EmptyClients.h"
44 #include "core/loader/FrameLoadRequest.h"
45 #include "core/page/Chrome.h"
46 #include "core/page/EventHandler.h"
47 #include "core/page/Page.h"
48 #include "core/frame/Settings.h"
49 #include "core/rendering/RenderBoxModelObject.h"
50 #include "core/rendering/RenderInline.h"
51 #include "core/rendering/RenderObject.h"
52 #include "core/rendering/style/RenderStyleConstants.h"
53 #include "platform/JSONValues.h"
54 #include "platform/PlatformMouseEvent.h"
55 #include "platform/graphics/GraphicsContextStateSaver.h"
56 #include "wtf/text/StringBuilder.h"
63 struct PathApplyInfo {
66 TypeBuilder::Array<JSONValue>* array;
67 RenderObject* renderer;
68 const ShapeOutsideInfo* shapeOutsideInfo;
71 class InspectorOverlayChromeClient FINAL: public EmptyChromeClient {
73 InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay* overlay)
78 virtual void setCursor(const Cursor& cursor) OVERRIDE
80 m_client.setCursor(cursor);
83 virtual void setToolTip(const String& tooltip, TextDirection direction) OVERRIDE
85 m_client.setToolTip(tooltip, direction);
88 virtual void invalidateContentsAndRootView(const IntRect&) OVERRIDE
90 m_overlay->invalidate();
93 virtual void invalidateContentsForSlowScroll(const IntRect&) OVERRIDE
95 m_overlay->invalidate();
99 ChromeClient& m_client;
100 InspectorOverlay* m_overlay;
103 Path quadToPath(const FloatQuad& quad)
106 quadPath.moveTo(quad.p1());
107 quadPath.addLineTo(quad.p2());
108 quadPath.addLineTo(quad.p3());
109 quadPath.addLineTo(quad.p4());
110 quadPath.closeSubpath();
114 void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
116 static const int outlineThickness = 2;
118 Path quadPath = quadToPath(quad);
120 // Clip out the quad, then draw with a 2px stroke to get a pixel
121 // of outline (because inflating a quad is hard)
124 context->clipOut(quadPath);
126 context->setStrokeThickness(outlineThickness);
127 context->setStrokeColor(outlineColor);
128 context->strokePath(quadPath);
134 context->setFillColor(fillColor);
135 context->fillPath(quadPath);
138 static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
140 quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
141 quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
142 quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
143 quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));
144 quad += mainView->scrollOffset();
147 static bool buildNodeQuads(Node* node, Vector<FloatQuad>& quads)
149 RenderObject* renderer = node->renderer();
150 LocalFrame* containingFrame = node->document().frame();
152 if (!renderer || !containingFrame)
155 FrameView* containingView = containingFrame->view();
156 FrameView* mainView = containingFrame->page()->deprecatedLocalMainFrame()->view();
157 IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
158 boundingBox.move(mainView->scrollOffset());
160 // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
161 if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot()) {
162 renderer->absoluteQuads(quads);
163 for (size_t i = 0; i < quads.size(); ++i)
164 contentsQuadToPage(mainView, containingView, quads[i]);
168 if (!renderer->isBox() && !renderer->isRenderInline())
171 LayoutRect contentBox;
172 LayoutRect paddingBox;
173 LayoutRect borderBox;
174 LayoutRect marginBox;
176 if (renderer->isBox()) {
177 RenderBox* renderBox = toRenderBox(renderer);
179 // RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
180 contentBox = renderBox->contentBoxRect();
181 contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
182 contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
184 paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
185 contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
186 borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
187 paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
188 marginBox = LayoutRect(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
189 borderBox.width() + renderBox->marginWidth(), borderBox.height() + renderBox->marginHeight());
191 RenderInline* renderInline = toRenderInline(renderer);
193 // RenderInline's bounding box includes paddings and borders, excludes margins.
194 borderBox = renderInline->linesBoundingBox();
195 paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
196 borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
197 contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
198 paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
199 // Ignore marginTop and marginBottom for inlines.
200 marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
201 borderBox.width() + renderInline->marginWidth(), borderBox.height());
204 FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
205 FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
206 FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
207 FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
209 contentsQuadToPage(mainView, containingView, absContentQuad);
210 contentsQuadToPage(mainView, containingView, absPaddingQuad);
211 contentsQuadToPage(mainView, containingView, absBorderQuad);
212 contentsQuadToPage(mainView, containingView, absMarginQuad);
214 quads.append(absMarginQuad);
215 quads.append(absBorderQuad);
216 quads.append(absPaddingQuad);
217 quads.append(absContentQuad);
222 static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
224 RenderObject* renderer = node->renderer();
225 LocalFrame* containingFrame = node->document().frame();
227 if (!renderer || !containingFrame)
230 highlight->setDataFromConfig(highlightConfig);
232 // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
233 if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot())
234 highlight->type = HighlightTypeRects;
235 else if (renderer->isBox() || renderer->isRenderInline())
236 highlight->type = HighlightTypeNode;
237 buildNodeQuads(node, highlight->quads);
240 static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
244 highlight->setDataFromConfig(highlightConfig);
245 highlight->type = HighlightTypeRects;
246 highlight->quads.append(quad);
249 } // anonymous namespace
251 InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
254 , m_inspectModeEnabled(false)
255 , m_overlayHost(InspectorOverlayHost::create())
256 , m_drawViewSize(false)
257 , m_drawViewSizeWithGrid(false)
258 , m_omitTooltip(false)
259 , m_timer(this, &InspectorOverlay::onTimer)
260 , m_activeProfilerCount(0)
264 InspectorOverlay::~InspectorOverlay()
266 ASSERT(!m_overlayPage);
269 void InspectorOverlay::paint(GraphicsContext& context)
273 GraphicsContextStateSaver stateSaver(context);
274 FrameView* view = toLocalFrame(overlayPage()->mainFrame())->view();
275 ASSERT(!view->needsLayout());
276 view->paint(&context, IntRect(0, 0, view->width(), view->height()));
279 void InspectorOverlay::invalidate()
281 m_client->highlight();
284 bool InspectorOverlay::handleGestureEvent(const PlatformGestureEvent& event)
289 return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleGestureEvent(event);
292 bool InspectorOverlay::handleMouseEvent(const PlatformMouseEvent& event)
297 EventHandler& eventHandler = toLocalFrame(overlayPage()->mainFrame())->eventHandler();
299 switch (event.type()) {
300 case PlatformEvent::MouseMoved:
301 result = eventHandler.handleMouseMoveEvent(event);
303 case PlatformEvent::MousePressed:
304 result = eventHandler.handleMousePressEvent(event);
306 case PlatformEvent::MouseReleased:
307 result = eventHandler.handleMouseReleaseEvent(event);
313 toLocalFrame(overlayPage()->mainFrame())->document()->updateLayout();
317 bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event)
322 return toLocalFrame(overlayPage()->mainFrame())->eventHandler().handleTouchEvent(event);
325 bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event)
330 return toLocalFrame(overlayPage()->mainFrame())->eventHandler().keyEvent(event);
333 void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
335 FloatRect outlineRect = rect;
336 drawOutlinedQuad(context, outlineRect, Color(), color);
339 void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
341 m_pausedInDebuggerMessage = message ? *message : String();
345 void InspectorOverlay::setInspectModeEnabled(bool enabled)
347 m_inspectModeEnabled = enabled;
351 void InspectorOverlay::hideHighlight()
353 m_highlightNode.clear();
354 m_eventTargetNode.clear();
355 m_highlightQuad.clear();
359 void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig, bool omitTooltip)
361 m_nodeHighlightConfig = highlightConfig;
362 m_highlightNode = node;
363 m_eventTargetNode = eventTarget;
364 m_omitTooltip = omitTooltip;
368 void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig)
370 m_quadHighlightConfig = highlightConfig;
371 m_highlightQuad = quad;
372 m_omitTooltip = false;
376 void InspectorOverlay::showAndHideViewSize(bool showGrid)
378 m_drawViewSize = true;
379 m_drawViewSizeWithGrid = showGrid;
381 m_timer.startOneShot(1, FROM_HERE);
384 Node* InspectorOverlay::highlightedNode() const
386 return m_highlightNode.get();
389 bool InspectorOverlay::isEmpty()
391 if (m_activeProfilerCount)
393 bool hasAlwaysVisibleElements = m_highlightNode || m_eventTargetNode || m_highlightQuad || m_drawViewSize;
394 bool hasInvisibleInInspectModeElements = !m_pausedInDebuggerMessage.isNull();
395 return !(hasAlwaysVisibleElements || (hasInvisibleInInspectModeElements && !m_inspectModeEnabled));
398 void InspectorOverlay::update()
401 m_client->hideHighlight();
405 FrameView* view = m_page->deprecatedLocalMainFrame()->view();
409 // Include scrollbars to avoid masking them by the gutter.
410 IntSize size = view->unscaledVisibleContentSize(IncludeScrollbars);
411 toLocalFrame(overlayPage()->mainFrame())->view()->resize(size);
413 // Clear canvas and paint things.
414 IntRect viewRect = view->visibleContentRect();
415 reset(size, viewRect.x(), viewRect.y());
419 if (!m_inspectModeEnabled)
420 drawPausedInDebuggerMessage();
423 // Position DOM elements.
424 toLocalFrame(overlayPage()->mainFrame())->document()->setNeedsStyleRecalc(SubtreeStyleChange);
425 toLocalFrame(overlayPage()->mainFrame())->document()->updateLayout();
428 m_client->highlight();
431 void InspectorOverlay::hide()
434 m_highlightNode.clear();
435 m_eventTargetNode.clear();
436 m_highlightQuad.clear();
437 m_pausedInDebuggerMessage = String();
438 m_drawViewSize = false;
439 m_drawViewSizeWithGrid = false;
443 static PassRefPtr<JSONObject> buildObjectForPoint(const FloatPoint& point)
445 RefPtr<JSONObject> object = JSONObject::create();
446 object->setNumber("x", point.x());
447 object->setNumber("y", point.y());
448 return object.release();
451 static PassRefPtr<JSONArray> buildArrayForQuad(const FloatQuad& quad)
453 RefPtr<JSONArray> array = JSONArray::create();
454 array->pushObject(buildObjectForPoint(quad.p1()));
455 array->pushObject(buildObjectForPoint(quad.p2()));
456 array->pushObject(buildObjectForPoint(quad.p3()));
457 array->pushObject(buildObjectForPoint(quad.p4()));
458 return array.release();
461 static PassRefPtr<JSONObject> buildObjectForHighlight(const Highlight& highlight)
463 RefPtr<JSONObject> object = JSONObject::create();
464 RefPtr<JSONArray> array = JSONArray::create();
465 for (size_t i = 0; i < highlight.quads.size(); ++i)
466 array->pushArray(buildArrayForQuad(highlight.quads[i]));
467 object->setArray("quads", array.release());
468 object->setBoolean("showRulers", highlight.showRulers);
469 object->setString("contentColor", highlight.contentColor.serialized());
470 object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
471 object->setString("paddingColor", highlight.paddingColor.serialized());
472 object->setString("borderColor", highlight.borderColor.serialized());
473 object->setString("marginColor", highlight.marginColor.serialized());
474 object->setString("eventTargetColor", highlight.eventTargetColor.serialized());
475 return object.release();
478 static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size)
480 RefPtr<JSONObject> result = JSONObject::create();
481 result->setNumber("width", size.width());
482 result->setNumber("height", size.height());
483 return result.release();
487 static void appendPathCommandAndPoints(PathApplyInfo* info, const String& command, const FloatPoint points[], unsigned length)
490 info->array->addItem(JSONString::create(command));
491 for (unsigned i = 0; i < length; i++) {
492 point = info->shapeOutsideInfo->shapeToRendererPoint(points[i]);
493 point = info->view->contentsToRootView(roundedIntPoint(info->renderer->localToAbsolute(point))) + info->rootView->scrollOffset();
494 info->array->addItem(JSONBasicValue::create(point.x()));
495 info->array->addItem(JSONBasicValue::create(point.y()));
499 static void appendPathSegment(void* info, const PathElement* pathElement)
501 PathApplyInfo* pathApplyInfo = static_cast<PathApplyInfo*>(info);
503 switch (pathElement->type) {
504 // The points member will contain 1 value.
505 case PathElementMoveToPoint:
506 appendPathCommandAndPoints(pathApplyInfo, "M", pathElement->points, 1);
508 // The points member will contain 1 value.
509 case PathElementAddLineToPoint:
510 appendPathCommandAndPoints(pathApplyInfo, "L", pathElement->points, 1);
512 // The points member will contain 3 values.
513 case PathElementAddCurveToPoint:
514 appendPathCommandAndPoints(pathApplyInfo, "C", pathElement->points, 3);
516 // The points member will contain 2 values.
517 case PathElementAddQuadCurveToPoint:
518 appendPathCommandAndPoints(pathApplyInfo, "Q", pathElement->points, 2);
520 // The points member will contain no values.
521 case PathElementCloseSubpath:
522 appendPathCommandAndPoints(pathApplyInfo, "Z", 0, 0);
527 static RefPtr<TypeBuilder::Array<double> > buildArrayForQuadTypeBuilder(const FloatQuad& quad)
529 RefPtr<TypeBuilder::Array<double> > array = TypeBuilder::Array<double>::create();
530 array->addItem(quad.p1().x());
531 array->addItem(quad.p1().y());
532 array->addItem(quad.p2().x());
533 array->addItem(quad.p2().y());
534 array->addItem(quad.p3().x());
535 array->addItem(quad.p3().y());
536 array->addItem(quad.p4().x());
537 array->addItem(quad.p4().y());
538 return array.release();
541 PassRefPtr<TypeBuilder::DOM::ShapeOutsideInfo> InspectorOverlay::buildObjectForShapeOutside(Node* node)
543 RenderObject* renderer = node->renderer();
544 if (!renderer || !renderer->isBox() || !toRenderBox(renderer)->shapeOutsideInfo())
547 LocalFrame* containingFrame = node->document().frame();
548 RenderBox* renderBox = toRenderBox(renderer);
549 const ShapeOutsideInfo* shapeOutsideInfo = renderBox->shapeOutsideInfo();
551 LayoutRect shapeBounds = shapeOutsideInfo->computedShapePhysicalBoundingBox();
552 FloatQuad shapeQuad = renderBox->localToAbsoluteQuad(FloatRect(shapeBounds));
553 FrameView* mainView = containingFrame->page()->deprecatedLocalMainFrame()->view();
554 FrameView* containingView = containingFrame->view();
555 contentsQuadToPage(mainView, containingView, shapeQuad);
557 Shape::DisplayPaths paths;
558 shapeOutsideInfo->computedShape().buildDisplayPaths(paths);
559 RefPtr<TypeBuilder::Array<JSONValue> > shapePath = TypeBuilder::Array<JSONValue>::create();
560 RefPtr<TypeBuilder::Array<JSONValue> > marginShapePath = TypeBuilder::Array<JSONValue>::create();
562 if (paths.shape.length()) {
564 info.rootView = mainView;
565 info.view = containingView;
566 info.array = shapePath.get();
567 info.renderer = renderBox;
568 info.shapeOutsideInfo = shapeOutsideInfo;
569 paths.shape.apply(&info, &appendPathSegment);
571 if (paths.marginShape.length()) {
572 info.array = marginShapePath.get();
573 paths.marginShape.apply(&info, &appendPathSegment);
576 RefPtr<TypeBuilder::DOM::ShapeOutsideInfo> shapeTypeBuilder = TypeBuilder::DOM::ShapeOutsideInfo::create()
577 .setBounds(buildArrayForQuadTypeBuilder(shapeQuad))
579 .setMarginShape(marginShapePath);
581 return shapeTypeBuilder.release();
584 static void setElementInfo(RefPtr<JSONObject>& highlightObject, RefPtr<JSONObject>& shapeObject, Node* node)
586 RefPtr<JSONObject> elementInfo = JSONObject::create();
587 Element* element = toElement(node);
588 Element* realElement = element;
589 PseudoElement* pseudoElement = 0;
590 if (element->isPseudoElement()) {
591 pseudoElement = toPseudoElement(element);
592 realElement = element->parentOrShadowHostElement();
594 bool isXHTML = realElement->document().isXHTMLDocument();
595 elementInfo->setString("tagName", isXHTML ? realElement->nodeName() : realElement->nodeName().lower());
596 elementInfo->setString("idValue", realElement->getIdAttribute());
597 StringBuilder classNames;
598 if (realElement->hasClass() && realElement->isStyledElement()) {
599 HashSet<AtomicString> usedClassNames;
600 const SpaceSplitString& classNamesString = realElement->classNames();
601 size_t classNameCount = classNamesString.size();
602 for (size_t i = 0; i < classNameCount; ++i) {
603 const AtomicString& className = classNamesString[i];
604 if (!usedClassNames.add(className).isNewEntry)
606 classNames.append('.');
607 classNames.append(className);
611 if (pseudoElement->pseudoId() == BEFORE)
612 classNames.append("::before");
613 else if (pseudoElement->pseudoId() == AFTER)
614 classNames.append("::after");
616 if (!classNames.isEmpty())
617 elementInfo->setString("className", classNames.toString());
619 RenderObject* renderer = node->renderer();
620 LocalFrame* containingFrame = node->document().frame();
621 FrameView* containingView = containingFrame->view();
622 IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
623 RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
624 elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
625 elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
626 if (renderer->isBox() && shapeObject)
627 elementInfo->setObject("shapeOutsideInfo", shapeObject.release());
628 highlightObject->setObject("elementInfo", elementInfo.release());
631 void InspectorOverlay::drawNodeHighlight()
633 if (!m_highlightNode)
637 buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
638 if (m_eventTargetNode) {
639 Highlight eventTargetHighlight;
640 buildNodeHighlight(m_eventTargetNode.get(), m_nodeHighlightConfig, &eventTargetHighlight);
641 highlight.quads.append(eventTargetHighlight.quads[1]); // Add border from eventTargetNode to highlight.
643 RefPtr<JSONObject> highlightObject = buildObjectForHighlight(highlight);
645 Node* node = m_highlightNode.get();
646 RefPtr<TypeBuilder::DOM::ShapeOutsideInfo> shapeObject = buildObjectForShapeOutside(node);
647 RefPtr<JSONObject> shapeObjectJSON = shapeObject ? shapeObject->asObject() : nullptr;
648 if (node->isElementNode() && !m_omitTooltip && m_nodeHighlightConfig.showInfo && node->renderer() && node->document().frame())
649 setElementInfo(highlightObject, shapeObjectJSON, node);
650 evaluateInOverlay("drawNodeHighlight", highlightObject);
653 void InspectorOverlay::drawQuadHighlight()
655 if (!m_highlightQuad)
659 buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
660 evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
663 void InspectorOverlay::drawPausedInDebuggerMessage()
665 if (!m_pausedInDebuggerMessage.isNull())
666 evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
669 void InspectorOverlay::drawViewSize()
672 evaluateInOverlay("drawViewSize", m_drawViewSizeWithGrid ? "true" : "false");
675 Page* InspectorOverlay::overlayPage()
678 return m_overlayPage.get();
680 static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient;
681 Page::PageClients pageClients;
682 fillWithEmptyClients(pageClients);
683 ASSERT(!m_overlayChromeClient);
684 m_overlayChromeClient = adoptPtr(new InspectorOverlayChromeClient(m_page->chrome().client(), this));
685 pageClients.chromeClient = m_overlayChromeClient.get();
686 m_overlayPage = adoptPtrWillBeNoop(new Page(pageClients));
688 Settings& settings = m_page->settings();
689 Settings& overlaySettings = m_overlayPage->settings();
691 overlaySettings.genericFontFamilySettings().setStandard(settings.genericFontFamilySettings().standard());
692 overlaySettings.genericFontFamilySettings().setSerif(settings.genericFontFamilySettings().serif());
693 overlaySettings.genericFontFamilySettings().setSansSerif(settings.genericFontFamilySettings().sansSerif());
694 overlaySettings.genericFontFamilySettings().setCursive(settings.genericFontFamilySettings().cursive());
695 overlaySettings.genericFontFamilySettings().setFantasy(settings.genericFontFamilySettings().fantasy());
696 overlaySettings.genericFontFamilySettings().setPictograph(settings.genericFontFamilySettings().pictograph());
697 overlaySettings.setMinimumFontSize(settings.minimumFontSize());
698 overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
699 overlaySettings.setScriptEnabled(true);
700 overlaySettings.setPluginsEnabled(false);
701 overlaySettings.setLoadsImagesAutomatically(true);
702 // FIXME: http://crbug.com/363843. Inspector should probably create its
703 // own graphics layers and attach them to the tree rather than going
704 // through some non-composited paint function.
705 overlaySettings.setAcceleratedCompositingEnabled(false);
707 RefPtr<LocalFrame> frame = LocalFrame::create(dummyFrameLoaderClient, &m_overlayPage->frameHost(), 0);
708 frame->setView(FrameView::create(frame.get()));
710 FrameLoader& loader = frame->loader();
711 frame->view()->setCanHaveScrollbars(false);
712 frame->view()->setTransparent(true);
714 RefPtr<SharedBuffer> data = SharedBuffer::create(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
715 loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
716 v8::Isolate* isolate = toIsolate(frame.get());
717 ScriptState* scriptState = ScriptState::forMainWorld(frame.get());
718 ASSERT(!scriptState->contextIsEmpty());
719 ScriptState::Scope scope(scriptState);
720 v8::Handle<v8::Object> global = scriptState->context()->Global();
721 v8::Handle<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), global, isolate);
722 global->Set(v8::String::NewFromUtf8(isolate, "InspectorOverlayHost"), overlayHostObj);
725 evaluateInOverlay("setPlatform", "windows");
727 evaluateInOverlay("setPlatform", "mac");
729 evaluateInOverlay("setPlatform", "linux");
732 return m_overlayPage.get();
735 void InspectorOverlay::reset(const IntSize& viewportSize, int scrollX, int scrollY)
737 RefPtr<JSONObject> resetData = JSONObject::create();
738 resetData->setNumber("pageScaleFactor", m_page->settings().pinchVirtualViewportEnabled() ? 1 : m_page->pageScaleFactor());
739 resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
740 resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
741 resetData->setNumber("pageZoomFactor", m_page->deprecatedLocalMainFrame()->pageZoomFactor());
742 resetData->setNumber("scrollX", scrollX);
743 resetData->setNumber("scrollY", scrollY);
744 evaluateInOverlay("reset", resetData.release());
747 void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
749 RefPtr<JSONArray> command = JSONArray::create();
750 command->pushString(method);
751 command->pushString(argument);
752 toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
755 void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<JSONValue> argument)
757 RefPtr<JSONArray> command = JSONArray::create();
758 command->pushString(method);
759 command->pushValue(argument);
760 toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
763 void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
765 m_drawViewSize = false;
769 bool InspectorOverlay::getBoxModel(Node* node, Vector<FloatQuad>* quads)
771 return buildNodeQuads(node, *quads);
774 void InspectorOverlay::freePage()
777 m_overlayPage->willBeDestroyed();
778 m_overlayPage.clear();
780 m_overlayChromeClient.clear();
783 // This will clear internal structures and issue update to the client. Safe to call last.
787 void InspectorOverlay::startedRecordingProfile()
789 if (!m_activeProfilerCount++)
793 } // namespace WebCore