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 "WebDevToolsAgentImpl.h" 33 34 #include "InspectorBackendDispatcher.h" 35 #include "InspectorFrontend.h" 36 #include "InspectorProtocolVersion.h" 37 #include "WebDataSource.h" 38 #include "WebDevToolsAgentClient.h" 39 #include "WebFrameImpl.h" 40 #include "WebInputEventConversion.h" 41 #include "WebMemoryUsageInfo.h" 42 #include "WebViewClient.h" 43 #include "WebViewImpl.h" 44 #include "bindings/v8/PageScriptDebugServer.h" 45 #include "bindings/v8/ScriptController.h" 46 #include "bindings/v8/V8Binding.h" 47 #include "bindings/v8/V8Utilities.h" 48 #include "core/dom/ExceptionCode.h" 49 #include "core/inspector/InjectedScriptHost.h" 50 #include "core/inspector/InspectorController.h" 51 #include "core/loader/cache/MemoryCache.h" 52 #include "core/page/Frame.h" 53 #include "core/page/FrameView.h" 54 #include "core/page/Page.h" 55 #include "core/page/PageGroup.h" 56 #include "core/platform/JSONValues.h" 57 #include "core/platform/graphics/GraphicsContext.h" 58 #include "core/platform/network/ResourceError.h" 59 #include "core/platform/network/ResourceRequest.h" 60 #include "core/platform/network/ResourceResponse.h" 61 #include "core/rendering/RenderView.h" 62 #include "public/platform/Platform.h" 63 #include "public/platform/WebRect.h" 64 #include "public/platform/WebString.h" 65 #include "public/platform/WebURL.h" 66 #include "public/platform/WebURLError.h" 67 #include "public/platform/WebURLRequest.h" 68 #include "public/platform/WebURLResponse.h" 69 #include "wtf/CurrentTime.h" 70 #include "wtf/MathExtras.h" 71 #include "wtf/Noncopyable.h" 72 #include "wtf/OwnPtr.h" 73 #include "wtf/text/WTFString.h" 74 75 using namespace WebCore; 76 using namespace std; 77 78 namespace OverlayZOrders { 79 // Use 99 as a big z-order number so that highlight is above other overlays. 80 static const int highlight = 99; 81 } 82 83 namespace WebKit { 84 85 class ClientMessageLoopAdapter : public PageScriptDebugServer::ClientMessageLoop { 86 public: 87 static void ensureClientMessageLoopCreated(WebDevToolsAgentClient* client) 88 { 89 if (s_instance) 90 return; 91 OwnPtr<ClientMessageLoopAdapter> instance = adoptPtr(new ClientMessageLoopAdapter(adoptPtr(client->createClientMessageLoop()))); 92 s_instance = instance.get(); 93 PageScriptDebugServer::shared().setClientMessageLoop(instance.release()); 94 } 95 96 static void inspectedViewClosed(WebViewImpl* view) 97 { 98 if (s_instance) 99 s_instance->m_frozenViews.remove(view); 100 } 101 102 static void didNavigate() 103 { 104 // Release render thread if necessary. 105 if (s_instance && s_instance->m_running) 106 PageScriptDebugServer::shared().continueProgram(); 107 } 108 109 private: 110 ClientMessageLoopAdapter(PassOwnPtr<WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop> messageLoop) 111 : m_running(false) 112 , m_messageLoop(messageLoop) { } 113 114 115 virtual void run(Page* page) 116 { 117 if (m_running) 118 return; 119 m_running = true; 120 121 Vector<WebViewImpl*> views; 122 123 // 1. Disable input events. 124 HashSet<Page*>::const_iterator end = page->group().pages().end(); 125 for (HashSet<Page*>::const_iterator it = page->group().pages().begin(); it != end; ++it) { 126 WebViewImpl* view = WebViewImpl::fromPage(*it); 127 if (!view) 128 continue; 129 m_frozenViews.add(view); 130 views.append(view); 131 view->setIgnoreInputEvents(true); 132 } 133 134 // 2. Disable active objects 135 WebView::willEnterModalLoop(); 136 137 // 3. Process messages until quitNow is called. 138 m_messageLoop->run(); 139 140 // 4. Resume active objects 141 WebView::didExitModalLoop(); 142 143 // 5. Resume input events. 144 for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) { 145 if (m_frozenViews.contains(*it)) { 146 // The view was not closed during the dispatch. 147 (*it)->setIgnoreInputEvents(false); 148 } 149 } 150 151 // 6. All views have been resumed, clear the set. 152 m_frozenViews.clear(); 153 154 m_running = false; 155 } 156 157 virtual void quitNow() 158 { 159 m_messageLoop->quitNow(); 160 } 161 162 bool m_running; 163 OwnPtr<WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop> m_messageLoop; 164 typedef HashSet<WebViewImpl*> FrozenViewsSet; 165 FrozenViewsSet m_frozenViews; 166 // FIXME: The ownership model for s_instance is somewhat complicated. Can we make this simpler? 167 static ClientMessageLoopAdapter* s_instance; 168 }; 169 170 ClientMessageLoopAdapter* ClientMessageLoopAdapter::s_instance = 0; 171 172 class DebuggerTask : public PageScriptDebugServer::Task { 173 public: 174 DebuggerTask(PassOwnPtr<WebDevToolsAgent::MessageDescriptor> descriptor) 175 : m_descriptor(descriptor) 176 { 177 } 178 179 virtual ~DebuggerTask() { } 180 virtual void run() 181 { 182 if (WebDevToolsAgent* webagent = m_descriptor->agent()) 183 webagent->dispatchOnInspectorBackend(m_descriptor->message()); 184 } 185 186 private: 187 OwnPtr<WebDevToolsAgent::MessageDescriptor> m_descriptor; 188 }; 189 190 class DeviceMetricsSupport { 191 public: 192 DeviceMetricsSupport(WebViewImpl* webView) 193 : m_webView(webView) 194 , m_fitWindow(false) 195 , m_originalZoomFactor(0) 196 { 197 } 198 199 ~DeviceMetricsSupport() 200 { 201 restore(); 202 } 203 204 void setDeviceMetrics(int width, int height, float textZoomFactor, bool fitWindow) 205 { 206 WebCore::FrameView* view = frameView(); 207 if (!view) 208 return; 209 210 m_emulatedFrameSize = WebSize(width, height); 211 m_fitWindow = fitWindow; 212 m_originalZoomFactor = 0; 213 m_webView->setTextZoomFactor(textZoomFactor); 214 applySizeOverrideInternal(view, FitWindowAllowed); 215 autoZoomPageToFitWidth(view->frame()); 216 217 m_webView->sendResizeEventAndRepaint(); 218 } 219 220 void autoZoomPageToFitWidthOnNavigation(Frame* frame) 221 { 222 FrameView* frameView = frame->view(); 223 applySizeOverrideInternal(frameView, FitWindowNotAllowed); 224 m_originalZoomFactor = 0; 225 applySizeOverrideInternal(frameView, FitWindowAllowed); 226 autoZoomPageToFitWidth(frame); 227 } 228 229 void autoZoomPageToFitWidth(Frame* frame) 230 { 231 if (!frame) 232 return; 233 234 frame->setTextZoomFactor(m_webView->textZoomFactor()); 235 ensureOriginalZoomFactor(frame->view()); 236 Document* document = frame->document(); 237 float numerator = document->renderView() ? document->renderView()->viewWidth() : frame->view()->contentsWidth(); 238 float factor = m_originalZoomFactor * (numerator / m_emulatedFrameSize.width); 239 frame->setPageAndTextZoomFactors(factor, m_webView->textZoomFactor()); 240 document->styleResolverChanged(RecalcStyleImmediately); 241 document->updateLayout(); 242 } 243 244 void webViewResized() 245 { 246 if (!m_fitWindow) 247 return; 248 249 applySizeOverrideIfNecessary(); 250 autoZoomPageToFitWidth(m_webView->mainFrameImpl()->frame()); 251 } 252 253 void applySizeOverrideIfNecessary() 254 { 255 FrameView* view = frameView(); 256 if (!view) 257 return; 258 259 applySizeOverrideInternal(view, FitWindowAllowed); 260 } 261 262 private: 263 enum FitWindowFlag { FitWindowAllowed, FitWindowNotAllowed }; 264 265 void ensureOriginalZoomFactor(FrameView* frameView) 266 { 267 if (m_originalZoomFactor) 268 return; 269 270 m_webView->setPageScaleFactor(1, WebPoint()); 271 m_webView->setZoomLevel(0); 272 WebSize scaledEmulatedSize = scaledEmulatedFrameSize(frameView); 273 double denominator = frameView->contentsWidth(); 274 if (!denominator) 275 denominator = 1; 276 m_originalZoomFactor = static_cast<double>(scaledEmulatedSize.width) / denominator; 277 } 278 279 void restore() 280 { 281 WebCore::FrameView* view = frameView(); 282 if (!view) 283 return; 284 285 m_webView->setZoomLevel(0); 286 m_webView->setTextZoomFactor(1); 287 view->setHorizontalScrollbarLock(false); 288 view->setVerticalScrollbarLock(false); 289 view->setScrollbarModes(ScrollbarAuto, ScrollbarAuto, false, false); 290 view->setFrameRect(IntRect(IntPoint(), IntSize(m_webView->size()))); 291 m_webView->sendResizeEventAndRepaint(); 292 } 293 294 WebSize scaledEmulatedFrameSize(FrameView* frameView) 295 { 296 if (!m_fitWindow) 297 return m_emulatedFrameSize; 298 299 WebSize scrollbarDimensions = forcedScrollbarDimensions(frameView); 300 301 int overrideWidth = m_emulatedFrameSize.width; 302 int overrideHeight = m_emulatedFrameSize.height; 303 304 WebSize webViewSize = m_webView->size(); 305 int availableViewWidth = max(webViewSize.width - scrollbarDimensions.width, 1); 306 int availableViewHeight = max(webViewSize.height - scrollbarDimensions.height, 1); 307 308 double widthRatio = static_cast<double>(overrideWidth) / availableViewWidth; 309 double heightRatio = static_cast<double>(overrideHeight) / availableViewHeight; 310 double dimensionRatio = max(widthRatio, heightRatio); 311 overrideWidth = static_cast<int>(ceil(static_cast<double>(overrideWidth) / dimensionRatio)); 312 overrideHeight = static_cast<int>(ceil(static_cast<double>(overrideHeight) / dimensionRatio)); 313 314 return WebSize(overrideWidth, overrideHeight); 315 } 316 317 WebSize forcedScrollbarDimensions(FrameView* frameView) 318 { 319 frameView->setScrollbarModes(ScrollbarAlwaysOn, ScrollbarAlwaysOn, true, true); 320 321 int verticalScrollbarWidth = 0; 322 int horizontalScrollbarHeight = 0; 323 if (Scrollbar* verticalBar = frameView->verticalScrollbar()) 324 verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0; 325 if (Scrollbar* horizontalBar = frameView->horizontalScrollbar()) 326 horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0; 327 return WebSize(verticalScrollbarWidth, horizontalScrollbarHeight); 328 } 329 330 void applySizeOverrideInternal(FrameView* frameView, FitWindowFlag fitWindowFlag) 331 { 332 WebSize scrollbarDimensions = forcedScrollbarDimensions(frameView); 333 334 WebSize effectiveEmulatedSize = (fitWindowFlag == FitWindowAllowed) ? scaledEmulatedFrameSize(frameView) : m_emulatedFrameSize; 335 int overrideWidth = effectiveEmulatedSize.width + scrollbarDimensions.width; 336 int overrideHeight = effectiveEmulatedSize.height + scrollbarDimensions.height; 337 338 if (IntSize(overrideWidth, overrideHeight) != frameView->size()) 339 frameView->resize(overrideWidth, overrideHeight); 340 341 Document* doc = frameView->frame()->document(); 342 doc->styleResolverChanged(RecalcStyleImmediately); 343 doc->updateLayout(); 344 } 345 346 WebCore::FrameView* frameView() 347 { 348 return m_webView->mainFrameImpl() ? m_webView->mainFrameImpl()->frameView() : 0; 349 } 350 351 WebViewImpl* m_webView; 352 WebSize m_emulatedFrameSize; 353 bool m_fitWindow; 354 double m_originalZoomFactor; 355 }; 356 357 WebDevToolsAgentImpl::WebDevToolsAgentImpl( 358 WebViewImpl* webViewImpl, 359 WebDevToolsAgentClient* client) 360 : m_hostId(client->hostIdentifier()) 361 , m_client(client) 362 , m_webViewImpl(webViewImpl) 363 , m_attached(false) 364 { 365 ASSERT(m_hostId > 0); 366 ClientMessageLoopAdapter::ensureClientMessageLoopCreated(m_client); 367 } 368 369 WebDevToolsAgentImpl::~WebDevToolsAgentImpl() 370 { 371 ClientMessageLoopAdapter::inspectedViewClosed(m_webViewImpl); 372 if (m_attached) 373 WebKit::Platform::current()->currentThread()->removeTaskObserver(this); 374 } 375 376 void WebDevToolsAgentImpl::attach() 377 { 378 if (m_attached) 379 return; 380 381 inspectorController()->connectFrontend(this); 382 inspectorController()->webViewResized(m_webViewImpl->size()); 383 WebKit::Platform::current()->currentThread()->addTaskObserver(this); 384 m_attached = true; 385 } 386 387 void WebDevToolsAgentImpl::reattach(const WebString& savedState) 388 { 389 if (m_attached) 390 return; 391 392 inspectorController()->reuseFrontend(this, savedState); 393 WebKit::Platform::current()->currentThread()->addTaskObserver(this); 394 m_attached = true; 395 } 396 397 void WebDevToolsAgentImpl::detach() 398 { 399 WebKit::Platform::current()->currentThread()->removeTaskObserver(this); 400 401 // Prevent controller from sending messages to the frontend. 402 InspectorController* ic = inspectorController(); 403 ic->disconnectFrontend(); 404 ic->hideHighlight(); 405 m_attached = false; 406 } 407 408 void WebDevToolsAgentImpl::didNavigate() 409 { 410 ClientMessageLoopAdapter::didNavigate(); 411 } 412 413 void WebDevToolsAgentImpl::didBeginFrame() 414 { 415 if (InspectorController* ic = inspectorController()) 416 ic->didBeginFrame(); 417 } 418 419 void WebDevToolsAgentImpl::didCancelFrame() 420 { 421 if (InspectorController* ic = inspectorController()) 422 ic->didCancelFrame(); 423 } 424 425 void WebDevToolsAgentImpl::willComposite() 426 { 427 if (InspectorController* ic = inspectorController()) 428 ic->willComposite(); 429 } 430 431 void WebDevToolsAgentImpl::didComposite() 432 { 433 if (InspectorController* ic = inspectorController()) 434 ic->didComposite(); 435 } 436 437 void WebDevToolsAgentImpl::didCreateScriptContext(WebFrameImpl* webframe, int worldId) 438 { 439 // Skip non main world contexts. 440 if (worldId) 441 return; 442 if (WebCore::Frame* frame = webframe->frame()) 443 frame->script()->setContextDebugId(m_hostId); 444 } 445 446 void WebDevToolsAgentImpl::mainFrameViewCreated(WebFrameImpl* webFrame) 447 { 448 if (m_metricsSupport) 449 m_metricsSupport->applySizeOverrideIfNecessary(); 450 } 451 452 bool WebDevToolsAgentImpl::metricsOverridden() 453 { 454 return !!m_metricsSupport; 455 } 456 457 void WebDevToolsAgentImpl::webViewResized(const WebSize& size) 458 { 459 if (m_metricsSupport) 460 m_metricsSupport->webViewResized(); 461 if (InspectorController* ic = inspectorController()) 462 ic->webViewResized(m_metricsSupport ? IntSize(size.width, size.height) : IntSize()); 463 } 464 465 bool WebDevToolsAgentImpl::handleInputEvent(WebCore::Page* page, const WebInputEvent& inputEvent) 466 { 467 if (!m_attached) 468 return false; 469 470 InspectorController* ic = inspectorController(); 471 if (!ic) 472 return false; 473 474 if (WebInputEvent::isGestureEventType(inputEvent.type) && inputEvent.type == WebInputEvent::GestureTap) { 475 // Only let GestureTab in (we only need it and we know PlatformGestureEventBuilder supports it). 476 PlatformGestureEvent gestureEvent = PlatformGestureEventBuilder(page->mainFrame()->view(), *static_cast<const WebGestureEvent*>(&inputEvent)); 477 return ic->handleGestureEvent(page->mainFrame(), gestureEvent); 478 } 479 if (WebInputEvent::isMouseEventType(inputEvent.type) && inputEvent.type != WebInputEvent::MouseEnter) { 480 // PlatformMouseEventBuilder does not work with MouseEnter type, so we filter it out manually. 481 PlatformMouseEvent mouseEvent = PlatformMouseEventBuilder(page->mainFrame()->view(), *static_cast<const WebMouseEvent*>(&inputEvent)); 482 return ic->handleMouseEvent(page->mainFrame(), mouseEvent); 483 } 484 if (WebInputEvent::isTouchEventType(inputEvent.type)) { 485 PlatformTouchEvent touchEvent = PlatformTouchEventBuilder(page->mainFrame()->view(), *static_cast<const WebTouchEvent*>(&inputEvent)); 486 return ic->handleTouchEvent(page->mainFrame(), touchEvent); 487 } 488 return false; 489 } 490 491 void WebDevToolsAgentImpl::overrideDeviceMetrics(int width, int height, float fontScaleFactor, bool fitWindow) 492 { 493 if (!width && !height) { 494 if (m_metricsSupport) 495 m_metricsSupport.clear(); 496 if (InspectorController* ic = inspectorController()) 497 ic->webViewResized(IntSize()); 498 return; 499 } 500 501 if (!m_metricsSupport) 502 m_metricsSupport = adoptPtr(new DeviceMetricsSupport(m_webViewImpl)); 503 504 m_metricsSupport->setDeviceMetrics(width, height, fontScaleFactor, fitWindow); 505 if (InspectorController* ic = inspectorController()) { 506 WebSize size = m_webViewImpl->size(); 507 ic->webViewResized(IntSize(size.width, size.height)); 508 } 509 } 510 511 void WebDevToolsAgentImpl::autoZoomPageToFitWidth() 512 { 513 if (m_metricsSupport) 514 m_metricsSupport->autoZoomPageToFitWidthOnNavigation(m_webViewImpl->mainFrameImpl()->frame()); 515 } 516 517 void WebDevToolsAgentImpl::getAllocatedObjects(HashSet<const void*>& set) 518 { 519 class CountingVisitor : public WebDevToolsAgentClient::AllocatedObjectVisitor { 520 public: 521 CountingVisitor() : m_totalObjectsCount(0) 522 { 523 } 524 525 virtual bool visitObject(const void* ptr) 526 { 527 ++m_totalObjectsCount; 528 return true; 529 } 530 size_t totalObjectsCount() const 531 { 532 return m_totalObjectsCount; 533 } 534 535 private: 536 size_t m_totalObjectsCount; 537 }; 538 539 CountingVisitor counter; 540 m_client->visitAllocatedObjects(&counter); 541 542 class PointerCollector : public WebDevToolsAgentClient::AllocatedObjectVisitor { 543 public: 544 explicit PointerCollector(size_t maxObjectsCount) 545 : m_maxObjectsCount(maxObjectsCount) 546 , m_index(0) 547 , m_success(true) 548 , m_pointers(new const void*[maxObjectsCount]) 549 { 550 } 551 virtual ~PointerCollector() 552 { 553 delete[] m_pointers; 554 } 555 virtual bool visitObject(const void* ptr) 556 { 557 if (m_index == m_maxObjectsCount) { 558 m_success = false; 559 return false; 560 } 561 m_pointers[m_index++] = ptr; 562 return true; 563 } 564 565 bool success() const { return m_success; } 566 567 void copyTo(HashSet<const void*>& set) 568 { 569 for (size_t i = 0; i < m_index; i++) 570 set.add(m_pointers[i]); 571 } 572 573 private: 574 const size_t m_maxObjectsCount; 575 size_t m_index; 576 bool m_success; 577 const void** m_pointers; 578 }; 579 580 // Double size to allow room for all objects that may have been allocated 581 // since we counted them. 582 size_t estimatedMaxObjectsCount = counter.totalObjectsCount() * 2; 583 while (true) { 584 PointerCollector collector(estimatedMaxObjectsCount); 585 m_client->visitAllocatedObjects(&collector); 586 if (collector.success()) { 587 collector.copyTo(set); 588 break; 589 } 590 estimatedMaxObjectsCount *= 2; 591 } 592 } 593 594 void WebDevToolsAgentImpl::dumpUncountedAllocatedObjects(const HashMap<const void*, size_t>& map) 595 { 596 class InstrumentedObjectSizeProvider : public WebDevToolsAgentClient::InstrumentedObjectSizeProvider { 597 public: 598 InstrumentedObjectSizeProvider(const HashMap<const void*, size_t>& map) : m_map(map) { } 599 virtual size_t objectSize(const void* ptr) const 600 { 601 HashMap<const void*, size_t>::const_iterator i = m_map.find(ptr); 602 return i == m_map.end() ? 0 : i->value; 603 } 604 605 private: 606 const HashMap<const void*, size_t>& m_map; 607 }; 608 609 InstrumentedObjectSizeProvider provider(map); 610 m_client->dumpUncountedAllocatedObjects(&provider); 611 } 612 613 void WebDevToolsAgentImpl::setTraceEventCallback(TraceEventCallback callback) 614 { 615 m_client->setTraceEventCallback(callback); 616 } 617 618 void WebDevToolsAgentImpl::dispatchKeyEvent(const PlatformKeyboardEvent& event) 619 { 620 WebKeyboardEvent webEvent = WebKeyboardEventBuilder(event); 621 if (!webEvent.keyIdentifier[0] && webEvent.type != WebInputEvent::Char) 622 webEvent.setKeyIdentifierFromWindowsKeyCode(); 623 m_webViewImpl->handleInputEvent(webEvent); 624 } 625 626 void WebDevToolsAgentImpl::dispatchMouseEvent(const PlatformMouseEvent& event) 627 { 628 WebMouseEvent webEvent = WebMouseEventBuilder(m_webViewImpl->mainFrameImpl()->frameView(), event); 629 m_webViewImpl->handleInputEvent(webEvent); 630 } 631 632 void WebDevToolsAgentImpl::dispatchOnInspectorBackend(const WebString& message) 633 { 634 inspectorController()->dispatchMessageFromFrontend(message); 635 } 636 637 void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& point) 638 { 639 m_webViewImpl->inspectElementAt(point); 640 } 641 642 InspectorController* WebDevToolsAgentImpl::inspectorController() 643 { 644 if (Page* page = m_webViewImpl->page()) 645 return page->inspectorController(); 646 return 0; 647 } 648 649 Frame* WebDevToolsAgentImpl::mainFrame() 650 { 651 if (Page* page = m_webViewImpl->page()) 652 return page->mainFrame(); 653 return 0; 654 } 655 656 // WebPageOverlay 657 void WebDevToolsAgentImpl::paintPageOverlay(WebCanvas* canvas) 658 { 659 InspectorController* ic = inspectorController(); 660 if (ic) { 661 GraphicsContext context(canvas); 662 context.setCertainlyOpaque(false); 663 ic->drawHighlight(context); 664 } 665 } 666 667 void WebDevToolsAgentImpl::highlight() 668 { 669 m_webViewImpl->addPageOverlay(this, OverlayZOrders::highlight); 670 } 671 672 void WebDevToolsAgentImpl::hideHighlight() 673 { 674 m_webViewImpl->removePageOverlay(this); 675 } 676 677 bool WebDevToolsAgentImpl::sendMessageToFrontend(const String& message) 678 { 679 WebDevToolsAgentImpl* devToolsAgent = static_cast<WebDevToolsAgentImpl*>(m_webViewImpl->devToolsAgent()); 680 if (!devToolsAgent) 681 return false; 682 m_client->sendMessageToInspectorFrontend(message); 683 return true; 684 } 685 686 void WebDevToolsAgentImpl::updateInspectorStateCookie(const String& state) 687 { 688 m_client->saveAgentRuntimeState(state); 689 } 690 691 void WebDevToolsAgentImpl::clearBrowserCache() 692 { 693 m_client->clearBrowserCache(); 694 } 695 696 void WebDevToolsAgentImpl::clearBrowserCookies() 697 { 698 m_client->clearBrowserCookies(); 699 } 700 701 void WebDevToolsAgentImpl::setProcessId(long processId) 702 { 703 inspectorController()->setProcessId(processId); 704 } 705 706 void WebDevToolsAgentImpl::setLayerTreeId(int layerTreeId) 707 { 708 inspectorController()->setLayerTreeId(layerTreeId); 709 } 710 711 void WebDevToolsAgentImpl::evaluateInWebInspector(long callId, const WebString& script) 712 { 713 InspectorController* ic = inspectorController(); 714 ic->evaluateForTestInFrontend(callId, script); 715 } 716 717 void WebDevToolsAgentImpl::willProcessTask() 718 { 719 if (InspectorController* ic = inspectorController()) 720 ic->willProcessTask(); 721 } 722 723 void WebDevToolsAgentImpl::didProcessTask() 724 { 725 if (InspectorController* ic = inspectorController()) 726 ic->didProcessTask(); 727 } 728 729 WebString WebDevToolsAgent::inspectorProtocolVersion() 730 { 731 return WebCore::inspectorProtocolVersion(); 732 } 733 734 bool WebDevToolsAgent::supportsInspectorProtocolVersion(const WebString& version) 735 { 736 return WebCore::supportsInspectorProtocolVersion(version); 737 } 738 739 void WebDevToolsAgent::interruptAndDispatch(MessageDescriptor* rawDescriptor) 740 { 741 // rawDescriptor can't be a PassOwnPtr because interruptAndDispatch is a WebKit API function. 742 OwnPtr<MessageDescriptor> descriptor = adoptPtr(rawDescriptor); 743 OwnPtr<DebuggerTask> task = adoptPtr(new DebuggerTask(descriptor.release())); 744 PageScriptDebugServer::interruptAndRun(task.release(), v8::Isolate::GetCurrent()); 745 } 746 747 bool WebDevToolsAgent::shouldInterruptForMessage(const WebString& message) 748 { 749 String commandName; 750 if (!InspectorBackendDispatcher::getCommandName(message, &commandName)) 751 return false; 752 return commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kDebugger_pauseCmd] 753 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kDebugger_setBreakpointCmd] 754 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kDebugger_setBreakpointByUrlCmd] 755 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kDebugger_removeBreakpointCmd] 756 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kDebugger_setBreakpointsActiveCmd] 757 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kProfiler_startCmd] 758 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kProfiler_stopCmd] 759 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kProfiler_getCPUProfileCmd] 760 || commandName == InspectorBackendDispatcher::commandNames[InspectorBackendDispatcher::kHeapProfiler_getHeapSnapshotCmd]; 761 } 762 763 void WebDevToolsAgent::processPendingMessages() 764 { 765 PageScriptDebugServer::shared().runPendingTasks(); 766 } 767 768 } // namespace WebKit 769