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 58namespace WebCore { 59 60namespace { 61 62class InspectorOverlayChromeClient: public EmptyChromeClient { 63public: 64 InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay* overlay) 65 : m_client(client) 66 , m_overlay(overlay) 67 { } 68 69 virtual void setCursor(const Cursor& cursor) 70 { 71 m_client.setCursor(cursor); 72 } 73 74 virtual void setToolTip(const String& tooltip, TextDirection direction) 75 { 76 m_client.setToolTip(tooltip, direction); 77 } 78 79 virtual void invalidateRootView(const IntRect& rect) 80 { 81 m_overlay->invalidate(); 82 } 83 84 virtual void invalidateContentsAndRootView(const IntRect& rect) 85 { 86 m_overlay->invalidate(); 87 } 88 89 virtual void invalidateContentsForSlowScroll(const IntRect& rect) 90 { 91 m_overlay->invalidate(); 92 } 93 94private: 95 ChromeClient& m_client; 96 InspectorOverlay* m_overlay; 97}; 98 99Path 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 110void 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 134static 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 143static 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 218static 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 236static 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 247InspectorOverlay::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 259InspectorOverlay::~InspectorOverlay() 260{ 261} 262 263void 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 273void InspectorOverlay::invalidate() 274{ 275 m_client->highlight(); 276} 277 278bool InspectorOverlay::handleGestureEvent(const PlatformGestureEvent& event) 279{ 280 if (isEmpty()) 281 return false; 282 283 return overlayPage()->mainFrame()->eventHandler().handleGestureEvent(event); 284} 285 286bool 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 311bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event) 312{ 313 if (isEmpty()) 314 return false; 315 316 return overlayPage()->mainFrame()->eventHandler().handleTouchEvent(event); 317} 318 319bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event) 320{ 321 if (isEmpty()) 322 return false; 323 324 return overlayPage()->mainFrame()->eventHandler().keyEvent(event); 325} 326 327void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color) 328{ 329 FloatRect outlineRect = rect; 330 drawOutlinedQuad(context, outlineRect, Color(), color); 331} 332 333void 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 345void InspectorOverlay::resize(const IntSize& size) 346{ 347 m_size = size; 348 update(); 349} 350 351void InspectorOverlay::setPausedInDebuggerMessage(const String* message) 352{ 353 m_pausedInDebuggerMessage = message ? *message : String(); 354 update(); 355} 356 357void InspectorOverlay::setInspectModeEnabled(bool enabled) 358{ 359 m_inspectModeEnabled = enabled; 360 update(); 361} 362 363void InspectorOverlay::hideHighlight() 364{ 365 m_highlightNode.clear(); 366 m_eventTargetNode.clear(); 367 m_highlightQuad.clear(); 368 update(); 369} 370 371void 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 379void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig) 380{ 381 m_quadHighlightConfig = highlightConfig; 382 m_highlightQuad = quad; 383 update(); 384} 385 386void InspectorOverlay::showAndHideViewSize(bool showGrid) 387{ 388 m_drawViewSize = true; 389 m_drawViewSizeWithGrid = showGrid; 390 update(); 391 m_timer.startOneShot(1); 392} 393 394Node* InspectorOverlay::highlightedNode() const 395{ 396 return m_highlightNode.get(); 397} 398 399bool 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 408void 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 445void 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 458static 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 466static 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 476static 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 493static 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 501void 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 562void 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 572void InspectorOverlay::drawPausedInDebuggerMessage() 573{ 574 if (!m_pausedInDebuggerMessage.isNull()) 575 evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage); 576} 577 578void InspectorOverlay::drawViewSize() 579{ 580 if (m_drawViewSize) 581 evaluateInOverlay("drawViewSize", m_drawViewSizeWithGrid ? "true" : "false"); 582} 583 584Page* 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 642void 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 655void 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 663void 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 671void InspectorOverlay::onTimer(Timer<InspectorOverlay>*) 672{ 673 m_drawViewSize = false; 674 update(); 675} 676 677bool InspectorOverlay::getBoxModel(Node* node, Vector<FloatQuad>* quads) 678{ 679 return buildNodeQuads(node, *quads); 680} 681 682void InspectorOverlay::freePage() 683{ 684 m_overlayPage.clear(); 685 m_overlayChromeClient.clear(); 686 m_timer.stop(); 687} 688 689void InspectorOverlay::startedRecordingProfile() 690{ 691 if (!m_activeProfilerCount++) 692 freePage(); 693} 694 695} // namespace WebCore 696