1 /* 2 * Copyright (C) 2010-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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "web/WebDevToolsAgentImpl.h" 33 34 #include "bindings/v8/PageScriptDebugServer.h" 35 #include "bindings/v8/ScriptController.h" 36 #include "bindings/v8/V8Binding.h" 37 #include "core/InspectorBackendDispatcher.h" 38 #include "core/InspectorFrontend.h" 39 #include "core/dom/ExceptionCode.h" 40 #include "core/fetch/MemoryCache.h" 41 #include "core/frame/FrameView.h" 42 #include "core/frame/LocalFrame.h" 43 #include "core/frame/Settings.h" 44 #include "core/inspector/InjectedScriptHost.h" 45 #include "core/inspector/InspectorController.h" 46 #include "core/page/FocusController.h" 47 #include "core/page/Page.h" 48 #include "core/rendering/RenderView.h" 49 #include "platform/JSONValues.h" 50 #include "platform/RuntimeEnabledFeatures.h" 51 #include "platform/TraceEvent.h" 52 #include "platform/graphics/GraphicsContext.h" 53 #include "platform/network/ResourceError.h" 54 #include "platform/network/ResourceRequest.h" 55 #include "platform/network/ResourceResponse.h" 56 #include "public/platform/Platform.h" 57 #include "public/platform/WebRect.h" 58 #include "public/platform/WebString.h" 59 #include "public/platform/WebURL.h" 60 #include "public/platform/WebURLError.h" 61 #include "public/platform/WebURLRequest.h" 62 #include "public/platform/WebURLResponse.h" 63 #include "public/web/WebDataSource.h" 64 #include "public/web/WebDevToolsAgentClient.h" 65 #include "public/web/WebDeviceEmulationParams.h" 66 #include "public/web/WebMemoryUsageInfo.h" 67 #include "public/web/WebSettings.h" 68 #include "public/web/WebViewClient.h" 69 #include "web/WebInputEventConversion.h" 70 #include "web/WebLocalFrameImpl.h" 71 #include "web/WebViewImpl.h" 72 #include "wtf/CurrentTime.h" 73 #include "wtf/MathExtras.h" 74 #include "wtf/Noncopyable.h" 75 #include "wtf/text/WTFString.h" 76 77 using namespace WebCore; 78 79 namespace OverlayZOrders { 80 // Use 99 as a big z-order number so that highlight is above other overlays. 81 static const int highlight = 99; 82 } 83 84 namespace blink { 85 86 class ClientMessageLoopAdapter : public PageScriptDebugServer::ClientMessageLoop { 87 public: 88 static void ensureClientMessageLoopCreated(WebDevToolsAgentClient* client) 89 { 90 if (s_instance) 91 return; 92 OwnPtr<ClientMessageLoopAdapter> instance = adoptPtr(new ClientMessageLoopAdapter(adoptPtr(client->createClientMessageLoop()))); 93 s_instance = instance.get(); 94 PageScriptDebugServer::shared().setClientMessageLoop(instance.release()); 95 } 96 97 static void inspectedViewClosed(WebViewImpl* view) 98 { 99 if (s_instance) 100 s_instance->m_frozenViews.remove(view); 101 } 102 103 static void didNavigate() 104 { 105 // Release render thread if necessary. 106 if (s_instance && s_instance->m_running) 107 PageScriptDebugServer::shared().continueProgram(); 108 } 109 110 private: 111 ClientMessageLoopAdapter(PassOwnPtr<blink::WebDevToolsAgentClient::WebKitClientMessageLoop> messageLoop) 112 : m_running(false) 113 , m_messageLoop(messageLoop) { } 114 115 116 virtual void run(Page* page) 117 { 118 if (m_running) 119 return; 120 m_running = true; 121 122 // 0. Flush pending frontend messages. 123 WebViewImpl* viewImpl = WebViewImpl::fromPage(page); 124 WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(viewImpl->devToolsAgent()); 125 agent->flushPendingFrontendMessages(); 126 127 Vector<WebViewImpl*> views; 128 129 // 1. Disable input events. 130 const HashSet<Page*>& pages = Page::ordinaryPages(); 131 HashSet<Page*>::const_iterator end = pages.end(); 132 for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { 133 WebViewImpl* view = WebViewImpl::fromPage(*it); 134 if (!view) 135 continue; 136 m_frozenViews.add(view); 137 views.append(view); 138 view->setIgnoreInputEvents(true); 139 } 140 // Notify embedder about pausing. 141 agent->client()->willEnterDebugLoop(); 142 143 // 2. Disable active objects 144 WebView::willEnterModalLoop(); 145 146 // 3. Process messages until quitNow is called. 147 m_messageLoop->run(); 148 149 // 4. Resume active objects 150 WebView::didExitModalLoop(); 151 152 // 5. Resume input events. 153 for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) { 154 if (m_frozenViews.contains(*it)) { 155 // The view was not closed during the dispatch. 156 (*it)->setIgnoreInputEvents(false); 157 } 158 } 159 agent->client()->didExitDebugLoop(); 160 161 // 6. All views have been resumed, clear the set. 162 m_frozenViews.clear(); 163 164 m_running = false; 165 } 166 167 virtual void quitNow() 168 { 169 m_messageLoop->quitNow(); 170 } 171 172 bool m_running; 173 OwnPtr<blink::WebDevToolsAgentClient::WebKitClientMessageLoop> m_messageLoop; 174 typedef HashSet<WebViewImpl*> FrozenViewsSet; 175 FrozenViewsSet m_frozenViews; 176 // FIXME: The ownership model for s_instance is somewhat complicated. Can we make this simpler? 177 static ClientMessageLoopAdapter* s_instance; 178 }; 179 180 ClientMessageLoopAdapter* ClientMessageLoopAdapter::s_instance = 0; 181 182 class DebuggerTask : public PageScriptDebugServer::Task { 183 public: 184 DebuggerTask(PassOwnPtr<WebDevToolsAgent::MessageDescriptor> descriptor) 185 : m_descriptor(descriptor) 186 { 187 } 188 189 virtual ~DebuggerTask() { } 190 virtual void run() 191 { 192 if (WebDevToolsAgent* webagent = m_descriptor->agent()) 193 webagent->dispatchOnInspectorBackend(m_descriptor->message()); 194 } 195 196 private: 197 OwnPtr<WebDevToolsAgent::MessageDescriptor> m_descriptor; 198 }; 199 200 WebDevToolsAgentImpl::WebDevToolsAgentImpl( 201 WebViewImpl* webViewImpl, 202 WebDevToolsAgentClient* client) 203 : m_debuggerId(client->debuggerId()) 204 , m_layerTreeId(0) 205 , m_client(client) 206 , m_webViewImpl(webViewImpl) 207 , m_attached(false) 208 , m_generatingEvent(false) 209 , m_deviceMetricsEnabled(false) 210 , m_emulateViewportEnabled(false) 211 , m_originalViewportEnabled(false) 212 , m_isOverlayScrollbarsEnabled(false) 213 , m_originalMinimumPageScaleFactor(0) 214 , m_originalMaximumPageScaleFactor(0) 215 , m_pageScaleLimitsOverriden(false) 216 , m_touchEventEmulationEnabled(false) 217 { 218 ASSERT(m_debuggerId > 0); 219 ClientMessageLoopAdapter::ensureClientMessageLoopCreated(m_client); 220 } 221 222 WebDevToolsAgentImpl::~WebDevToolsAgentImpl() 223 { 224 ClientMessageLoopAdapter::inspectedViewClosed(m_webViewImpl); 225 if (m_attached) 226 blink::Platform::current()->currentThread()->removeTaskObserver(this); 227 } 228 229 void WebDevToolsAgentImpl::attach() 230 { 231 attach(""); 232 } 233 234 void WebDevToolsAgentImpl::reattach(const WebString& savedState) 235 { 236 reattach("", savedState); 237 } 238 239 void WebDevToolsAgentImpl::attach(const WebString& hostId) 240 { 241 if (m_attached) 242 return; 243 244 inspectorController()->connectFrontend(hostId, this); 245 blink::Platform::current()->currentThread()->addTaskObserver(this); 246 m_attached = true; 247 } 248 249 void WebDevToolsAgentImpl::reattach(const WebString& hostId, const WebString& savedState) 250 { 251 if (m_attached) 252 return; 253 254 inspectorController()->reuseFrontend(hostId, this, savedState); 255 blink::Platform::current()->currentThread()->addTaskObserver(this); 256 m_attached = true; 257 } 258 259 void WebDevToolsAgentImpl::detach() 260 { 261 blink::Platform::current()->currentThread()->removeTaskObserver(this); 262 263 // Prevent controller from sending messages to the frontend. 264 InspectorController* ic = inspectorController(); 265 ic->disconnectFrontend(); 266 m_attached = false; 267 } 268 269 void WebDevToolsAgentImpl::didNavigate() 270 { 271 ClientMessageLoopAdapter::didNavigate(); 272 } 273 274 void WebDevToolsAgentImpl::didBeginFrame(int frameId) 275 { 276 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "BeginMainThreadFrame", "layerTreeId", m_layerTreeId); 277 if (InspectorController* ic = inspectorController()) 278 ic->didBeginFrame(frameId); 279 } 280 281 void WebDevToolsAgentImpl::didCancelFrame() 282 { 283 if (InspectorController* ic = inspectorController()) 284 ic->didCancelFrame(); 285 } 286 287 void WebDevToolsAgentImpl::willComposite() 288 { 289 TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "CompositeLayers", "layerTreeId", m_layerTreeId); 290 if (InspectorController* ic = inspectorController()) 291 ic->willComposite(); 292 } 293 294 void WebDevToolsAgentImpl::didComposite() 295 { 296 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "CompositeLayers"); 297 if (InspectorController* ic = inspectorController()) 298 ic->didComposite(); 299 } 300 301 void WebDevToolsAgentImpl::didCreateScriptContext(WebLocalFrameImpl* webframe, int worldId) 302 { 303 // Skip non main world contexts. 304 if (worldId) 305 return; 306 if (WebCore::LocalFrame* frame = webframe->frame()) 307 frame->script().setContextDebugId(m_debuggerId); 308 } 309 310 bool WebDevToolsAgentImpl::handleInputEvent(WebCore::Page* page, const WebInputEvent& inputEvent) 311 { 312 if (!m_attached && !m_generatingEvent) 313 return false; 314 315 // FIXME: This workaround is required for touch emulation on Mac, where 316 // compositor-side pinch handling is not enabled. See http://crbug.com/138003. 317 bool isPinch = inputEvent.type == WebInputEvent::GesturePinchBegin || inputEvent.type == WebInputEvent::GesturePinchUpdate || inputEvent.type == WebInputEvent::GesturePinchEnd; 318 if (isPinch && m_touchEventEmulationEnabled && m_emulateViewportEnabled) { 319 FrameView* frameView = page->deprecatedLocalMainFrame()->view(); 320 PlatformGestureEventBuilder gestureEvent(frameView, *static_cast<const WebGestureEvent*>(&inputEvent)); 321 float pageScaleFactor = page->pageScaleFactor(); 322 if (gestureEvent.type() == PlatformEvent::GesturePinchBegin) { 323 m_lastPinchAnchorCss = adoptPtr(new WebCore::IntPoint(frameView->scrollPosition() + gestureEvent.position())); 324 m_lastPinchAnchorDip = adoptPtr(new WebCore::IntPoint(gestureEvent.position())); 325 m_lastPinchAnchorDip->scale(pageScaleFactor, pageScaleFactor); 326 } 327 if (gestureEvent.type() == PlatformEvent::GesturePinchUpdate && m_lastPinchAnchorCss) { 328 float newPageScaleFactor = pageScaleFactor * gestureEvent.scale(); 329 WebCore::IntPoint anchorCss(*m_lastPinchAnchorDip.get()); 330 anchorCss.scale(1.f / newPageScaleFactor, 1.f / newPageScaleFactor); 331 m_webViewImpl->setPageScaleFactor(newPageScaleFactor); 332 m_webViewImpl->setMainFrameScrollOffset(*m_lastPinchAnchorCss.get() - toIntSize(anchorCss)); 333 } 334 if (gestureEvent.type() == PlatformEvent::GesturePinchEnd) { 335 m_lastPinchAnchorCss.clear(); 336 m_lastPinchAnchorDip.clear(); 337 } 338 return true; 339 } 340 341 InspectorController* ic = inspectorController(); 342 if (!ic) 343 return false; 344 345 if (WebInputEvent::isGestureEventType(inputEvent.type) && inputEvent.type == WebInputEvent::GestureTap) { 346 // Only let GestureTab in (we only need it and we know PlatformGestureEventBuilder supports it). 347 PlatformGestureEvent gestureEvent = PlatformGestureEventBuilder(page->deprecatedLocalMainFrame()->view(), *static_cast<const WebGestureEvent*>(&inputEvent)); 348 return ic->handleGestureEvent(toLocalFrame(page->mainFrame()), gestureEvent); 349 } 350 if (WebInputEvent::isMouseEventType(inputEvent.type) && inputEvent.type != WebInputEvent::MouseEnter) { 351 // PlatformMouseEventBuilder does not work with MouseEnter type, so we filter it out manually. 352 PlatformMouseEvent mouseEvent = PlatformMouseEventBuilder(page->deprecatedLocalMainFrame()->view(), *static_cast<const WebMouseEvent*>(&inputEvent)); 353 return ic->handleMouseEvent(toLocalFrame(page->mainFrame()), mouseEvent); 354 } 355 if (WebInputEvent::isTouchEventType(inputEvent.type)) { 356 PlatformTouchEvent touchEvent = PlatformTouchEventBuilder(page->deprecatedLocalMainFrame()->view(), *static_cast<const WebTouchEvent*>(&inputEvent)); 357 return ic->handleTouchEvent(toLocalFrame(page->mainFrame()), touchEvent); 358 } 359 if (WebInputEvent::isKeyboardEventType(inputEvent.type)) { 360 PlatformKeyboardEvent keyboardEvent = PlatformKeyboardEventBuilder(*static_cast<const WebKeyboardEvent*>(&inputEvent)); 361 return ic->handleKeyboardEvent(page->deprecatedLocalMainFrame(), keyboardEvent); 362 } 363 return false; 364 } 365 366 void WebDevToolsAgentImpl::setDeviceMetricsOverride(int width, int height, float deviceScaleFactor, bool emulateViewport, bool fitWindow) 367 { 368 if (!m_deviceMetricsEnabled) { 369 m_deviceMetricsEnabled = true; 370 m_webViewImpl->setBackgroundColorOverride(Color::darkGray); 371 } 372 if (emulateViewport) 373 enableViewportEmulation(); 374 else 375 disableViewportEmulation(); 376 377 WebDeviceEmulationParams params; 378 params.screenPosition = emulateViewport ? WebDeviceEmulationParams::Mobile : WebDeviceEmulationParams::Desktop; 379 params.deviceScaleFactor = deviceScaleFactor; 380 params.viewSize = WebSize(width, height); 381 params.fitToView = fitWindow; 382 params.viewInsets = WebSize(0, 0); 383 m_client->enableDeviceEmulation(params); 384 } 385 386 void WebDevToolsAgentImpl::clearDeviceMetricsOverride() 387 { 388 if (m_deviceMetricsEnabled) { 389 m_deviceMetricsEnabled = false; 390 m_webViewImpl->setBackgroundColorOverride(Color::transparent); 391 disableViewportEmulation(); 392 m_client->disableDeviceEmulation(); 393 } 394 } 395 396 void WebDevToolsAgentImpl::setTouchEventEmulationEnabled(bool enabled) 397 { 398 m_client->setTouchEventEmulationEnabled(enabled, enabled); 399 m_touchEventEmulationEnabled = enabled; 400 updatePageScaleFactorLimits(); 401 } 402 403 void WebDevToolsAgentImpl::enableViewportEmulation() 404 { 405 if (m_emulateViewportEnabled) 406 return; 407 m_emulateViewportEnabled = true; 408 m_isOverlayScrollbarsEnabled = RuntimeEnabledFeatures::overlayScrollbarsEnabled(); 409 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true); 410 m_originalViewportEnabled = RuntimeEnabledFeatures::cssViewportEnabled(); 411 RuntimeEnabledFeatures::setCSSViewportEnabled(true); 412 m_webViewImpl->settings()->setViewportEnabled(true); 413 m_webViewImpl->settings()->setViewportMetaEnabled(true); 414 m_webViewImpl->settings()->setShrinksViewportContentToFit(true); 415 m_webViewImpl->setIgnoreViewportTagScaleLimits(true); 416 m_webViewImpl->setZoomFactorOverride(1); 417 // FIXME: with touch and viewport emulation enabled, we may want to disable overscroll navigation. 418 updatePageScaleFactorLimits(); 419 } 420 421 void WebDevToolsAgentImpl::disableViewportEmulation() 422 { 423 if (!m_emulateViewportEnabled) 424 return; 425 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_isOverlayScrollbarsEnabled); 426 RuntimeEnabledFeatures::setCSSViewportEnabled(m_originalViewportEnabled); 427 m_webViewImpl->settings()->setViewportEnabled(false); 428 m_webViewImpl->settings()->setViewportMetaEnabled(false); 429 m_webViewImpl->settings()->setShrinksViewportContentToFit(false); 430 m_webViewImpl->setIgnoreViewportTagScaleLimits(false); 431 m_webViewImpl->setZoomFactorOverride(0); 432 m_emulateViewportEnabled = false; 433 updatePageScaleFactorLimits(); 434 } 435 436 void WebDevToolsAgentImpl::updatePageScaleFactorLimits() 437 { 438 if (m_touchEventEmulationEnabled || m_emulateViewportEnabled) { 439 if (!m_pageScaleLimitsOverriden) { 440 m_originalMinimumPageScaleFactor = m_webViewImpl->minimumPageScaleFactor(); 441 m_originalMaximumPageScaleFactor = m_webViewImpl->maximumPageScaleFactor(); 442 m_pageScaleLimitsOverriden = true; 443 } 444 m_webViewImpl->setPageScaleFactorLimits(1, 4); 445 } else { 446 if (m_pageScaleLimitsOverriden) { 447 m_pageScaleLimitsOverriden = false; 448 m_webViewImpl->setPageScaleFactorLimits(m_originalMinimumPageScaleFactor, m_originalMaximumPageScaleFactor); 449 } 450 } 451 } 452 453 void WebDevToolsAgentImpl::getAllocatedObjects(HashSet<const void*>& set) 454 { 455 class CountingVisitor : public WebDevToolsAgentClient::AllocatedObjectVisitor { 456 public: 457 CountingVisitor() : m_totalObjectsCount(0) 458 { 459 } 460 461 virtual bool visitObject(const void* ptr) 462 { 463 ++m_totalObjectsCount; 464 return true; 465 } 466 size_t totalObjectsCount() const 467 { 468 return m_totalObjectsCount; 469 } 470 471 private: 472 size_t m_totalObjectsCount; 473 }; 474 475 CountingVisitor counter; 476 m_client->visitAllocatedObjects(&counter); 477 478 class PointerCollector : public WebDevToolsAgentClient::AllocatedObjectVisitor { 479 public: 480 explicit PointerCollector(size_t maxObjectsCount) 481 : m_maxObjectsCount(maxObjectsCount) 482 , m_index(0) 483 , m_success(true) 484 , m_pointers(new const void*[maxObjectsCount]) 485 { 486 } 487 virtual ~PointerCollector() 488 { 489 delete[] m_pointers; 490 } 491 virtual bool visitObject(const void* ptr) 492 { 493 if (m_index == m_maxObjectsCount) { 494 m_success = false; 495 return false; 496 } 497 m_pointers[m_index++] = ptr; 498 return true; 499 } 500 501 bool success() const { return m_success; } 502 503 void copyTo(HashSet<const void*>& set) 504 { 505 for (size_t i = 0; i < m_index; i++) 506 set.add(m_pointers[i]); 507 } 508 509 private: 510 const size_t m_maxObjectsCount; 511 size_t m_index; 512 bool m_success; 513 const void** m_pointers; 514 }; 515 516 // Double size to allow room for all objects that may have been allocated 517 // since we counted them. 518 size_t estimatedMaxObjectsCount = counter.totalObjectsCount() * 2; 519 while (true) { 520 PointerCollector collector(estimatedMaxObjectsCount); 521 m_client->visitAllocatedObjects(&collector); 522 if (collector.success()) { 523 collector.copyTo(set); 524 break; 525 } 526 estimatedMaxObjectsCount *= 2; 527 } 528 } 529 530 void WebDevToolsAgentImpl::dumpUncountedAllocatedObjects(const HashMap<const void*, size_t>& map) 531 { 532 class InstrumentedObjectSizeProvider : public WebDevToolsAgentClient::InstrumentedObjectSizeProvider { 533 public: 534 InstrumentedObjectSizeProvider(const HashMap<const void*, size_t>& map) : m_map(map) { } 535 virtual size_t objectSize(const void* ptr) const 536 { 537 HashMap<const void*, size_t>::const_iterator i = m_map.find(ptr); 538 return i == m_map.end() ? 0 : i->value; 539 } 540 541 private: 542 const HashMap<const void*, size_t>& m_map; 543 }; 544 545 InstrumentedObjectSizeProvider provider(map); 546 m_client->dumpUncountedAllocatedObjects(&provider); 547 } 548 549 void WebDevToolsAgentImpl::setTraceEventCallback(const String& categoryFilter, TraceEventCallback callback) 550 { 551 m_client->setTraceEventCallback(categoryFilter, callback); 552 } 553 554 void WebDevToolsAgentImpl::resetTraceEventCallback() 555 { 556 m_client->resetTraceEventCallback(); 557 } 558 559 void WebDevToolsAgentImpl::enableTracing(const String& categoryFilter) 560 { 561 m_client->enableTracing(categoryFilter); 562 } 563 564 void WebDevToolsAgentImpl::disableTracing() 565 { 566 m_client->disableTracing(); 567 } 568 569 void WebDevToolsAgentImpl::startGPUEventsRecording() 570 { 571 m_client->startGPUEventsRecording(); 572 } 573 574 void WebDevToolsAgentImpl::stopGPUEventsRecording() 575 { 576 m_client->stopGPUEventsRecording(); 577 } 578 579 void WebDevToolsAgentImpl::processGPUEvent(const GPUEvent& event) 580 { 581 if (InspectorController* ic = inspectorController()) 582 ic->processGPUEvent(event.timestamp, event.phase, event.foreign, event.usedGPUMemoryBytes, event.limitGPUMemoryBytes); 583 } 584 585 void WebDevToolsAgentImpl::dispatchKeyEvent(const PlatformKeyboardEvent& event) 586 { 587 if (!m_webViewImpl->page()->focusController().isFocused()) 588 m_webViewImpl->setFocus(true); 589 590 m_generatingEvent = true; 591 WebKeyboardEvent webEvent = WebKeyboardEventBuilder(event); 592 if (!webEvent.keyIdentifier[0] && webEvent.type != WebInputEvent::Char) 593 webEvent.setKeyIdentifierFromWindowsKeyCode(); 594 m_webViewImpl->handleInputEvent(webEvent); 595 m_generatingEvent = false; 596 } 597 598 void WebDevToolsAgentImpl::dispatchMouseEvent(const PlatformMouseEvent& event) 599 { 600 if (!m_webViewImpl->page()->focusController().isFocused()) 601 m_webViewImpl->setFocus(true); 602 603 m_generatingEvent = true; 604 WebMouseEvent webEvent = WebMouseEventBuilder(m_webViewImpl->mainFrameImpl()->frameView(), event); 605 m_webViewImpl->handleInputEvent(webEvent); 606 m_generatingEvent = false; 607 } 608 609 void WebDevToolsAgentImpl::dispatchOnInspectorBackend(const WebString& message) 610 { 611 inspectorController()->dispatchMessageFromFrontend(message); 612 } 613 614 void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& point) 615 { 616 m_webViewImpl->inspectElementAt(point); 617 } 618 619 InspectorController* WebDevToolsAgentImpl::inspectorController() 620 { 621 if (Page* page = m_webViewImpl->page()) 622 return &page->inspectorController(); 623 return 0; 624 } 625 626 LocalFrame* WebDevToolsAgentImpl::mainFrame() 627 { 628 if (Page* page = m_webViewImpl->page()) 629 return page->deprecatedLocalMainFrame(); 630 return 0; 631 } 632 633 // WebPageOverlay 634 void WebDevToolsAgentImpl::paintPageOverlay(WebCanvas* canvas) 635 { 636 InspectorController* ic = inspectorController(); 637 if (ic) { 638 GraphicsContext context(canvas); 639 context.setCertainlyOpaque(false); 640 ic->drawHighlight(context); 641 } 642 } 643 644 void WebDevToolsAgentImpl::highlight() 645 { 646 m_webViewImpl->addPageOverlay(this, OverlayZOrders::highlight); 647 } 648 649 void WebDevToolsAgentImpl::hideHighlight() 650 { 651 m_webViewImpl->removePageOverlay(this); 652 } 653 654 void WebDevToolsAgentImpl::sendMessageToFrontend(PassRefPtr<WebCore::JSONObject> message) 655 { 656 m_frontendMessageQueue.append(message); 657 } 658 659 void WebDevToolsAgentImpl::flush() 660 { 661 flushPendingFrontendMessages(); 662 } 663 664 void WebDevToolsAgentImpl::updateInspectorStateCookie(const String& state) 665 { 666 m_client->saveAgentRuntimeState(state); 667 } 668 669 void WebDevToolsAgentImpl::setProcessId(long processId) 670 { 671 inspectorController()->setProcessId(processId); 672 } 673 674 void WebDevToolsAgentImpl::setLayerTreeId(int layerTreeId) 675 { 676 m_layerTreeId = layerTreeId; 677 inspectorController()->setLayerTreeId(layerTreeId); 678 } 679 680 void WebDevToolsAgentImpl::evaluateInWebInspector(long callId, const WebString& script) 681 { 682 InspectorController* ic = inspectorController(); 683 ic->evaluateForTestInFrontend(callId, script); 684 } 685 686 void WebDevToolsAgentImpl::flushPendingFrontendMessages() 687 { 688 InspectorController* ic = inspectorController(); 689 ic->flushPendingFrontendMessages(); 690 691 for (size_t i = 0; i < m_frontendMessageQueue.size(); ++i) 692 m_client->sendMessageToInspectorFrontend(m_frontendMessageQueue[i]->toJSONString()); 693 m_frontendMessageQueue.clear(); 694 } 695 696 void WebDevToolsAgentImpl::willProcessTask() 697 { 698 if (!m_attached) 699 return; 700 if (InspectorController* ic = inspectorController()) 701 ic->willProcessTask(); 702 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Program"); 703 } 704 705 void WebDevToolsAgentImpl::didProcessTask() 706 { 707 if (!m_attached) 708 return; 709 if (InspectorController* ic = inspectorController()) 710 ic->didProcessTask(); 711 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Program"); 712 flushPendingFrontendMessages(); 713 } 714 715 void WebDevToolsAgent::interruptAndDispatch(MessageDescriptor* rawDescriptor) 716 { 717 // rawDescriptor can't be a PassOwnPtr because interruptAndDispatch is a WebKit API function. 718 OwnPtr<MessageDescriptor> descriptor = adoptPtr(rawDescriptor); 719 OwnPtr<DebuggerTask> task = adoptPtr(new DebuggerTask(descriptor.release())); 720 PageScriptDebugServer::interruptAndRun(task.release()); 721 } 722 723 bool WebDevToolsAgent::shouldInterruptForMessage(const WebString& message) 724 { 725 String commandName; 726 if (!InspectorBackendDispatcher::getCommandName(message, &commandName)) 727 return false; 728 return commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_pauseCmd) 729 || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointCmd) 730 || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointByUrlCmd) 731 || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_removeBreakpointCmd) 732 || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointsActiveCmd); 733 } 734 735 void WebDevToolsAgent::processPendingMessages() 736 { 737 PageScriptDebugServer::shared().runPendingTasks(); 738 } 739 740 } // namespace blink 741