• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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.
16  *
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.
27  */
28 
29 #include "config.h"
30 #include "core/inspector/InspectorOverlay.h"
31 
32 #include "InspectorOverlayPage.h"
33 #include "V8InspectorOverlayHost.h"
34 #include "bindings/v8/ScriptController.h"
35 #include "bindings/v8/ScriptSourceCode.h"
36 #include "core/dom/Element.h"
37 #include "core/dom/Node.h"
38 #include "core/dom/PseudoElement.h"
39 #include "core/inspector/InspectorClient.h"
40 #include "core/inspector/InspectorOverlayHost.h"
41 #include "core/loader/DocumentLoader.h"
42 #include "core/loader/EmptyClients.h"
43 #include "core/page/Chrome.h"
44 #include "core/page/EventHandler.h"
45 #include "core/frame/Frame.h"
46 #include "core/frame/FrameView.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"
57 
58 namespace WebCore {
59 
60 namespace {
61 
62 class InspectorOverlayChromeClient: public EmptyChromeClient {
63 public:
InspectorOverlayChromeClient(ChromeClient & client,InspectorOverlay * overlay)64     InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay* overlay)
65         : m_client(client)
66         , m_overlay(overlay)
67     { }
68 
setCursor(const Cursor & cursor)69     virtual void setCursor(const Cursor& cursor)
70     {
71         m_client.setCursor(cursor);
72     }
73 
setToolTip(const String & tooltip,TextDirection direction)74     virtual void setToolTip(const String& tooltip, TextDirection direction)
75     {
76         m_client.setToolTip(tooltip, direction);
77     }
78 
invalidateRootView(const IntRect & rect)79     virtual void invalidateRootView(const IntRect& rect)
80     {
81         m_overlay->invalidate();
82     }
83 
invalidateContentsAndRootView(const IntRect & rect)84     virtual void invalidateContentsAndRootView(const IntRect& rect)
85     {
86         m_overlay->invalidate();
87     }
88 
invalidateContentsForSlowScroll(const IntRect & rect)89     virtual void invalidateContentsForSlowScroll(const IntRect& rect)
90     {
91         m_overlay->invalidate();
92     }
93 
94 private:
95     ChromeClient& m_client;
96     InspectorOverlay* m_overlay;
97 };
98 
quadToPath(const FloatQuad & quad)99 Path quadToPath(const FloatQuad& quad)
100 {
101     Path quadPath;
102     quadPath.moveTo(quad.p1());
103     quadPath.addLineTo(quad.p2());
104     quadPath.addLineTo(quad.p3());
105     quadPath.addLineTo(quad.p4());
106     quadPath.closeSubpath();
107     return quadPath;
108 }
109 
drawOutlinedQuad(GraphicsContext * context,const FloatQuad & quad,const Color & fillColor,const Color & outlineColor)110 void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
111 {
112     static const int outlineThickness = 2;
113 
114     Path quadPath = quadToPath(quad);
115 
116     // Clip out the quad, then draw with a 2px stroke to get a pixel
117     // of outline (because inflating a quad is hard)
118     {
119         context->save();
120         context->clipOut(quadPath);
121 
122         context->setStrokeThickness(outlineThickness);
123         context->setStrokeColor(outlineColor);
124         context->strokePath(quadPath);
125 
126         context->restore();
127     }
128 
129     // Now do the fill
130     context->setFillColor(fillColor);
131     context->fillPath(quadPath);
132 }
133 
contentsQuadToPage(const FrameView * mainView,const FrameView * view,FloatQuad & quad)134 static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
135 {
136     quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
137     quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
138     quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
139     quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));
140     quad += mainView->scrollOffset();
141 }
142 
buildNodeQuads(Node * node,Vector<FloatQuad> & quads)143 static bool buildNodeQuads(Node* node, Vector<FloatQuad>& quads)
144 {
145     RenderObject* renderer = node->renderer();
146     Frame* containingFrame = node->document().frame();
147 
148     if (!renderer || !containingFrame)
149         return false;
150 
151     FrameView* containingView = containingFrame->view();
152     FrameView* mainView = containingFrame->page()->mainFrame()->view();
153     IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
154     boundingBox.move(mainView->scrollOffset());
155 
156     // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
157     if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot()) {
158         renderer->absoluteQuads(quads);
159         for (size_t i = 0; i < quads.size(); ++i)
160             contentsQuadToPage(mainView, containingView, quads[i]);
161         return false;
162     }
163 
164     if (!renderer->isBox() && !renderer->isRenderInline())
165         return false;
166 
167     LayoutRect contentBox;
168     LayoutRect paddingBox;
169     LayoutRect borderBox;
170     LayoutRect marginBox;
171 
172     if (renderer->isBox()) {
173         RenderBox* renderBox = toRenderBox(renderer);
174 
175         // RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
176         contentBox = renderBox->contentBoxRect();
177         contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
178         contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
179 
180         paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
181             contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
182         borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
183             paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
184         marginBox = LayoutRect(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
185             borderBox.width() + renderBox->marginWidth(), borderBox.height() + renderBox->marginHeight());
186     } else {
187         RenderInline* renderInline = toRenderInline(renderer);
188 
189         // RenderInline's bounding box includes paddings and borders, excludes margins.
190         borderBox = renderInline->linesBoundingBox();
191         paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
192             borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
193         contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
194             paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
195         // Ignore marginTop and marginBottom for inlines.
196         marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
197             borderBox.width() + renderInline->marginWidth(), borderBox.height());
198     }
199 
200     FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
201     FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
202     FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
203     FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
204 
205     contentsQuadToPage(mainView, containingView, absContentQuad);
206     contentsQuadToPage(mainView, containingView, absPaddingQuad);
207     contentsQuadToPage(mainView, containingView, absBorderQuad);
208     contentsQuadToPage(mainView, containingView, absMarginQuad);
209 
210     quads.append(absMarginQuad);
211     quads.append(absBorderQuad);
212     quads.append(absPaddingQuad);
213     quads.append(absContentQuad);
214 
215     return true;
216 }
217 
buildNodeHighlight(Node * node,const HighlightConfig & highlightConfig,Highlight * highlight)218 static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
219 {
220     RenderObject* renderer = node->renderer();
221     Frame* containingFrame = node->document().frame();
222 
223     if (!renderer || !containingFrame)
224         return;
225 
226     highlight->setDataFromConfig(highlightConfig);
227 
228     // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
229     if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot())
230         highlight->type = HighlightTypeRects;
231     else if (renderer->isBox() || renderer->isRenderInline())
232         highlight->type = HighlightTypeNode;
233     buildNodeQuads(node, highlight->quads);
234 }
235 
buildQuadHighlight(Page * page,const FloatQuad & quad,const HighlightConfig & highlightConfig,Highlight * highlight)236 static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
237 {
238     if (!page)
239         return;
240     highlight->setDataFromConfig(highlightConfig);
241     highlight->type = HighlightTypeRects;
242     highlight->quads.append(quad);
243 }
244 
245 } // anonymous namespace
246 
InspectorOverlay(Page * page,InspectorClient * client)247 InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
248     : m_page(page)
249     , m_client(client)
250     , m_inspectModeEnabled(false)
251     , m_overlayHost(InspectorOverlayHost::create())
252     , m_drawViewSize(false)
253     , m_drawViewSizeWithGrid(false)
254     , m_timer(this, &InspectorOverlay::onTimer)
255     , m_activeProfilerCount(0)
256 {
257 }
258 
~InspectorOverlay()259 InspectorOverlay::~InspectorOverlay()
260 {
261 }
262 
paint(GraphicsContext & context)263 void InspectorOverlay::paint(GraphicsContext& context)
264 {
265     if (isEmpty())
266         return;
267     GraphicsContextStateSaver stateSaver(context);
268     FrameView* view = overlayPage()->mainFrame()->view();
269     ASSERT(!view->needsLayout());
270     view->paint(&context, IntRect(0, 0, view->width(), view->height()));
271 }
272 
invalidate()273 void InspectorOverlay::invalidate()
274 {
275     m_client->highlight();
276 }
277 
handleGestureEvent(const PlatformGestureEvent & event)278 bool InspectorOverlay::handleGestureEvent(const PlatformGestureEvent& event)
279 {
280     if (isEmpty())
281         return false;
282 
283     return overlayPage()->mainFrame()->eventHandler().handleGestureEvent(event);
284 }
285 
handleMouseEvent(const PlatformMouseEvent & event)286 bool InspectorOverlay::handleMouseEvent(const PlatformMouseEvent& event)
287 {
288     if (isEmpty())
289         return false;
290 
291     EventHandler& eventHandler = overlayPage()->mainFrame()->eventHandler();
292     bool result;
293     switch (event.type()) {
294     case PlatformEvent::MouseMoved:
295         result = eventHandler.handleMouseMoveEvent(event);
296         break;
297     case PlatformEvent::MousePressed:
298         result = eventHandler.handleMousePressEvent(event);
299         break;
300     case PlatformEvent::MouseReleased:
301         result = eventHandler.handleMouseReleaseEvent(event);
302         break;
303     default:
304         return false;
305     }
306 
307     overlayPage()->mainFrame()->document()->updateLayout();
308     return result;
309 }
310 
handleTouchEvent(const PlatformTouchEvent & event)311 bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event)
312 {
313     if (isEmpty())
314         return false;
315 
316     return overlayPage()->mainFrame()->eventHandler().handleTouchEvent(event);
317 }
318 
handleKeyboardEvent(const PlatformKeyboardEvent & event)319 bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event)
320 {
321     if (isEmpty())
322         return false;
323 
324     return overlayPage()->mainFrame()->eventHandler().keyEvent(event);
325 }
326 
drawOutline(GraphicsContext * context,const LayoutRect & rect,const Color & color)327 void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
328 {
329     FloatRect outlineRect = rect;
330     drawOutlinedQuad(context, outlineRect, Color(), color);
331 }
332 
getHighlight(Highlight * highlight) const333 void InspectorOverlay::getHighlight(Highlight* highlight) const
334 {
335     if (!m_highlightNode && !m_highlightQuad)
336         return;
337 
338     highlight->type = HighlightTypeRects;
339     if (m_highlightNode)
340         buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight);
341     else
342         buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, highlight);
343 }
344 
resize(const IntSize & size)345 void InspectorOverlay::resize(const IntSize& size)
346 {
347     m_size = size;
348     update();
349 }
350 
setPausedInDebuggerMessage(const String * message)351 void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
352 {
353     m_pausedInDebuggerMessage = message ? *message : String();
354     update();
355 }
356 
setInspectModeEnabled(bool enabled)357 void InspectorOverlay::setInspectModeEnabled(bool enabled)
358 {
359     m_inspectModeEnabled = enabled;
360     update();
361 }
362 
hideHighlight()363 void InspectorOverlay::hideHighlight()
364 {
365     m_highlightNode.clear();
366     m_eventTargetNode.clear();
367     m_highlightQuad.clear();
368     update();
369 }
370 
highlightNode(Node * node,Node * eventTarget,const HighlightConfig & highlightConfig)371 void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig)
372 {
373     m_nodeHighlightConfig = highlightConfig;
374     m_highlightNode = node;
375     m_eventTargetNode = eventTarget;
376     update();
377 }
378 
highlightQuad(PassOwnPtr<FloatQuad> quad,const HighlightConfig & highlightConfig)379 void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig)
380 {
381     m_quadHighlightConfig = highlightConfig;
382     m_highlightQuad = quad;
383     update();
384 }
385 
showAndHideViewSize(bool showGrid)386 void InspectorOverlay::showAndHideViewSize(bool showGrid)
387 {
388     m_drawViewSize = true;
389     m_drawViewSizeWithGrid = showGrid;
390     update();
391     m_timer.startOneShot(1);
392 }
393 
highlightedNode() const394 Node* InspectorOverlay::highlightedNode() const
395 {
396     return m_highlightNode.get();
397 }
398 
isEmpty()399 bool InspectorOverlay::isEmpty()
400 {
401     if (m_activeProfilerCount)
402         return true;
403     bool hasAlwaysVisibleElements = m_highlightNode || m_eventTargetNode || m_highlightQuad || !m_size.isEmpty() || m_drawViewSize;
404     bool hasInvisibleInInspectModeElements = !m_pausedInDebuggerMessage.isNull();
405     return !(hasAlwaysVisibleElements || (hasInvisibleInInspectModeElements && !m_inspectModeEnabled));
406 }
407 
update()408 void InspectorOverlay::update()
409 {
410     if (isEmpty()) {
411         m_client->hideHighlight();
412         return;
413     }
414 
415     FrameView* view = m_page->mainFrame()->view();
416     if (!view)
417         return;
418     IntRect viewRect = view->visibleContentRect();
419     FrameView* overlayView = overlayPage()->mainFrame()->view();
420 
421     // Include scrollbars to avoid masking them by the gutter.
422     IntSize frameViewFullSize = view->visibleContentRect(ScrollableArea::IncludeScrollbars).size();
423     IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
424     size.scale(m_page->pageScaleFactor());
425     overlayView->resize(size);
426 
427     // Clear canvas and paint things.
428     reset(size, m_size.isEmpty() ? IntSize() : frameViewFullSize, viewRect.x(), viewRect.y());
429 
430     drawNodeHighlight();
431     drawQuadHighlight();
432     if (!m_inspectModeEnabled)
433         drawPausedInDebuggerMessage();
434     drawViewSize();
435 
436     // Position DOM elements.
437     overlayPage()->mainFrame()->document()->recalcStyle(Force);
438     if (overlayView->needsLayout())
439         overlayView->layout();
440 
441     // Kick paint.
442     m_client->highlight();
443 }
444 
hide()445 void InspectorOverlay::hide()
446 {
447     m_timer.stop();
448     m_highlightNode.clear();
449     m_eventTargetNode.clear();
450     m_highlightQuad.clear();
451     m_pausedInDebuggerMessage = String();
452     m_size = IntSize();
453     m_drawViewSize = false;
454     m_drawViewSizeWithGrid = false;
455     update();
456 }
457 
buildObjectForPoint(const FloatPoint & point)458 static PassRefPtr<JSONObject> buildObjectForPoint(const FloatPoint& point)
459 {
460     RefPtr<JSONObject> object = JSONObject::create();
461     object->setNumber("x", point.x());
462     object->setNumber("y", point.y());
463     return object.release();
464 }
465 
buildArrayForQuad(const FloatQuad & quad)466 static PassRefPtr<JSONArray> buildArrayForQuad(const FloatQuad& quad)
467 {
468     RefPtr<JSONArray> array = JSONArray::create();
469     array->pushObject(buildObjectForPoint(quad.p1()));
470     array->pushObject(buildObjectForPoint(quad.p2()));
471     array->pushObject(buildObjectForPoint(quad.p3()));
472     array->pushObject(buildObjectForPoint(quad.p4()));
473     return array.release();
474 }
475 
buildObjectForHighlight(const Highlight & highlight)476 static PassRefPtr<JSONObject> buildObjectForHighlight(const Highlight& highlight)
477 {
478     RefPtr<JSONObject> object = JSONObject::create();
479     RefPtr<JSONArray> array = JSONArray::create();
480     for (size_t i = 0; i < highlight.quads.size(); ++i)
481         array->pushArray(buildArrayForQuad(highlight.quads[i]));
482     object->setArray("quads", array.release());
483     object->setBoolean("showRulers", highlight.showRulers);
484     object->setString("contentColor", highlight.contentColor.serialized());
485     object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
486     object->setString("paddingColor", highlight.paddingColor.serialized());
487     object->setString("borderColor", highlight.borderColor.serialized());
488     object->setString("marginColor", highlight.marginColor.serialized());
489     object->setString("eventTargetColor", highlight.eventTargetColor.serialized());
490     return object.release();
491 }
492 
buildObjectForSize(const IntSize & size)493 static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size)
494 {
495     RefPtr<JSONObject> result = JSONObject::create();
496     result->setNumber("width", size.width());
497     result->setNumber("height", size.height());
498     return result.release();
499 }
500 
drawNodeHighlight()501 void InspectorOverlay::drawNodeHighlight()
502 {
503     if (!m_highlightNode)
504         return;
505 
506     Highlight highlight;
507     buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
508     if (m_eventTargetNode) {
509         Highlight eventTargetHighlight;
510         buildNodeHighlight(m_eventTargetNode.get(), m_nodeHighlightConfig, &eventTargetHighlight);
511         highlight.quads.append(eventTargetHighlight.quads[1]); // Add border from eventTargetNode to highlight.
512     }
513     RefPtr<JSONObject> highlightObject = buildObjectForHighlight(highlight);
514 
515     Node* node = m_highlightNode.get();
516     if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document().frame()) {
517         RefPtr<JSONObject> elementInfo = JSONObject::create();
518         Element* element = toElement(node);
519         Element* realElement = element;
520         PseudoElement* pseudoElement = 0;
521         if (element->isPseudoElement()) {
522             pseudoElement = toPseudoElement(element);
523             realElement = element->parentOrShadowHostElement();
524         }
525         bool isXHTML = realElement->document().isXHTMLDocument();
526         elementInfo->setString("tagName", isXHTML ? realElement->nodeName() : realElement->nodeName().lower());
527         elementInfo->setString("idValue", realElement->getIdAttribute());
528         StringBuilder classNames;
529         if (realElement->hasClass() && realElement->isStyledElement()) {
530             HashSet<AtomicString> usedClassNames;
531             const SpaceSplitString& classNamesString = realElement->classNames();
532             size_t classNameCount = classNamesString.size();
533             for (size_t i = 0; i < classNameCount; ++i) {
534                 const AtomicString& className = classNamesString[i];
535                 if (!usedClassNames.add(className).isNewEntry)
536                     continue;
537                 classNames.append('.');
538                 classNames.append(className);
539             }
540         }
541         if (pseudoElement) {
542             if (pseudoElement->pseudoId() == BEFORE)
543                 classNames.append("::before");
544             else if (pseudoElement->pseudoId() == AFTER)
545                 classNames.append("::after");
546         }
547         if (!classNames.isEmpty())
548             elementInfo->setString("className", classNames.toString());
549 
550         RenderObject* renderer = node->renderer();
551         Frame* containingFrame = node->document().frame();
552         FrameView* containingView = containingFrame->view();
553         IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
554         RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
555         elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
556         elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
557         highlightObject->setObject("elementInfo", elementInfo.release());
558     }
559     evaluateInOverlay("drawNodeHighlight", highlightObject);
560 }
561 
drawQuadHighlight()562 void InspectorOverlay::drawQuadHighlight()
563 {
564     if (!m_highlightQuad)
565         return;
566 
567     Highlight highlight;
568     buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
569     evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
570 }
571 
drawPausedInDebuggerMessage()572 void InspectorOverlay::drawPausedInDebuggerMessage()
573 {
574     if (!m_pausedInDebuggerMessage.isNull())
575         evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
576 }
577 
drawViewSize()578 void InspectorOverlay::drawViewSize()
579 {
580     if (m_drawViewSize)
581         evaluateInOverlay("drawViewSize", m_drawViewSizeWithGrid ? "true" : "false");
582 }
583 
overlayPage()584 Page* InspectorOverlay::overlayPage()
585 {
586     if (m_overlayPage)
587         return m_overlayPage.get();
588 
589     static FrameLoaderClient* dummyFrameLoaderClient =  new EmptyFrameLoaderClient;
590     Page::PageClients pageClients;
591     fillWithEmptyClients(pageClients);
592     ASSERT(!m_overlayChromeClient);
593     m_overlayChromeClient = adoptPtr(new InspectorOverlayChromeClient(m_page->chrome().client(), this));
594     pageClients.chromeClient = m_overlayChromeClient.get();
595     m_overlayPage = adoptPtr(new Page(pageClients));
596 
597     Settings& settings = m_page->settings();
598     Settings& overlaySettings = m_overlayPage->settings();
599 
600     overlaySettings.genericFontFamilySettings().setStandard(settings.genericFontFamilySettings().standard());
601     overlaySettings.genericFontFamilySettings().setSerif(settings.genericFontFamilySettings().serif());
602     overlaySettings.genericFontFamilySettings().setSansSerif(settings.genericFontFamilySettings().sansSerif());
603     overlaySettings.genericFontFamilySettings().setCursive(settings.genericFontFamilySettings().cursive());
604     overlaySettings.genericFontFamilySettings().setFantasy(settings.genericFontFamilySettings().fantasy());
605     overlaySettings.genericFontFamilySettings().setPictograph(settings.genericFontFamilySettings().pictograph());
606     overlaySettings.setMinimumFontSize(settings.minimumFontSize());
607     overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
608     overlaySettings.setMediaEnabled(false);
609     overlaySettings.setScriptEnabled(true);
610     overlaySettings.setPluginsEnabled(false);
611     overlaySettings.setLoadsImagesAutomatically(true);
612 
613     RefPtr<Frame> frame = Frame::create(FrameInit::create(0, m_overlayPage.get(), dummyFrameLoaderClient));
614     frame->setView(FrameView::create(frame.get()));
615     frame->init();
616     FrameLoader& loader = frame->loader();
617     frame->view()->setCanHaveScrollbars(false);
618     frame->view()->setTransparent(true);
619     ASSERT(loader.activeDocumentLoader());
620     DocumentWriter* writer = loader.activeDocumentLoader()->beginWriting("text/html", "UTF-8");
621     writer->addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
622     loader.activeDocumentLoader()->endWriting(writer);
623     v8::Isolate* isolate = toIsolate(frame.get());
624     v8::HandleScope handleScope(isolate);
625     v8::Handle<v8::Context> frameContext = frame->script().currentWorldContext();
626     v8::Context::Scope contextScope(frameContext);
627     v8::Handle<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), v8::Handle<v8::Object>(), isolate);
628     v8::Handle<v8::Object> global = frameContext->Global();
629     global->Set(v8::String::NewFromUtf8(isolate, "InspectorOverlayHost"), overlayHostObj);
630 
631 #if OS(WIN)
632     evaluateInOverlay("setPlatform", "windows");
633 #elif OS(MACOSX)
634     evaluateInOverlay("setPlatform", "mac");
635 #elif OS(POSIX)
636     evaluateInOverlay("setPlatform", "linux");
637 #endif
638 
639     return m_overlayPage.get();
640 }
641 
reset(const IntSize & viewportSize,const IntSize & frameViewFullSize,int scrollX,int scrollY)642 void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize, int scrollX, int scrollY)
643 {
644     RefPtr<JSONObject> resetData = JSONObject::create();
645     resetData->setNumber("pageScaleFactor", m_page->pageScaleFactor());
646     resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
647     resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
648     resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
649     resetData->setNumber("pageZoomFactor", m_page->mainFrame()->pageZoomFactor());
650     resetData->setNumber("scrollX", scrollX);
651     resetData->setNumber("scrollY", scrollY);
652     evaluateInOverlay("reset", resetData.release());
653 }
654 
evaluateInOverlay(const String & method,const String & argument)655 void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
656 {
657     RefPtr<JSONArray> command = JSONArray::create();
658     command->pushString(method);
659     command->pushString(argument);
660     overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
661 }
662 
evaluateInOverlay(const String & method,PassRefPtr<JSONValue> argument)663 void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<JSONValue> argument)
664 {
665     RefPtr<JSONArray> command = JSONArray::create();
666     command->pushString(method);
667     command->pushValue(argument);
668     overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
669 }
670 
onTimer(Timer<InspectorOverlay> *)671 void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
672 {
673     m_drawViewSize = false;
674     update();
675 }
676 
getBoxModel(Node * node,Vector<FloatQuad> * quads)677 bool InspectorOverlay::getBoxModel(Node* node, Vector<FloatQuad>* quads)
678 {
679     return buildNodeQuads(node, *quads);
680 }
681 
freePage()682 void InspectorOverlay::freePage()
683 {
684     m_overlayPage.clear();
685     m_overlayChromeClient.clear();
686     m_timer.stop();
687 }
688 
startedRecordingProfile()689 void InspectorOverlay::startedRecordingProfile()
690 {
691     if (!m_activeProfilerCount++)
692         freePage();
693 }
694 
695 } // namespace WebCore
696