InspectorOverlay.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. #include "config.h"
  29. #if ENABLE(INSPECTOR)
  30. #include "InspectorOverlay.h"
  31. #include "DocumentLoader.h"
  32. #include "Element.h"
  33. #include "EmptyClients.h"
  34. #include "Frame.h"
  35. #include "FrameView.h"
  36. #include "GraphicsContext.h"
  37. #include "InspectorClient.h"
  38. #include "InspectorOverlayPage.h"
  39. #include "InspectorValues.h"
  40. #include "Node.h"
  41. #include "Page.h"
  42. #include "RenderBoxModelObject.h"
  43. #include "RenderInline.h"
  44. #include "RenderObject.h"
  45. #include "ScriptController.h"
  46. #include "ScriptSourceCode.h"
  47. #include "ScriptValue.h"
  48. #include "Settings.h"
  49. #include "StyledElement.h"
  50. #include <wtf/text/StringBuilder.h>
  51. namespace WebCore {
  52. namespace {
  53. Path quadToPath(const FloatQuad& quad)
  54. {
  55. Path quadPath;
  56. quadPath.moveTo(quad.p1());
  57. quadPath.addLineTo(quad.p2());
  58. quadPath.addLineTo(quad.p3());
  59. quadPath.addLineTo(quad.p4());
  60. quadPath.closeSubpath();
  61. return quadPath;
  62. }
  63. void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
  64. {
  65. static const int outlineThickness = 2;
  66. Path quadPath = quadToPath(quad);
  67. // Clip out the quad, then draw with a 2px stroke to get a pixel
  68. // of outline (because inflating a quad is hard)
  69. {
  70. context->save();
  71. context->clipOut(quadPath);
  72. context->setStrokeThickness(outlineThickness);
  73. context->setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
  74. context->strokePath(quadPath);
  75. context->restore();
  76. }
  77. // Now do the fill
  78. context->setFillColor(fillColor, ColorSpaceDeviceRGB);
  79. context->fillPath(quadPath);
  80. }
  81. static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
  82. {
  83. quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
  84. quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
  85. quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
  86. quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));
  87. quad += mainView->scrollOffset();
  88. }
  89. static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
  90. {
  91. RenderObject* renderer = node->renderer();
  92. Frame* containingFrame = node->document()->frame();
  93. if (!renderer || !containingFrame)
  94. return;
  95. highlight->setDataFromConfig(highlightConfig);
  96. FrameView* containingView = containingFrame->view();
  97. FrameView* mainView = containingFrame->page()->mainFrame()->view();
  98. IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
  99. boundingBox.move(mainView->scrollOffset());
  100. IntRect titleAnchorBox = boundingBox;
  101. // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
  102. #if ENABLE(SVG)
  103. bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
  104. #else
  105. bool isSVGRenderer = false;
  106. #endif
  107. if (isSVGRenderer) {
  108. highlight->type = HighlightTypeRects;
  109. renderer->absoluteQuads(highlight->quads);
  110. for (size_t i = 0; i < highlight->quads.size(); ++i)
  111. contentsQuadToPage(mainView, containingView, highlight->quads[i]);
  112. } else if (renderer->isBox() || renderer->isRenderInline()) {
  113. LayoutRect contentBox;
  114. LayoutRect paddingBox;
  115. LayoutRect borderBox;
  116. LayoutRect marginBox;
  117. if (renderer->isBox()) {
  118. RenderBox* renderBox = toRenderBox(renderer);
  119. // RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
  120. contentBox = renderBox->contentBoxRect();
  121. contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
  122. contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
  123. paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
  124. contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
  125. borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
  126. paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
  127. marginBox = LayoutRect(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
  128. borderBox.width() + renderBox->marginWidth(), borderBox.height() + renderBox->marginHeight());
  129. } else {
  130. RenderInline* renderInline = toRenderInline(renderer);
  131. // RenderInline's bounding box includes paddings and borders, excludes margins.
  132. borderBox = renderInline->linesBoundingBox();
  133. paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
  134. borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
  135. contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
  136. paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
  137. // Ignore marginTop and marginBottom for inlines.
  138. marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
  139. borderBox.width() + renderInline->marginWidth(), borderBox.height());
  140. }
  141. FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
  142. FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
  143. FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
  144. FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
  145. contentsQuadToPage(mainView, containingView, absContentQuad);
  146. contentsQuadToPage(mainView, containingView, absPaddingQuad);
  147. contentsQuadToPage(mainView, containingView, absBorderQuad);
  148. contentsQuadToPage(mainView, containingView, absMarginQuad);
  149. titleAnchorBox = absMarginQuad.enclosingBoundingBox();
  150. highlight->type = HighlightTypeNode;
  151. highlight->quads.append(absMarginQuad);
  152. highlight->quads.append(absBorderQuad);
  153. highlight->quads.append(absPaddingQuad);
  154. highlight->quads.append(absContentQuad);
  155. }
  156. }
  157. static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
  158. {
  159. if (!page)
  160. return;
  161. highlight->setDataFromConfig(highlightConfig);
  162. highlight->type = HighlightTypeRects;
  163. highlight->quads.append(quad);
  164. }
  165. } // anonymous namespace
  166. InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
  167. : m_page(page)
  168. , m_client(client)
  169. {
  170. }
  171. InspectorOverlay::~InspectorOverlay()
  172. {
  173. }
  174. void InspectorOverlay::paint(GraphicsContext& context)
  175. {
  176. if (m_pausedInDebuggerMessage.isNull() && !m_highlightNode && !m_highlightQuad && m_size.isEmpty())
  177. return;
  178. GraphicsContextStateSaver stateSaver(context);
  179. FrameView* view = overlayPage()->mainFrame()->view();
  180. ASSERT(!view->needsLayout());
  181. view->paint(&context, IntRect(0, 0, view->width(), view->height()));
  182. }
  183. void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
  184. {
  185. FloatRect outlineRect = rect;
  186. drawOutlinedQuad(context, outlineRect, Color(), color);
  187. }
  188. void InspectorOverlay::getHighlight(Highlight* highlight) const
  189. {
  190. if (!m_highlightNode && !m_highlightQuad)
  191. return;
  192. highlight->type = HighlightTypeRects;
  193. if (m_highlightNode)
  194. buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight);
  195. else
  196. buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, highlight);
  197. }
  198. void InspectorOverlay::resize(const IntSize& size)
  199. {
  200. m_size = size;
  201. update();
  202. }
  203. void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
  204. {
  205. m_pausedInDebuggerMessage = message ? *message : String();
  206. update();
  207. }
  208. void InspectorOverlay::hideHighlight()
  209. {
  210. m_highlightNode.clear();
  211. m_highlightQuad.clear();
  212. update();
  213. }
  214. void InspectorOverlay::highlightNode(Node* node, const HighlightConfig& highlightConfig)
  215. {
  216. m_nodeHighlightConfig = highlightConfig;
  217. m_highlightNode = node;
  218. update();
  219. }
  220. void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig)
  221. {
  222. if (m_quadHighlightConfig.usePageCoordinates)
  223. *quad -= m_page->mainFrame()->view()->scrollOffset();
  224. m_quadHighlightConfig = highlightConfig;
  225. m_highlightQuad = quad;
  226. update();
  227. }
  228. Node* InspectorOverlay::highlightedNode() const
  229. {
  230. return m_highlightNode.get();
  231. }
  232. void InspectorOverlay::update()
  233. {
  234. if (!m_highlightNode && !m_highlightQuad && m_pausedInDebuggerMessage.isNull() && m_size.isEmpty()) {
  235. m_client->hideHighlight();
  236. return;
  237. }
  238. FrameView* view = m_page->mainFrame()->view();
  239. if (!view)
  240. return;
  241. FrameView* overlayView = overlayPage()->mainFrame()->view();
  242. IntSize viewportSize = view->visibleContentRect().size();
  243. IntSize frameViewFullSize = view->visibleContentRect(ScrollableArea::IncludeScrollbars).size();
  244. IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
  245. overlayPage()->setPageScaleFactor(m_page->pageScaleFactor(), IntPoint());
  246. size.scale(m_page->pageScaleFactor());
  247. overlayView->resize(size);
  248. // Clear canvas and paint things.
  249. reset(viewportSize, m_size.isEmpty() ? IntSize() : frameViewFullSize);
  250. // Include scrollbars to avoid masking them by the gutter.
  251. drawGutter();
  252. drawNodeHighlight();
  253. drawQuadHighlight();
  254. drawPausedInDebuggerMessage();
  255. // Position DOM elements.
  256. overlayPage()->mainFrame()->document()->recalcStyle(Node::Force);
  257. if (overlayView->needsLayout())
  258. overlayView->layout();
  259. // Kick paint.
  260. m_client->highlight();
  261. }
  262. static PassRefPtr<InspectorObject> buildObjectForPoint(const FloatPoint& point)
  263. {
  264. RefPtr<InspectorObject> object = InspectorObject::create();
  265. object->setNumber("x", point.x());
  266. object->setNumber("y", point.y());
  267. return object.release();
  268. }
  269. static PassRefPtr<InspectorArray> buildArrayForQuad(const FloatQuad& quad)
  270. {
  271. RefPtr<InspectorArray> array = InspectorArray::create();
  272. array->pushObject(buildObjectForPoint(quad.p1()));
  273. array->pushObject(buildObjectForPoint(quad.p2()));
  274. array->pushObject(buildObjectForPoint(quad.p3()));
  275. array->pushObject(buildObjectForPoint(quad.p4()));
  276. return array.release();
  277. }
  278. static PassRefPtr<InspectorObject> buildObjectForHighlight(FrameView* mainView, const Highlight& highlight)
  279. {
  280. RefPtr<InspectorObject> object = InspectorObject::create();
  281. RefPtr<InspectorArray> array = InspectorArray::create();
  282. for (size_t i = 0; i < highlight.quads.size(); ++i)
  283. array->pushArray(buildArrayForQuad(highlight.quads[i]));
  284. object->setArray("quads", array.release());
  285. object->setBoolean("showRulers", highlight.showRulers);
  286. object->setString("contentColor", highlight.contentColor.serialized());
  287. object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
  288. object->setString("paddingColor", highlight.paddingColor.serialized());
  289. object->setString("borderColor", highlight.borderColor.serialized());
  290. object->setString("marginColor", highlight.marginColor.serialized());
  291. FloatRect visibleRect = mainView->visibleContentRect();
  292. if (!mainView->delegatesScrolling()) {
  293. object->setNumber("scrollX", visibleRect.x());
  294. object->setNumber("scrollY", visibleRect.y());
  295. } else {
  296. object->setNumber("scrollX", 0);
  297. object->setNumber("scrollY", 0);
  298. }
  299. return object.release();
  300. }
  301. static PassRefPtr<InspectorObject> buildObjectForSize(const IntSize& size)
  302. {
  303. RefPtr<InspectorObject> result = InspectorObject::create();
  304. result->setNumber("width", size.width());
  305. result->setNumber("height", size.height());
  306. return result.release();
  307. }
  308. void InspectorOverlay::drawGutter()
  309. {
  310. evaluateInOverlay("drawGutter", "");
  311. }
  312. void InspectorOverlay::drawNodeHighlight()
  313. {
  314. if (!m_highlightNode)
  315. return;
  316. Highlight highlight;
  317. buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
  318. RefPtr<InspectorObject> highlightObject = buildObjectForHighlight(m_page->mainFrame()->view(), highlight);
  319. Node* node = m_highlightNode.get();
  320. if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document()->frame()) {
  321. RefPtr<InspectorObject> elementInfo = InspectorObject::create();
  322. Element* element = toElement(node);
  323. bool isXHTML = element->document()->isXHTMLDocument();
  324. elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower());
  325. elementInfo->setString("idValue", element->getIdAttribute());
  326. HashSet<AtomicString> usedClassNames;
  327. if (element->hasClass() && element->isStyledElement()) {
  328. StringBuilder classNames;
  329. const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
  330. size_t classNameCount = classNamesString.size();
  331. for (size_t i = 0; i < classNameCount; ++i) {
  332. const AtomicString& className = classNamesString[i];
  333. if (usedClassNames.contains(className))
  334. continue;
  335. usedClassNames.add(className);
  336. classNames.append('.');
  337. classNames.append(className);
  338. }
  339. elementInfo->setString("className", classNames.toString());
  340. }
  341. RenderObject* renderer = node->renderer();
  342. Frame* containingFrame = node->document()->frame();
  343. FrameView* containingView = containingFrame->view();
  344. IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
  345. RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
  346. elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
  347. elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
  348. highlightObject->setObject("elementInfo", elementInfo.release());
  349. }
  350. evaluateInOverlay("drawNodeHighlight", highlightObject);
  351. }
  352. void InspectorOverlay::drawQuadHighlight()
  353. {
  354. if (!m_highlightQuad)
  355. return;
  356. Highlight highlight;
  357. buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
  358. evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(m_page->mainFrame()->view(), highlight));
  359. }
  360. void InspectorOverlay::drawPausedInDebuggerMessage()
  361. {
  362. if (!m_pausedInDebuggerMessage.isNull())
  363. evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
  364. }
  365. Page* InspectorOverlay::overlayPage()
  366. {
  367. if (m_overlayPage)
  368. return m_overlayPage.get();
  369. static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient;
  370. Page::PageClients pageClients;
  371. fillWithEmptyClients(pageClients);
  372. m_overlayPage = adoptPtr(new Page(pageClients));
  373. Settings* settings = m_page->settings();
  374. Settings* overlaySettings = m_overlayPage->settings();
  375. overlaySettings->setStandardFontFamily(settings->standardFontFamily());
  376. overlaySettings->setSerifFontFamily(settings->serifFontFamily());
  377. overlaySettings->setSansSerifFontFamily(settings->sansSerifFontFamily());
  378. overlaySettings->setCursiveFontFamily(settings->cursiveFontFamily());
  379. overlaySettings->setFantasyFontFamily(settings->fantasyFontFamily());
  380. overlaySettings->setPictographFontFamily(settings->pictographFontFamily());
  381. overlaySettings->setMinimumFontSize(settings->minimumFontSize());
  382. overlaySettings->setMinimumLogicalFontSize(settings->minimumLogicalFontSize());
  383. overlaySettings->setMediaEnabled(false);
  384. overlaySettings->setScriptEnabled(true);
  385. overlaySettings->setPluginsEnabled(false);
  386. RefPtr<Frame> frame = Frame::create(m_overlayPage.get(), 0, dummyFrameLoaderClient);
  387. frame->setView(FrameView::create(frame.get()));
  388. frame->init();
  389. FrameLoader* loader = frame->loader();
  390. frame->view()->setCanHaveScrollbars(false);
  391. frame->view()->setTransparent(true);
  392. ASSERT(loader->activeDocumentLoader());
  393. loader->activeDocumentLoader()->writer()->setMIMEType("text/html");
  394. loader->activeDocumentLoader()->writer()->begin();
  395. loader->activeDocumentLoader()->writer()->addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
  396. loader->activeDocumentLoader()->writer()->end();
  397. #if OS(WINDOWS)
  398. evaluateInOverlay("setPlatform", "windows");
  399. #elif OS(MAC_OS_X)
  400. evaluateInOverlay("setPlatform", "mac");
  401. #elif OS(UNIX)
  402. evaluateInOverlay("setPlatform", "linux");
  403. #endif
  404. return m_overlayPage.get();
  405. }
  406. void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize)
  407. {
  408. RefPtr<InspectorObject> resetData = InspectorObject::create();
  409. resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
  410. resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
  411. resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
  412. evaluateInOverlay("reset", resetData.release());
  413. }
  414. void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
  415. {
  416. RefPtr<InspectorArray> command = InspectorArray::create();
  417. command->pushString(method);
  418. command->pushString(argument);
  419. overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
  420. }
  421. void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument)
  422. {
  423. RefPtr<InspectorArray> command = InspectorArray::create();
  424. command->pushString(method);
  425. command->pushValue(argument);
  426. overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
  427. }
  428. void InspectorOverlay::freePage()
  429. {
  430. m_overlayPage.clear();
  431. }
  432. } // namespace WebCore
  433. #endif // ENABLE(INSPECTOR)