| OLD | NEW |
| (Empty) |
| 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 "web/InspectorOverlayImpl.h" | |
| 31 | |
| 32 #include "bindings/core/v8/ScriptController.h" | |
| 33 #include "bindings/core/v8/V8InspectorOverlayHost.h" | |
| 34 #include "core/dom/Node.h" | |
| 35 #include "core/frame/FrameHost.h" | |
| 36 #include "core/frame/FrameView.h" | |
| 37 #include "core/frame/LocalFrame.h" | |
| 38 #include "core/frame/Settings.h" | |
| 39 #include "core/input/EventHandler.h" | |
| 40 #include "core/inspector/InspectorCSSAgent.h" | |
| 41 #include "core/inspector/InspectorDebuggerAgent.h" | |
| 42 #include "core/inspector/InspectorOverlayHost.h" | |
| 43 #include "core/inspector/LayoutEditor.h" | |
| 44 #include "core/layout/LayoutView.h" | |
| 45 #include "core/loader/EmptyClients.h" | |
| 46 #include "core/loader/FrameLoadRequest.h" | |
| 47 #include "core/page/ChromeClient.h" | |
| 48 #include "core/page/Page.h" | |
| 49 #include "platform/JSONValues.h" | |
| 50 #include "platform/ScriptForbiddenScope.h" | |
| 51 #include "platform/graphics/GraphicsContext.h" | |
| 52 #include "public/platform/Platform.h" | |
| 53 #include "public/platform/WebData.h" | |
| 54 #include "web/PageOverlay.h" | |
| 55 #include "web/WebGraphicsContextImpl.h" | |
| 56 #include "web/WebInputEventConversion.h" | |
| 57 #include "web/WebLocalFrameImpl.h" | |
| 58 #include "web/WebViewImpl.h" | |
| 59 #include <v8.h> | |
| 60 | |
| 61 namespace blink { | |
| 62 | |
| 63 namespace { | |
| 64 | |
| 65 Node* hoveredNodeForPoint(LocalFrame* frame, const IntPoint& pointInRootFrame, b
ool ignorePointerEventsNone) | |
| 66 { | |
| 67 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestR
equest::ReadOnly | HitTestRequest::AllowChildFrameContent; | |
| 68 if (ignorePointerEventsNone) | |
| 69 hitType |= HitTestRequest::IgnorePointerEventsNone; | |
| 70 HitTestRequest request(hitType); | |
| 71 HitTestResult result(request, frame->view()->rootFrameToContents(pointInRoot
Frame)); | |
| 72 frame->contentLayoutObject()->hitTest(result); | |
| 73 Node* node = result.innerPossiblyPseudoNode(); | |
| 74 while (node && node->nodeType() == Node::TEXT_NODE) | |
| 75 node = node->parentNode(); | |
| 76 return node; | |
| 77 } | |
| 78 | |
| 79 Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformGestureEvent& event,
bool ignorePointerEventsNone) | |
| 80 { | |
| 81 return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone)
; | |
| 82 } | |
| 83 | |
| 84 Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformMouseEvent& event, bo
ol ignorePointerEventsNone) | |
| 85 { | |
| 86 return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone)
; | |
| 87 } | |
| 88 | |
| 89 Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformTouchEvent& event, bo
ol ignorePointerEventsNone) | |
| 90 { | |
| 91 const Vector<PlatformTouchPoint>& points = event.touchPoints(); | |
| 92 if (!points.size()) | |
| 93 return nullptr; | |
| 94 return hoveredNodeForPoint(frame, roundedIntPoint(points[0].pos()), ignorePo
interEventsNone); | |
| 95 } | |
| 96 } // namespace | |
| 97 | |
| 98 class InspectorOverlayImpl::InspectorPageOverlayDelegate final : public PageOver
lay::Delegate { | |
| 99 public: | |
| 100 explicit InspectorPageOverlayDelegate(InspectorOverlayImpl& overlay) | |
| 101 : m_overlay(&overlay) | |
| 102 { } | |
| 103 | |
| 104 DEFINE_INLINE_VIRTUAL_TRACE() | |
| 105 { | |
| 106 visitor->trace(m_overlay); | |
| 107 PageOverlay::Delegate::trace(visitor); | |
| 108 } | |
| 109 | |
| 110 void paintPageOverlay(WebGraphicsContext* context, const WebSize& webViewSiz
e) | |
| 111 { | |
| 112 if (m_overlay->isEmpty()) | |
| 113 return; | |
| 114 | |
| 115 GraphicsContext& graphicsContext = toWebGraphicsContextImpl(context)->gr
aphicsContext(); | |
| 116 FrameView* view = m_overlay->overlayMainFrame()->view(); | |
| 117 ASSERT(!view->needsLayout()); | |
| 118 view->paint(&graphicsContext, IntRect(0, 0, view->width(), view->height(
))); | |
| 119 } | |
| 120 | |
| 121 private: | |
| 122 RawPtrWillBeMember<InspectorOverlayImpl> m_overlay; | |
| 123 }; | |
| 124 | |
| 125 | |
| 126 class InspectorOverlayImpl::InspectorOverlayChromeClient final : public EmptyChr
omeClient { | |
| 127 public: | |
| 128 static PassOwnPtrWillBeRawPtr<InspectorOverlayChromeClient> create(ChromeCli
ent& client, InspectorOverlayImpl& overlay) | |
| 129 { | |
| 130 return adoptPtrWillBeNoop(new InspectorOverlayChromeClient(client, overl
ay)); | |
| 131 } | |
| 132 | |
| 133 DEFINE_INLINE_VIRTUAL_TRACE() | |
| 134 { | |
| 135 visitor->trace(m_client); | |
| 136 visitor->trace(m_overlay); | |
| 137 EmptyChromeClient::trace(visitor); | |
| 138 } | |
| 139 | |
| 140 void setCursor(const Cursor& cursor) override | |
| 141 { | |
| 142 toChromeClientImpl(m_client)->setCursorOverridden(false); | |
| 143 toChromeClientImpl(m_client)->setCursor(cursor); | |
| 144 bool overrideCursor = m_overlay->m_layoutEditor; | |
| 145 toChromeClientImpl(m_client)->setCursorOverridden(overrideCursor); | |
| 146 } | |
| 147 | |
| 148 void setToolTip(const String& tooltip, TextDirection direction) override | |
| 149 { | |
| 150 m_client->setToolTip(tooltip, direction); | |
| 151 } | |
| 152 | |
| 153 void invalidateRect(const IntRect&) override | |
| 154 { | |
| 155 m_overlay->invalidate(); | |
| 156 } | |
| 157 | |
| 158 void scheduleAnimation() override | |
| 159 { | |
| 160 if (m_overlay->m_inLayout) | |
| 161 return; | |
| 162 | |
| 163 m_client->scheduleAnimation(); | |
| 164 } | |
| 165 | |
| 166 private: | |
| 167 InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlayImpl& ove
rlay) | |
| 168 : m_client(&client) | |
| 169 , m_overlay(&overlay) | |
| 170 { } | |
| 171 | |
| 172 RawPtrWillBeMember<ChromeClient> m_client; | |
| 173 RawPtrWillBeMember<InspectorOverlayImpl> m_overlay; | |
| 174 }; | |
| 175 | |
| 176 | |
| 177 InspectorOverlayImpl::InspectorOverlayImpl(WebViewImpl* webViewImpl) | |
| 178 : m_webViewImpl(webViewImpl) | |
| 179 , m_overlayHost(InspectorOverlayHost::create()) | |
| 180 , m_drawViewSize(false) | |
| 181 , m_drawViewSizeWithGrid(false) | |
| 182 , m_resizeTimerActive(false) | |
| 183 , m_omitTooltip(false) | |
| 184 , m_timer(this, &InspectorOverlayImpl::onTimer) | |
| 185 , m_suspendCount(0) | |
| 186 , m_inLayout(false) | |
| 187 , m_needsUpdate(false) | |
| 188 , m_inspectMode(InspectorDOMAgent::NotSearching) | |
| 189 { | |
| 190 } | |
| 191 | |
| 192 InspectorOverlayImpl::~InspectorOverlayImpl() | |
| 193 { | |
| 194 ASSERT(!m_overlayPage); | |
| 195 } | |
| 196 | |
| 197 DEFINE_TRACE(InspectorOverlayImpl) | |
| 198 { | |
| 199 visitor->trace(m_highlightNode); | |
| 200 visitor->trace(m_eventTargetNode); | |
| 201 visitor->trace(m_overlayPage); | |
| 202 visitor->trace(m_overlayChromeClient); | |
| 203 visitor->trace(m_overlayHost); | |
| 204 visitor->trace(m_debuggerAgent); | |
| 205 visitor->trace(m_domAgent); | |
| 206 visitor->trace(m_cssAgent); | |
| 207 visitor->trace(m_layoutEditor); | |
| 208 visitor->trace(m_hoveredNodeForInspectMode); | |
| 209 } | |
| 210 | |
| 211 void InspectorOverlayImpl::init(InspectorCSSAgent* cssAgent, InspectorDebuggerAg
ent* debuggerAgent, InspectorDOMAgent* domAgent) | |
| 212 { | |
| 213 m_debuggerAgent = debuggerAgent; | |
| 214 m_domAgent = domAgent; | |
| 215 m_cssAgent = cssAgent; | |
| 216 m_overlayHost->setListener(this); | |
| 217 } | |
| 218 | |
| 219 void InspectorOverlayImpl::invalidate() | |
| 220 { | |
| 221 if (!m_pageOverlay) | |
| 222 m_pageOverlay = PageOverlay::create(m_webViewImpl, new InspectorPageOver
layDelegate(*this)); | |
| 223 | |
| 224 m_pageOverlay->update(); | |
| 225 } | |
| 226 | |
| 227 void InspectorOverlayImpl::layout() | |
| 228 { | |
| 229 if (isEmpty()) | |
| 230 return; | |
| 231 | |
| 232 TemporaryChange<bool> scoped(m_inLayout, true); | |
| 233 if (m_needsUpdate) { | |
| 234 m_needsUpdate = false; | |
| 235 rebuildOverlayPage(); | |
| 236 } | |
| 237 overlayMainFrame()->view()->updateAllLifecyclePhases(); | |
| 238 } | |
| 239 | |
| 240 bool InspectorOverlayImpl::handleInputEvent(const WebInputEvent& inputEvent) | |
| 241 { | |
| 242 bool handled = false; | |
| 243 | |
| 244 if (isEmpty()) | |
| 245 return false; | |
| 246 | |
| 247 if (WebInputEvent::isGestureEventType(inputEvent.type) && inputEvent.type ==
WebInputEvent::GestureTap) { | |
| 248 // Only let GestureTab in (we only need it and we know PlatformGestureEv
entBuilder supports it). | |
| 249 PlatformGestureEvent gestureEvent = PlatformGestureEventBuilder(m_webVie
wImpl->mainFrameImpl()->frameView(), static_cast<const WebGestureEvent&>(inputEv
ent)); | |
| 250 handled = handleGestureEvent(gestureEvent); | |
| 251 if (handled) | |
| 252 return true; | |
| 253 | |
| 254 overlayMainFrame()->eventHandler().handleGestureEvent(gestureEvent); | |
| 255 } | |
| 256 if (WebInputEvent::isMouseEventType(inputEvent.type) && inputEvent.type != W
ebInputEvent::MouseEnter) { | |
| 257 // PlatformMouseEventBuilder does not work with MouseEnter type, so we f
ilter it out manually. | |
| 258 PlatformMouseEvent mouseEvent = PlatformMouseEventBuilder(m_webViewImpl-
>mainFrameImpl()->frameView(), static_cast<const WebMouseEvent&>(inputEvent)); | |
| 259 | |
| 260 if (mouseEvent.type() == PlatformEvent::MouseMoved) | |
| 261 handled = handleMouseMove(mouseEvent); | |
| 262 else if (mouseEvent.type() == PlatformEvent::MousePressed) | |
| 263 handled = handleMousePress(); | |
| 264 | |
| 265 if (handled) | |
| 266 return true; | |
| 267 | |
| 268 if (mouseEvent.type() == PlatformEvent::MouseMoved) | |
| 269 handled = overlayMainFrame()->eventHandler().handleMouseMoveEvent(mo
useEvent); | |
| 270 if (mouseEvent.type() == PlatformEvent::MousePressed) | |
| 271 handled = overlayMainFrame()->eventHandler().handleMousePressEvent(m
ouseEvent); | |
| 272 if (mouseEvent.type() == PlatformEvent::MouseReleased) | |
| 273 handled = overlayMainFrame()->eventHandler().handleMouseReleaseEvent
(mouseEvent); | |
| 274 } | |
| 275 | |
| 276 if (WebInputEvent::isTouchEventType(inputEvent.type)) { | |
| 277 PlatformTouchEvent touchEvent = PlatformTouchEventBuilder(m_webViewImpl-
>mainFrameImpl()->frameView(), static_cast<const WebTouchEvent&>(inputEvent)); | |
| 278 handled = handleTouchEvent(touchEvent); | |
| 279 if (handled) | |
| 280 return true; | |
| 281 overlayMainFrame()->eventHandler().handleTouchEvent(touchEvent); | |
| 282 } | |
| 283 if (WebInputEvent::isKeyboardEventType(inputEvent.type)) { | |
| 284 PlatformKeyboardEvent keyboardEvent = PlatformKeyboardEventBuilder(stati
c_cast<const WebKeyboardEvent&>(inputEvent)); | |
| 285 overlayMainFrame()->eventHandler().keyEvent(keyboardEvent); | |
| 286 } | |
| 287 | |
| 288 if (inputEvent.type == WebInputEvent::MouseWheel) { | |
| 289 PlatformWheelEvent wheelEvent = PlatformWheelEventBuilder(m_webViewImpl-
>mainFrameImpl()->frameView(), static_cast<const WebMouseWheelEvent&>(inputEvent
)); | |
| 290 handled = overlayMainFrame()->eventHandler().handleWheelEvent(wheelEvent
); | |
| 291 } | |
| 292 | |
| 293 return handled; | |
| 294 } | |
| 295 | |
| 296 void InspectorOverlayImpl::setPausedInDebuggerMessage(const String* message) | |
| 297 { | |
| 298 m_pausedInDebuggerMessage = message ? *message : String(); | |
| 299 scheduleUpdate(); | |
| 300 } | |
| 301 | |
| 302 void InspectorOverlayImpl::hideHighlight() | |
| 303 { | |
| 304 m_highlightNode.clear(); | |
| 305 m_eventTargetNode.clear(); | |
| 306 m_highlightQuad.clear(); | |
| 307 | |
| 308 if (m_layoutEditor && m_inspectModeHighlightConfig) | |
| 309 highlightNode(m_layoutEditor->element(), *m_inspectModeHighlightConfig,
false); | |
| 310 else | |
| 311 scheduleUpdate(); | |
| 312 } | |
| 313 | |
| 314 void InspectorOverlayImpl::highlightNode(Node* node, const InspectorHighlightCon
fig& highlightConfig, bool omitTooltip) | |
| 315 { | |
| 316 highlightNode(node, nullptr, highlightConfig, omitTooltip); | |
| 317 } | |
| 318 | |
| 319 void InspectorOverlayImpl::highlightNode(Node* node, Node* eventTarget, const In
spectorHighlightConfig& highlightConfig, bool omitTooltip) | |
| 320 { | |
| 321 m_nodeHighlightConfig = highlightConfig; | |
| 322 m_highlightNode = node; | |
| 323 m_eventTargetNode = eventTarget; | |
| 324 m_omitTooltip = omitTooltip; | |
| 325 scheduleUpdate(); | |
| 326 } | |
| 327 | |
| 328 void InspectorOverlayImpl::setInspectMode(InspectorDOMAgent::SearchMode searchMo
de, PassOwnPtr<InspectorHighlightConfig> highlightConfig) | |
| 329 { | |
| 330 if (m_layoutEditor) | |
| 331 overlayClearSelection(true); | |
| 332 | |
| 333 m_inspectMode = searchMode; | |
| 334 scheduleUpdate(); | |
| 335 | |
| 336 if (searchMode != InspectorDOMAgent::NotSearching) { | |
| 337 m_inspectModeHighlightConfig = highlightConfig; | |
| 338 } else { | |
| 339 m_hoveredNodeForInspectMode.clear(); | |
| 340 hideHighlight(); | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 void InspectorOverlayImpl::highlightQuad(PassOwnPtr<FloatQuad> quad, const Inspe
ctorHighlightConfig& highlightConfig) | |
| 345 { | |
| 346 m_quadHighlightConfig = highlightConfig; | |
| 347 m_highlightQuad = quad; | |
| 348 m_omitTooltip = false; | |
| 349 scheduleUpdate(); | |
| 350 } | |
| 351 | |
| 352 bool InspectorOverlayImpl::isEmpty() | |
| 353 { | |
| 354 if (m_suspendCount) | |
| 355 return true; | |
| 356 bool hasVisibleElements = m_highlightNode || m_eventTargetNode || m_highligh
tQuad || (m_resizeTimerActive && m_drawViewSize) || !m_pausedInDebuggerMessage.
isNull(); | |
| 357 return !hasVisibleElements && m_inspectMode == InspectorDOMAgent::NotSearchi
ng; | |
| 358 } | |
| 359 | |
| 360 void InspectorOverlayImpl::scheduleUpdate() | |
| 361 { | |
| 362 if (isEmpty()) { | |
| 363 if (m_pageOverlay) | |
| 364 m_pageOverlay.clear(); | |
| 365 return; | |
| 366 } | |
| 367 m_needsUpdate = true; | |
| 368 m_webViewImpl->page()->chromeClient().scheduleAnimation(); | |
| 369 } | |
| 370 | |
| 371 void InspectorOverlayImpl::rebuildOverlayPage() | |
| 372 { | |
| 373 FrameView* view = m_webViewImpl->mainFrameImpl()->frameView(); | |
| 374 if (!view) | |
| 375 return; | |
| 376 | |
| 377 IntRect visibleRectInDocument = view->scrollableArea()->visibleContentRect()
; | |
| 378 IntSize viewportSize = m_webViewImpl->page()->frameHost().visualViewport().s
ize(); | |
| 379 toLocalFrame(overlayPage()->mainFrame())->view()->resize(viewportSize); | |
| 380 overlayPage()->frameHost().visualViewport().setSize(viewportSize); | |
| 381 reset(viewportSize, visibleRectInDocument.location()); | |
| 382 | |
| 383 drawNodeHighlight(); | |
| 384 drawQuadHighlight(); | |
| 385 drawPausedInDebuggerMessage(); | |
| 386 drawViewSize(); | |
| 387 } | |
| 388 | |
| 389 static PassRefPtr<JSONObject> buildObjectForSize(const IntSize& size) | |
| 390 { | |
| 391 RefPtr<JSONObject> result = JSONObject::create(); | |
| 392 result->setNumber("width", size.width()); | |
| 393 result->setNumber("height", size.height()); | |
| 394 return result.release(); | |
| 395 } | |
| 396 | |
| 397 void InspectorOverlayImpl::drawNodeHighlight() | |
| 398 { | |
| 399 if (!m_highlightNode) | |
| 400 return; | |
| 401 | |
| 402 bool appendElementInfo = m_highlightNode->isElementNode() && !m_omitTooltip
&& m_nodeHighlightConfig.showInfo && m_highlightNode->layoutObject() && m_highli
ghtNode->document().frame(); | |
| 403 InspectorHighlight highlight(m_highlightNode.get(), m_nodeHighlightConfig, a
ppendElementInfo); | |
| 404 if (m_eventTargetNode) | |
| 405 highlight.appendEventTargetQuads(m_eventTargetNode.get(), m_nodeHighligh
tConfig); | |
| 406 | |
| 407 RefPtr<JSONObject> highlightJSON = highlight.asJSONObject(); | |
| 408 evaluateInOverlay("drawHighlight", highlightJSON.release()); | |
| 409 if (m_layoutEditor && m_highlightNode == m_layoutEditor->element()) { | |
| 410 RefPtr<JSONObject> layoutEditorInfo = m_layoutEditor->buildJSONInfo(); | |
| 411 if (layoutEditorInfo) | |
| 412 evaluateInOverlay("showLayoutEditor", layoutEditorInfo.release()); | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 void InspectorOverlayImpl::drawQuadHighlight() | |
| 417 { | |
| 418 if (!m_highlightQuad) | |
| 419 return; | |
| 420 | |
| 421 InspectorHighlight highlight; | |
| 422 highlight.appendQuad(*m_highlightQuad, m_quadHighlightConfig.content, m_quad
HighlightConfig.contentOutline); | |
| 423 evaluateInOverlay("drawHighlight", highlight.asJSONObject()); | |
| 424 } | |
| 425 | |
| 426 void InspectorOverlayImpl::drawPausedInDebuggerMessage() | |
| 427 { | |
| 428 if (m_inspectMode == InspectorDOMAgent::NotSearching && !m_pausedInDebuggerM
essage.isNull()) | |
| 429 evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessa
ge); | |
| 430 } | |
| 431 | |
| 432 void InspectorOverlayImpl::drawViewSize() | |
| 433 { | |
| 434 if (m_resizeTimerActive && m_drawViewSize) | |
| 435 evaluateInOverlay("drawViewSize", m_drawViewSizeWithGrid ? "true" : "fal
se"); | |
| 436 } | |
| 437 | |
| 438 Page* InspectorOverlayImpl::overlayPage() | |
| 439 { | |
| 440 if (m_overlayPage) | |
| 441 return m_overlayPage.get(); | |
| 442 | |
| 443 ScriptForbiddenScope::AllowUserAgentScript allowScript; | |
| 444 | |
| 445 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<FrameLoaderClient>, dummyFrameLoa
derClient, (EmptyFrameLoaderClient::create())); | |
| 446 Page::PageClients pageClients; | |
| 447 fillWithEmptyClients(pageClients); | |
| 448 ASSERT(!m_overlayChromeClient); | |
| 449 m_overlayChromeClient = InspectorOverlayChromeClient::create(m_webViewImpl->
page()->chromeClient(), *this); | |
| 450 pageClients.chromeClient = m_overlayChromeClient.get(); | |
| 451 m_overlayPage = adoptPtrWillBeNoop(new Page(pageClients)); | |
| 452 | |
| 453 Settings& settings = m_webViewImpl->page()->settings(); | |
| 454 Settings& overlaySettings = m_overlayPage->settings(); | |
| 455 | |
| 456 overlaySettings.genericFontFamilySettings().updateStandard(settings.genericF
ontFamilySettings().standard()); | |
| 457 overlaySettings.genericFontFamilySettings().updateSerif(settings.genericFont
FamilySettings().serif()); | |
| 458 overlaySettings.genericFontFamilySettings().updateSansSerif(settings.generic
FontFamilySettings().sansSerif()); | |
| 459 overlaySettings.genericFontFamilySettings().updateCursive(settings.genericFo
ntFamilySettings().cursive()); | |
| 460 overlaySettings.genericFontFamilySettings().updateFantasy(settings.genericFo
ntFamilySettings().fantasy()); | |
| 461 overlaySettings.genericFontFamilySettings().updatePictograph(settings.generi
cFontFamilySettings().pictograph()); | |
| 462 overlaySettings.setMinimumFontSize(settings.minimumFontSize()); | |
| 463 overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize())
; | |
| 464 overlaySettings.setScriptEnabled(true); | |
| 465 overlaySettings.setPluginsEnabled(false); | |
| 466 overlaySettings.setLoadsImagesAutomatically(true); | |
| 467 // FIXME: http://crbug.com/363843. Inspector should probably create its | |
| 468 // own graphics layers and attach them to the tree rather than going | |
| 469 // through some non-composited paint function. | |
| 470 overlaySettings.setAcceleratedCompositingEnabled(false); | |
| 471 | |
| 472 RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(dummyFrameLoaderCl
ient.get(), &m_overlayPage->frameHost(), 0); | |
| 473 frame->setView(FrameView::create(frame.get())); | |
| 474 frame->init(); | |
| 475 FrameLoader& loader = frame->loader(); | |
| 476 frame->view()->setCanHaveScrollbars(false); | |
| 477 frame->view()->setTransparent(true); | |
| 478 | |
| 479 const WebData& overlayPageHTMLResource = Platform::current()->loadResource("
InspectorOverlayPage.html"); | |
| 480 RefPtr<SharedBuffer> data = SharedBuffer::create(overlayPageHTMLResource.dat
a(), overlayPageHTMLResource.size()); | |
| 481 loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html"
, "UTF-8", KURL(), ForceSynchronousLoad))); | |
| 482 v8::Isolate* isolate = toIsolate(frame.get()); | |
| 483 ScriptState* scriptState = ScriptState::forMainWorld(frame.get()); | |
| 484 ASSERT(scriptState->contextIsValid()); | |
| 485 ScriptState::Scope scope(scriptState); | |
| 486 v8::Local<v8::Object> global = scriptState->context()->Global(); | |
| 487 v8::Local<v8::Value> overlayHostObj = toV8(m_overlayHost.get(), global, isol
ate); | |
| 488 ASSERT(!overlayHostObj.IsEmpty()); | |
| 489 v8CallOrCrash(global->Set(scriptState->context(), v8AtomicString(isolate, "I
nspectorOverlayHost"), overlayHostObj)); | |
| 490 | |
| 491 #if OS(WIN) | |
| 492 evaluateInOverlay("setPlatform", "windows"); | |
| 493 #elif OS(MACOSX) | |
| 494 evaluateInOverlay("setPlatform", "mac"); | |
| 495 #elif OS(POSIX) | |
| 496 evaluateInOverlay("setPlatform", "linux"); | |
| 497 #endif | |
| 498 | |
| 499 return m_overlayPage.get(); | |
| 500 } | |
| 501 | |
| 502 LocalFrame* InspectorOverlayImpl::overlayMainFrame() | |
| 503 { | |
| 504 return toLocalFrame(overlayPage()->mainFrame()); | |
| 505 } | |
| 506 | |
| 507 void InspectorOverlayImpl::reset(const IntSize& viewportSize, const IntPoint& do
cumentScrollOffset) | |
| 508 { | |
| 509 RefPtr<JSONObject> resetData = JSONObject::create(); | |
| 510 resetData->setNumber("deviceScaleFactor", m_webViewImpl->page()->deviceScale
Factor()); | |
| 511 resetData->setObject("viewportSize", buildObjectForSize(viewportSize)); | |
| 512 resetData->setNumber("pageZoomFactor", m_webViewImpl->mainFrameImpl()->frame
()->pageZoomFactor()); | |
| 513 resetData->setNumber("scrollX", documentScrollOffset.x()); | |
| 514 resetData->setNumber("scrollY", documentScrollOffset.y()); | |
| 515 evaluateInOverlay("reset", resetData.release()); | |
| 516 } | |
| 517 | |
| 518 void InspectorOverlayImpl::evaluateInOverlay(const String& method, const String&
argument) | |
| 519 { | |
| 520 ScriptForbiddenScope::AllowUserAgentScript allowScript; | |
| 521 RefPtr<JSONArray> command = JSONArray::create(); | |
| 522 command->pushString(method); | |
| 523 command->pushString(argument); | |
| 524 toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld(
"dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhen
ScriptsDisabled); | |
| 525 } | |
| 526 | |
| 527 void InspectorOverlayImpl::evaluateInOverlay(const String& method, PassRefPtr<JS
ONValue> argument) | |
| 528 { | |
| 529 ScriptForbiddenScope::AllowUserAgentScript allowScript; | |
| 530 RefPtr<JSONArray> command = JSONArray::create(); | |
| 531 command->pushString(method); | |
| 532 command->pushValue(argument); | |
| 533 toLocalFrame(overlayPage()->mainFrame())->script().executeScriptInMainWorld(
"dispatch(" + command->toJSONString() + ")", ScriptController::ExecuteScriptWhen
ScriptsDisabled); | |
| 534 } | |
| 535 | |
| 536 void InspectorOverlayImpl::onTimer(Timer<InspectorOverlayImpl>*) | |
| 537 { | |
| 538 m_resizeTimerActive = false; | |
| 539 scheduleUpdate(); | |
| 540 } | |
| 541 | |
| 542 void InspectorOverlayImpl::clear() | |
| 543 { | |
| 544 if (m_overlayPage) { | |
| 545 m_overlayPage->willBeDestroyed(); | |
| 546 m_overlayPage.clear(); | |
| 547 m_overlayChromeClient.clear(); | |
| 548 } | |
| 549 m_resizeTimerActive = false; | |
| 550 m_pausedInDebuggerMessage = String(); | |
| 551 m_inspectMode = InspectorDOMAgent::NotSearching; | |
| 552 m_timer.stop(); | |
| 553 hideHighlight(); | |
| 554 } | |
| 555 | |
| 556 void InspectorOverlayImpl::overlayResumed() | |
| 557 { | |
| 558 if (m_debuggerAgent) { | |
| 559 ErrorString error; | |
| 560 m_debuggerAgent->resume(&error); | |
| 561 } | |
| 562 } | |
| 563 | |
| 564 void InspectorOverlayImpl::overlaySteppedOver() | |
| 565 { | |
| 566 if (m_debuggerAgent) { | |
| 567 ErrorString error; | |
| 568 m_debuggerAgent->stepOver(&error); | |
| 569 } | |
| 570 } | |
| 571 | |
| 572 void InspectorOverlayImpl::overlayStartedPropertyChange(const String& property) | |
| 573 { | |
| 574 ASSERT(m_layoutEditor); | |
| 575 m_layoutEditor->overlayStartedPropertyChange(property); | |
| 576 } | |
| 577 | |
| 578 void InspectorOverlayImpl::overlayPropertyChanged(float value) | |
| 579 { | |
| 580 ASSERT(m_layoutEditor); | |
| 581 m_layoutEditor->overlayPropertyChanged(value); | |
| 582 } | |
| 583 | |
| 584 void InspectorOverlayImpl::overlayEndedPropertyChange() | |
| 585 { | |
| 586 ASSERT(m_layoutEditor); | |
| 587 m_layoutEditor->overlayEndedPropertyChange(); | |
| 588 } | |
| 589 | |
| 590 void InspectorOverlayImpl::overlayNextSelector() | |
| 591 { | |
| 592 ASSERT(m_layoutEditor); | |
| 593 m_layoutEditor->nextSelector(); | |
| 594 } | |
| 595 | |
| 596 void InspectorOverlayImpl::overlayPreviousSelector() | |
| 597 { | |
| 598 ASSERT(m_layoutEditor); | |
| 599 m_layoutEditor->previousSelector(); | |
| 600 } | |
| 601 | |
| 602 String InspectorOverlayImpl::overlayCurrentSelectorInfo() | |
| 603 { | |
| 604 ASSERT(m_layoutEditor); | |
| 605 return m_layoutEditor->currentSelectorInfo(); | |
| 606 } | |
| 607 | |
| 608 void InspectorOverlayImpl::overlayClearSelection(bool commitChanges) | |
| 609 { | |
| 610 ASSERT(m_layoutEditor); | |
| 611 m_hoveredNodeForInspectMode = m_layoutEditor->element(); | |
| 612 | |
| 613 if (commitChanges) | |
| 614 m_layoutEditor->commitChanges(); | |
| 615 | |
| 616 if (m_layoutEditor) { | |
| 617 m_layoutEditor->dispose(); | |
| 618 m_layoutEditor.clear(); | |
| 619 } | |
| 620 | |
| 621 if (m_inspectModeHighlightConfig) | |
| 622 highlightNode(m_hoveredNodeForInspectMode.get(), *m_inspectModeHighlight
Config, false); | |
| 623 | |
| 624 toChromeClientImpl(m_webViewImpl->page()->chromeClient()).setCursorOverridde
n(false); | |
| 625 toChromeClientImpl(m_webViewImpl->page()->chromeClient()).setCursor(pointerC
ursor()); | |
| 626 } | |
| 627 | |
| 628 void InspectorOverlayImpl::profilingStarted() | |
| 629 { | |
| 630 if (!m_suspendCount++) | |
| 631 clear(); | |
| 632 } | |
| 633 | |
| 634 void InspectorOverlayImpl::profilingStopped() | |
| 635 { | |
| 636 --m_suspendCount; | |
| 637 } | |
| 638 | |
| 639 void InspectorOverlayImpl::pageLayoutInvalidated(bool resized) | |
| 640 { | |
| 641 if (resized && m_drawViewSize) { | |
| 642 m_resizeTimerActive = true; | |
| 643 m_timer.startOneShot(1, FROM_HERE); | |
| 644 } | |
| 645 scheduleUpdate(); | |
| 646 } | |
| 647 | |
| 648 void InspectorOverlayImpl::setShowViewportSizeOnResize(bool show, bool showGrid) | |
| 649 { | |
| 650 m_drawViewSize = show; | |
| 651 m_drawViewSizeWithGrid = showGrid; | |
| 652 } | |
| 653 | |
| 654 bool InspectorOverlayImpl::handleMouseMove(const PlatformMouseEvent& event) | |
| 655 { | |
| 656 if (!shouldSearchForNode()) | |
| 657 return false; | |
| 658 | |
| 659 LocalFrame* frame = m_webViewImpl->mainFrameImpl()->frame(); | |
| 660 if (!frame->view() || !frame->contentLayoutObject()) | |
| 661 return false; | |
| 662 Node* node = hoveredNodeForEvent(frame, event, event.shiftKey()); | |
| 663 | |
| 664 // Do not highlight within user agent shadow root unless requested. | |
| 665 if (m_inspectMode != InspectorDOMAgent::SearchingForUAShadow) { | |
| 666 ShadowRoot* shadowRoot = InspectorDOMAgent::userAgentShadowRoot(node); | |
| 667 if (shadowRoot) | |
| 668 node = shadowRoot->host(); | |
| 669 } | |
| 670 | |
| 671 // Shadow roots don't have boxes - use host element instead. | |
| 672 if (node && node->isShadowRoot()) | |
| 673 node = node->parentOrShadowHostNode(); | |
| 674 | |
| 675 if (!node) | |
| 676 return true; | |
| 677 | |
| 678 Node* eventTarget = event.shiftKey() ? hoveredNodeForEvent(m_webViewImpl->ma
inFrameImpl()->frame(), event, false) : nullptr; | |
| 679 if (eventTarget == node) | |
| 680 eventTarget = nullptr; | |
| 681 | |
| 682 if (node && m_inspectModeHighlightConfig) { | |
| 683 m_hoveredNodeForInspectMode = node; | |
| 684 highlightNode(node, eventTarget, *m_inspectModeHighlightConfig, event.ct
rlKey() || event.metaKey()); | |
| 685 } | |
| 686 return true; | |
| 687 } | |
| 688 | |
| 689 bool InspectorOverlayImpl::handleMousePress() | |
| 690 { | |
| 691 if (!shouldSearchForNode()) | |
| 692 return false; | |
| 693 | |
| 694 if (m_hoveredNodeForInspectMode) { | |
| 695 inspect(m_hoveredNodeForInspectMode.get()); | |
| 696 m_hoveredNodeForInspectMode.clear(); | |
| 697 return true; | |
| 698 } | |
| 699 return false; | |
| 700 } | |
| 701 | |
| 702 bool InspectorOverlayImpl::handleGestureEvent(const PlatformGestureEvent& event) | |
| 703 { | |
| 704 if (!shouldSearchForNode() || event.type() != PlatformEvent::GestureTap) | |
| 705 return false; | |
| 706 Node* node = hoveredNodeForEvent(m_webViewImpl->mainFrameImpl()->frame(), ev
ent, false); | |
| 707 if (node && m_inspectModeHighlightConfig) { | |
| 708 highlightNode(node, *m_inspectModeHighlightConfig, false); | |
| 709 inspect(node); | |
| 710 return true; | |
| 711 } | |
| 712 return false; | |
| 713 } | |
| 714 | |
| 715 bool InspectorOverlayImpl::handleTouchEvent(const PlatformTouchEvent& event) | |
| 716 { | |
| 717 if (!shouldSearchForNode()) | |
| 718 return false; | |
| 719 Node* node = hoveredNodeForEvent(m_webViewImpl->mainFrameImpl()->frame(), ev
ent, false); | |
| 720 if (node && m_inspectModeHighlightConfig) { | |
| 721 highlightNode(node, *m_inspectModeHighlightConfig, false); | |
| 722 inspect(node); | |
| 723 return true; | |
| 724 } | |
| 725 return false; | |
| 726 } | |
| 727 | |
| 728 bool InspectorOverlayImpl::shouldSearchForNode() | |
| 729 { | |
| 730 return m_inspectMode != InspectorDOMAgent::NotSearching && !m_layoutEditor; | |
| 731 } | |
| 732 | |
| 733 void InspectorOverlayImpl::inspect(Node* node) | |
| 734 { | |
| 735 if (m_domAgent) | |
| 736 m_domAgent->inspect(node); | |
| 737 | |
| 738 if (node && node->isElementNode() && m_inspectMode == InspectorDOMAgent::Sho
wLayoutEditor && !m_layoutEditor) { | |
| 739 m_layoutEditor = LayoutEditor::create(toElement(node), m_cssAgent, m_dom
Agent); | |
| 740 toChromeClientImpl(m_webViewImpl->page()->chromeClient()).setCursorOverr
idden(true); | |
| 741 highlightNode(node, *m_inspectModeHighlightConfig, false); | |
| 742 } | |
| 743 } | |
| 744 | |
| 745 } // namespace blink | |
| OLD | NEW |