blob: c2b10d66da0045442381e6a5836415ea0bbcb2ee [file] [log] [blame]
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "core/inspector/InspectorOverlay.h"
#include "InspectorOverlayPage.h"
#include "V8InspectorOverlayHost.h"
#include "bindings/v8/ScriptController.h"
#include "bindings/v8/ScriptSourceCode.h"
#include "core/dom/Element.h"
#include "core/dom/Node.h"
#include "core/dom/PseudoElement.h"
#include "core/inspector/InspectorClient.h"
#include "core/inspector/InspectorOverlayHost.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/EmptyClients.h"
#include "core/page/Chrome.h"
#include "core/page/EventHandler.h"
#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/rendering/RenderBoxModelObject.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "platform/JSONValues.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "wtf/text/StringBuilder.h"
namespace WebCore {
namespace {
class InspectorOverlayChromeClient: public EmptyChromeClient {
public:
InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay* overlay)
: m_client(client)
, m_overlay(overlay)
{ }
virtual void setCursor(const Cursor& cursor)
{
m_client.setCursor(cursor);
}
virtual void setToolTip(const String& tooltip, TextDirection direction)
{
m_client.setToolTip(tooltip, direction);
}
virtual void invalidateRootView(const IntRect& rect)
{
m_overlay->invalidate();
}
virtual void invalidateContentsAndRootView(const IntRect& rect)
{
m_overlay->invalidate();
}
virtual void invalidateContentsForSlowScroll(const IntRect& rect)
{
m_overlay->invalidate();
}
private:
ChromeClient& m_client;
InspectorOverlay* m_overlay;
};
Path quadToPath(const FloatQuad& quad)
{
Path quadPath;
quadPath.moveTo(quad.p1());
quadPath.addLineTo(quad.p2());
quadPath.addLineTo(quad.p3());
quadPath.addLineTo(quad.p4());
quadPath.closeSubpath();
return quadPath;
}
void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
{
static const int outlineThickness = 2;
Path quadPath = quadToPath(quad);
// Clip out the quad, then draw with a 2px stroke to get a pixel
// of outline (because inflating a quad is hard)
{
context->save();
context->clipOut(quadPath);
context->setStrokeThickness(outlineThickness);
context->setStrokeColor(outlineColor);
context->strokePath(quadPath);
context->restore();
}
// Now do the fill
context->setFillColor(fillColor);
context->fillPath(quadPath);
}
static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
{
quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));
quad += mainView->scrollOffset();
}
static bool buildNodeQuads(Node* node, Vector<FloatQuad>& quads)
{
RenderObject* renderer = node->renderer();
Frame* containingFrame = node->document().frame();
if (!renderer || !containingFrame)
return false;
FrameView* containingView = containingFrame->view();
FrameView* mainView = containingFrame->page()->mainFrame()->view();
IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
boundingBox.move(mainView->scrollOffset());
// RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot()) {
renderer->absoluteQuads(quads);
for (size_t i = 0; i < quads.size(); ++i)
contentsQuadToPage(mainView, containingView, quads[i]);
return false;
}
if (!renderer->isBox() && !renderer->isRenderInline())
return false;
LayoutRect contentBox;
LayoutRect paddingBox;
LayoutRect borderBox;
LayoutRect marginBox;
if (renderer->isBox()) {
RenderBox* renderBox = toRenderBox(renderer);
// RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
contentBox = renderBox->contentBoxRect();
contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
marginBox = LayoutRect(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
borderBox.width() + renderBox->marginWidth(), borderBox.height() + renderBox->marginHeight());
} else {
RenderInline* renderInline = toRenderInline(renderer);
// RenderInline's bounding box includes paddings and borders, excludes margins.
borderBox = renderInline->linesBoundingBox();
paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
// Ignore marginTop and marginBottom for inlines.
marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
borderBox.width() + renderInline->marginWidth(), borderBox.height());
}
FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
contentsQuadToPage(mainView, containingView, absContentQuad);
contentsQuadToPage(mainView, containingView, absPaddingQuad);
contentsQuadToPage(mainView, containingView, absBorderQuad);
contentsQuadToPage(mainView, containingView, absMarginQuad);
quads.append(absMarginQuad);
quads.append(absBorderQuad);
quads.append(absPaddingQuad);
quads.append(absContentQuad);
return true;
}
static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
{
RenderObject* renderer = node->renderer();
Frame* containingFrame = node->document().frame();
if (!renderer || !containingFrame)
return;
highlight->setDataFromConfig(highlightConfig);
// RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
if (renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot())
highlight->type = HighlightTypeRects;
else if (renderer->isBox() || renderer->isRenderInline())
highlight->type = HighlightTypeNode;
buildNodeQuads(node, highlight->quads);
}
static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
{
if (!page)
return;
highlight->setDataFromConfig(highlightConfig);
highlight->type = HighlightTypeRects;
highlight->quads.append(quad);
}
} // anonymous namespace
InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
: m_page(page)
, m_client(client)
, m_inspectModeEnabled(false)
, m_overlayHost(InspectorOverlayHost::create())
, m_drawViewSize(false)
, m_drawViewSizeWithGrid(false)
, m_timer(this, &InspectorOverlay::onTimer)
, m_activeProfilerCount(0)
{
}
InspectorOverlay::~InspectorOverlay()
{
}
void InspectorOverlay::paint(GraphicsContext& context)
{
if (isEmpty())
return;
GraphicsContextStateSaver stateSaver(context);
FrameView* view = overlayPage()->mainFrame()->view();
ASSERT(!view->needsLayout());
view->paint(&context, IntRect(0, 0, view->width(), view->height()));
}
void InspectorOverlay::invalidate()
{
m_client->highlight();
}
bool InspectorOverlay::handleGestureEvent(const PlatformGestureEvent& event)
{
if (isEmpty())
return false;
return overlayPage()->mainFrame()->eventHandler().handleGestureEvent(event);
}
bool InspectorOverlay::handleMouseEvent(const PlatformMouseEvent& event)
{
if (isEmpty())
return false;
EventHandler& eventHandler = overlayPage()->mainFrame()->eventHandler();
bool result;
switch (event.type()) {
case PlatformEvent::MouseMoved:
result = eventHandler.handleMouseMoveEvent(event);
break;
case PlatformEvent::MousePressed:
result = eventHandler.handleMousePressEvent(event);
break;
case PlatformEvent::MouseReleased:
result = eventHandler.handleMouseReleaseEvent(event);
break;
default:
return false;
}
overlayPage()->mainFrame()->document()->updateLayout();
return result;
}
bool InspectorOverlay::handleTouchEvent(const PlatformTouchEvent& event)
{
if (isEmpty())
return false;
return overlayPage()->mainFrame()->eventHandler().handleTouchEvent(event);
}
bool InspectorOverlay::handleKeyboardEvent(const PlatformKeyboardEvent& event)
{
if (isEmpty())
return false;
return overlayPage()->mainFrame()->eventHandler().keyEvent(event);
}
void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
{
FloatRect outlineRect = rect;
drawOutlinedQuad(context, outlineRect, Color(), color);
}
void InspectorOverlay::getHighlight(Highlight* highlight) const
{
if (!m_highlightNode && !m_highlightQuad)
return;
highlight->type = HighlightTypeRects;
if (m_highlightNode)
buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight);
else
buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, highlight);
}
void InspectorOverlay::resize(const IntSize& size)
{
m_size = size;
update();
}
void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
{
m_pausedInDebuggerMessage = message ? *message : String();
update();
}
void InspectorOverlay::setInspectModeEnabled(bool enabled)
{
m_inspectModeEnabled = enabled;
update();
}
void InspectorOverlay::hideHighlight()
{
m_highlightNode.clear();
m_eventTargetNode.clear();
m_highlightQuad.clear();
update();
}
void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig)
{
m_nodeHighlightConfig = highlightConfig;
m_highlightNode = node;
m_eventTargetNode = eventTarget;
update();
}
void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig)
{
m_quadHighlightConfig = highlightConfig;
m_highlightQuad = quad;
update();
}
void InspectorOverlay::showAndHideViewSize(bool showGrid)
{
m_drawViewSize = true;
m_drawViewSizeWithGrid = showGrid;
update();
m_timer.startOneShot(1);
}
Node* InspectorOverlay::highlightedNode() const
{
return m_highlightNode.get();
}
bool InspectorOverlay::isEmpty()
{
if (m_activeProfilerCount)
return true;
bool hasAlwaysVisibleElements = m_highlightNode || m_eventTargetNode || m_highlightQuad || !m_size.isEmpty() || m_drawViewSize;
bool hasInvisibleInInspectModeElements = !m_pausedInDebuggerMessage.isNull();
return !(hasAlwaysVisibleElements || (hasInvisibleInInspectModeElements && !m_inspectModeEnabled));
}
void InspectorOverlay::update()
{
if (isEmpty()) {
m_client->hideHighlight();
return;
}
FrameView* view = m_page->mainFrame()->view();
if (!view)
return;
IntRect viewRect = view->visibleContentRect();
FrameView* overlayView = overlayPage()->mainFrame()->view();
// Include scrollbars to avoid masking them by the gutter.
IntSize frameViewFullSize = view->visibleContentRect(ScrollableArea::IncludeScrollbars).size();
IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
size.scale(m_page->pageScaleFactor());
overlayView->resize(size);
// Clear canvas and paint things.
reset(size, m_size.isEmpty() ? IntSize() : frameViewFullSize, viewRect.x(), viewRect.y());
drawNodeHighlight();
drawQuadHighlight();
if (!m_inspectModeEnabled)
drawPausedInDebuggerMessage();
drawViewSize();
// Position DOM elements.
overlayPage()->mainFrame()->document()->recalcStyle(Force);
if (overlayView->needsLayout())
overlayView->layout();
// Kick paint.
m_client->highlight();
}
void InspectorOverlay::hide()
{
m_timer.stop();
m_highlightNode.clear();
m_eventTargetNode.clear();
m_highlightQuad.clear();
m_pausedInDebuggerMessage = String();
m_size = IntSize();
m_drawViewSize = false;
m_drawViewSizeWithGrid = false;
update();
}
static PassRefPtr<JSONObject> buildObjectForPoint(const FloatPoint& point)
{
RefPtr<JSONObject> object = JSONObject::create();
object->setNumber("x", point.x());
object->setNumber("y", point.y());
return object.release();
}
static PassRefPtr<JSONArray> buildArrayForQuad(const FloatQuad& quad)
{
RefPtr<JSONArray> array = JSONArray::create();
array->pushObject(buildObjectForPoint(quad.p1()));
array->pushObject(buildObjectForPoint(quad.p2()));
array->pushObject(buildObjectForPoint(quad.p3()));
array->pushObject(buildObjectForPoint(quad.p4()));
return array.release();
}
static PassRefPtr<JSONObject> buildObjectForHighlight(const Highlight& highlight)
{
RefPtr<JSONObject> object = JSONObject::create();
RefPtr<JSONArray> array = JSONArray::create();
for (size_t i = 0; i < highlight.quads.size(); ++i)
array->pushArray(buildArrayForQuad(highlight.quads[i]));
object->setArray("quads", array.release());
object->setBoolean("showRulers", highlight.showRulers);
object->setString("contentColor", highlight.contentColor.serialized());
object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
object->setString("paddingColor", highlight.paddingColor.serialized());
object->setString("borderColor", highlight.borderColor.serialized());
object->setString("marginColor", highlight.marginColor.serialized());
object->setString("eventTargetColor", highlight.eventTargetColor.serialized());
return object.release();
}
static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size)
{
RefPtr<JSONObject> result = JSONObject::create();
result->setNumber("width", size.width());
result->setNumber("height", size.height());
return result.release();
}
void InspectorOverlay::drawNodeHighlight()
{
if (!m_highlightNode)
return;
Highlight highlight;
buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
if (m_eventTargetNode) {
Highlight eventTargetHighlight;
buildNodeHighlight(m_eventTargetNode.get(), m_nodeHighlightConfig, &eventTargetHighlight);
highlight.quads.append(eventTargetHighlight.quads[1]); // Add border from eventTargetNode to highlight.
}
RefPtr<JSONObject> highlightObject = buildObjectForHighlight(highlight);
Node* node = m_highlightNode.get();
if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document().frame()) {
RefPtr<JSONObject> elementInfo = JSONObject::create();
Element* element = toElement(node);
Element* realElement = element;
PseudoElement* pseudoElement = 0;
if (element->isPseudoElement()) {
pseudoElement = toPseudoElement(element);
realElement = element->parentOrShadowHostElement();
}
bool isXHTML = realElement->document().isXHTMLDocument();
elementInfo->setString("tagName", isXHTML ? realElement->nodeName() : realElement->nodeName().lower());
elementInfo->setString("idValue", realElement->getIdAttribute());
StringBuilder classNames;
if (realElement->hasClass() && realElement->isStyledElement()) {
HashSet<AtomicString> usedClassNames;
const SpaceSplitString& classNamesString = realElement->classNames();
size_t classNameCount = classNamesString.size();
for (size_t i = 0; i < classNameCount; ++i) {
const AtomicString& className = classNamesString[i];
if (!usedClassNames.add(className).isNewEntry)
continue;
classNames.append('.');
classNames.append(className);
}
}
if (pseudoElement) {
if (pseudoElement->pseudoId() == BEFORE)
classNames.append("::before");
else if (pseudoElement->pseudoId() == AFTER)
classNames.append("::after");
}
if (!classNames.isEmpty())
elementInfo->setString("className", classNames.toString());
RenderObject* renderer = node->renderer();
Frame* containingFrame = node->document().frame();
FrameView* containingView = containingFrame->view();
IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
highlightObject->setObject("elementInfo", elementInfo.release());
}
evaluateInOverlay("drawNodeHighlight", highlightObject);
}
void InspectorOverlay::drawQuadHighlight()
{
if (!m_highlightQuad)
return;
Highlight highlight;
buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
}
void InspectorOverlay::drawPausedInDebuggerMessage()
{
if (!m_pausedInDebuggerMessage.isNull())
evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
}
void InspectorOverlay::drawViewSize()
{
if (m_drawViewSize)
evaluateInOverlay("drawViewSize", m_drawViewSizeWithGrid ? "true" : "false");
}
Page* InspectorOverlay::overlayPage()
{
if (m_overlayPage)
return m_overlayPage.get();
static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient;
Page::PageClients pageClients;
fillWithEmptyClients(pageClients);
ASSERT(!m_overlayChromeClient);
m_overlayChromeClient = adoptPtr(new InspectorOverlayChromeClient(m_page->chrome().client(), this));
pageClients.chromeClient = m_overlayChromeClient.get();
m_overlayPage = adoptPtr(new Page(pageClients));
Settings& settings = m_page->settings();
Settings& overlaySettings = m_overlayPage->settings();
overlaySettings.genericFontFamilySettings().setStandard(settings.genericFontFamilySettings().standard());
overlaySettings.genericFontFamilySettings().setSerif(settings.genericFontFamilySettings().serif());
overlaySettings.genericFontFamilySettings().setSansSerif(settings.genericFontFamilySettings().sansSerif());
overlaySettings.genericFontFamilySettings().setCursive(settings.genericFontFamilySettings().cursive());
overlaySettings.genericFontFamilySettings().setFantasy(settings.genericFontFamilySettings().fantasy());
overlaySettings.genericFontFamilySettings().setPictograph(settings.genericFontFamilySettings().pictograph());
overlaySettings.setMinimumFontSize(settings.minimumFontSize());
overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
overlaySettings.setMediaEnabled(false);
overlaySettings.setScriptEnabled(true);
overlaySettings.setPluginsEnabled(false);
overlaySettings.setLoadsImagesAutomatically(true);
RefPtr<Frame> frame = Frame::create(FrameInit::create(0, m_overlayPage.get(), dummyFrameLoaderClient));
frame->setView(FrameView::create(frame.get()));
frame->init();
FrameLoader& loader = frame->loader();
frame->view()->setCanHaveScrollbars(false);
frame->view()->setTransparent(true);
ASSERT(loader.activeDocumentLoader());
DocumentWriter* writer = loader.activeDocumentLoader()->beginWriting("text/html", "UTF-8");
writer->addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
loader.activeDocumentLoader()->endWriting(writer);
v8::Isolate* isolate = toIsolate(frame.get());
v8::HandleScope handleScope(isolate);
v8::Handle<v8::Context> frameContext = frame->script().currentWorldContext();
v8::Context::Scope contextScope(frameContext);
v8::Handle<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), v8::Handle<v8::Object>(), isolate);
v8::Handle<v8::Object> global = frameContext->Global();
global->Set(v8::String::NewFromUtf8(isolate, "InspectorOverlayHost"), overlayHostObj);
#if OS(WIN)
evaluateInOverlay("setPlatform", "windows");
#elif OS(MACOSX)
evaluateInOverlay("setPlatform", "mac");
#elif OS(POSIX)
evaluateInOverlay("setPlatform", "linux");
#endif
return m_overlayPage.get();
}
void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize, int scrollX, int scrollY)
{
RefPtr<JSONObject> resetData = JSONObject::create();
resetData->setNumber("pageScaleFactor", m_page->pageScaleFactor());
resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
resetData->setNumber("pageZoomFactor", m_page->mainFrame()->pageZoomFactor());
resetData->setNumber("scrollX", scrollX);
resetData->setNumber("scrollY", scrollY);
evaluateInOverlay("reset", resetData.release());
}
void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
{
RefPtr<JSONArray> command = JSONArray::create();
command->pushString(method);
command->pushString(argument);
overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
}
void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<JSONValue> argument)
{
RefPtr<JSONArray> command = JSONArray::create();
command->pushString(method);
command->pushValue(argument);
overlayPage()->mainFrame()->script().executeScriptInMainWorld("dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhenScriptsDisabled);
}
void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
{
m_drawViewSize = false;
update();
}
bool InspectorOverlay::getBoxModel(Node* node, Vector<FloatQuad>* quads)
{
return buildNodeQuads(node, *quads);
}
void InspectorOverlay::freePage()
{
m_overlayPage.clear();
m_overlayChromeClient.clear();
m_timer.stop();
}
void InspectorOverlay::startedRecordingProfile()
{
if (!m_activeProfilerCount++)
freePage();
}
} // namespace WebCore