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