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