Home | History | Annotate | Download | only in web
      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 "RuntimeEnabledFeatures.h"
     38 #include "WebDataSource.h"
     39 #include "WebDevToolsAgentClient.h"
     40 #include "WebFrameImpl.h"
     41 #include "WebInputEventConversion.h"
     42 #include "WebMemoryUsageInfo.h"
     43 #include "WebSettings.h"
     44 #include "WebViewClient.h"
     45 #include "WebViewImpl.h"
     46 #include "bindings/v8/PageScriptDebugServer.h"
     47 #include "bindings/v8/ScriptController.h"
     48 #include "bindings/v8/V8Binding.h"
     49 #include "bindings/v8/V8Utilities.h"
     50 #include "core/dom/ExceptionCode.h"
     51 #include "core/fetch/MemoryCache.h"
     52 #include "core/frame/Frame.h"
     53 #include "core/frame/FrameView.h"
     54 #include "core/inspector/InjectedScriptHost.h"
     55 #include "core/inspector/InspectorController.h"
     56 #include "core/page/Page.h"
     57 #include "core/page/PageGroup.h"
     58 #include "core/rendering/RenderView.h"
     59 #include "platform/JSONValues.h"
     60 #include "platform/graphics/GraphicsContext.h"
     61 #include "platform/network/ResourceError.h"
     62 #include "platform/network/ResourceRequest.h"
     63 #include "platform/network/ResourceResponse.h"
     64 #include "public/platform/Platform.h"
     65 #include "public/platform/WebRect.h"
     66 #include "public/platform/WebString.h"
     67 #include "public/platform/WebURL.h"
     68 #include "public/platform/WebURLError.h"
     69 #include "public/platform/WebURLRequest.h"
     70 #include "public/platform/WebURLResponse.h"
     71 #include "wtf/CurrentTime.h"
     72 #include "wtf/MathExtras.h"
     73 #include "wtf/Noncopyable.h"
     74 #include "wtf/text/WTFString.h"
     75 
     76 using namespace WebCore;
     77 using namespace std;
     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         Vector<WebViewImpl*> views;
    123 
    124         // 1. Disable input events.
    125         HashSet<Page*>::const_iterator end =  page->group().pages().end();
    126         for (HashSet<Page*>::const_iterator it =  page->group().pages().begin(); it != end; ++it) {
    127             WebViewImpl* view = WebViewImpl::fromPage(*it);
    128             if (!view)
    129                 continue;
    130             m_frozenViews.add(view);
    131             views.append(view);
    132             view->setIgnoreInputEvents(true);
    133         }
    134 
    135         // 2. Disable active objects
    136         WebView::willEnterModalLoop();
    137 
    138         // 3. Process messages until quitNow is called.
    139         m_messageLoop->run();
    140 
    141         // 4. Resume active objects
    142         WebView::didExitModalLoop();
    143 
    144         // 5. Resume input events.
    145         for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) {
    146             if (m_frozenViews.contains(*it)) {
    147                 // The view was not closed during the dispatch.
    148                 (*it)->setIgnoreInputEvents(false);
    149             }
    150         }
    151 
    152         // 6. All views have been resumed, clear the set.
    153         m_frozenViews.clear();
    154 
    155         m_running = false;
    156     }
    157 
    158     virtual void quitNow()
    159     {
    160         m_messageLoop->quitNow();
    161     }
    162 
    163     bool m_running;
    164     OwnPtr<blink::WebDevToolsAgentClient::WebKitClientMessageLoop> m_messageLoop;
    165     typedef HashSet<WebViewImpl*> FrozenViewsSet;
    166     FrozenViewsSet m_frozenViews;
    167     // FIXME: The ownership model for s_instance is somewhat complicated. Can we make this simpler?
    168     static ClientMessageLoopAdapter* s_instance;
    169 };
    170 
    171 ClientMessageLoopAdapter* ClientMessageLoopAdapter::s_instance = 0;
    172 
    173 class DebuggerTask : public PageScriptDebugServer::Task {
    174 public:
    175     DebuggerTask(PassOwnPtr<WebDevToolsAgent::MessageDescriptor> descriptor)
    176         : m_descriptor(descriptor)
    177     {
    178     }
    179 
    180     virtual ~DebuggerTask() { }
    181     virtual void run()
    182     {
    183         if (WebDevToolsAgent* webagent = m_descriptor->agent())
    184             webagent->dispatchOnInspectorBackend(m_descriptor->message());
    185     }
    186 
    187 private:
    188     OwnPtr<WebDevToolsAgent::MessageDescriptor> m_descriptor;
    189 };
    190 
    191 WebDevToolsAgentImpl::WebDevToolsAgentImpl(
    192     WebViewImpl* webViewImpl,
    193     WebDevToolsAgentClient* client)
    194     : m_hostId(client->hostIdentifier())
    195     , m_client(client)
    196     , m_webViewImpl(webViewImpl)
    197     , m_attached(false)
    198     , m_generatingEvent(false)
    199     , m_deviceMetricsEnabled(false)
    200     , m_emulateViewportEnabled(false)
    201     , m_originalViewportEnabled(false)
    202     , m_isOverlayScrollbarsEnabled(false)
    203 {
    204     ASSERT(m_hostId > 0);
    205     ClientMessageLoopAdapter::ensureClientMessageLoopCreated(m_client);
    206 }
    207 
    208 WebDevToolsAgentImpl::~WebDevToolsAgentImpl()
    209 {
    210     ClientMessageLoopAdapter::inspectedViewClosed(m_webViewImpl);
    211     if (m_attached)
    212         blink::Platform::current()->currentThread()->removeTaskObserver(this);
    213 }
    214 
    215 void WebDevToolsAgentImpl::attach()
    216 {
    217     if (m_attached)
    218         return;
    219 
    220     inspectorController()->connectFrontend(this);
    221     inspectorController()->webViewResized(m_webViewImpl->size());
    222     blink::Platform::current()->currentThread()->addTaskObserver(this);
    223     m_attached = true;
    224 }
    225 
    226 void WebDevToolsAgentImpl::reattach(const WebString& savedState)
    227 {
    228     if (m_attached)
    229         return;
    230 
    231     inspectorController()->reuseFrontend(this, savedState);
    232     blink::Platform::current()->currentThread()->addTaskObserver(this);
    233     m_attached = true;
    234 }
    235 
    236 void WebDevToolsAgentImpl::detach()
    237 {
    238     blink::Platform::current()->currentThread()->removeTaskObserver(this);
    239 
    240     // Prevent controller from sending messages to the frontend.
    241     InspectorController* ic = inspectorController();
    242     ic->disconnectFrontend();
    243     ic->hideHighlight();
    244     m_attached = false;
    245 }
    246 
    247 void WebDevToolsAgentImpl::didNavigate()
    248 {
    249     ClientMessageLoopAdapter::didNavigate();
    250 }
    251 
    252 void WebDevToolsAgentImpl::didBeginFrame(int frameId)
    253 {
    254     if (InspectorController* ic = inspectorController())
    255         ic->didBeginFrame(frameId);
    256 }
    257 
    258 void WebDevToolsAgentImpl::didCancelFrame()
    259 {
    260     if (InspectorController* ic = inspectorController())
    261         ic->didCancelFrame();
    262 }
    263 
    264 void WebDevToolsAgentImpl::willComposite()
    265 {
    266     if (InspectorController* ic = inspectorController())
    267         ic->willComposite();
    268 }
    269 
    270 void WebDevToolsAgentImpl::didComposite()
    271 {
    272     if (InspectorController* ic = inspectorController())
    273         ic->didComposite();
    274 }
    275 
    276 void WebDevToolsAgentImpl::didCreateScriptContext(WebFrameImpl* webframe, int worldId)
    277 {
    278     // Skip non main world contexts.
    279     if (worldId)
    280         return;
    281     if (WebCore::Frame* frame = webframe->frame())
    282         frame->script().setContextDebugId(m_hostId);
    283 }
    284 
    285 void WebDevToolsAgentImpl::webViewResized(const WebSize& size)
    286 {
    287     if (InspectorController* ic = inspectorController())
    288         ic->webViewResized(IntSize());
    289 }
    290 
    291 bool WebDevToolsAgentImpl::handleInputEvent(WebCore::Page* page, const WebInputEvent& inputEvent)
    292 {
    293     if (!m_attached && !m_generatingEvent)
    294         return false;
    295 
    296     InspectorController* ic = inspectorController();
    297     if (!ic)
    298         return false;
    299 
    300     if (WebInputEvent::isGestureEventType(inputEvent.type) && inputEvent.type == WebInputEvent::GestureTap) {
    301         // Only let GestureTab in (we only need it and we know PlatformGestureEventBuilder supports it).
    302         PlatformGestureEvent gestureEvent = PlatformGestureEventBuilder(page->mainFrame()->view(), *static_cast<const WebGestureEvent*>(&inputEvent));
    303         return ic->handleGestureEvent(page->mainFrame(), gestureEvent);
    304     }
    305     if (WebInputEvent::isMouseEventType(inputEvent.type) && inputEvent.type != WebInputEvent::MouseEnter) {
    306         // PlatformMouseEventBuilder does not work with MouseEnter type, so we filter it out manually.
    307         PlatformMouseEvent mouseEvent = PlatformMouseEventBuilder(page->mainFrame()->view(), *static_cast<const WebMouseEvent*>(&inputEvent));
    308         return ic->handleMouseEvent(page->mainFrame(), mouseEvent);
    309     }
    310     if (WebInputEvent::isTouchEventType(inputEvent.type)) {
    311         PlatformTouchEvent touchEvent = PlatformTouchEventBuilder(page->mainFrame()->view(), *static_cast<const WebTouchEvent*>(&inputEvent));
    312         return ic->handleTouchEvent(page->mainFrame(), touchEvent);
    313     }
    314     if (WebInputEvent::isKeyboardEventType(inputEvent.type)) {
    315         PlatformKeyboardEvent keyboardEvent = PlatformKeyboardEventBuilder(*static_cast<const WebKeyboardEvent*>(&inputEvent));
    316         return ic->handleKeyboardEvent(page->mainFrame(), keyboardEvent);
    317     }
    318     return false;
    319 }
    320 
    321 void WebDevToolsAgentImpl::overrideDeviceMetrics(int width, int height, float deviceScaleFactor, bool emulateViewport, bool fitWindow)
    322 {
    323     if (!width && !height) {
    324         if (m_deviceMetricsEnabled) {
    325             m_deviceMetricsEnabled = false;
    326             m_webViewImpl->setBackgroundColorOverride(Color::transparent);
    327             RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_isOverlayScrollbarsEnabled);
    328             disableViewportEmulation();
    329             m_client->disableDeviceEmulation();
    330         }
    331     } else {
    332         if (!m_deviceMetricsEnabled) {
    333             m_deviceMetricsEnabled = true;
    334             m_webViewImpl->setBackgroundColorOverride(Color::darkGray);
    335             m_isOverlayScrollbarsEnabled = RuntimeEnabledFeatures::overlayScrollbarsEnabled();
    336             RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(true);
    337         }
    338         if (emulateViewport)
    339             enableViewportEmulation();
    340         else
    341             disableViewportEmulation();
    342         m_client->enableDeviceEmulation(IntRect(10, 10, width, height), IntRect(0, 0, width, height), deviceScaleFactor, fitWindow);
    343     }
    344 }
    345 
    346 void WebDevToolsAgentImpl::enableViewportEmulation()
    347 {
    348     if (m_emulateViewportEnabled)
    349         return;
    350     m_emulateViewportEnabled = true;
    351     m_originalViewportEnabled = RuntimeEnabledFeatures::cssViewportEnabled();
    352     RuntimeEnabledFeatures::setCSSViewportEnabled(true);
    353     m_webViewImpl->settings()->setViewportEnabled(true);
    354     m_webViewImpl->settings()->setViewportMetaEnabled(true);
    355     m_webViewImpl->setIgnoreViewportTagScaleLimits(true);
    356     m_webViewImpl->setPageScaleFactorLimits(-1, -1);
    357     m_webViewImpl->setZoomFactorOverride(1);
    358 }
    359 
    360 void WebDevToolsAgentImpl::disableViewportEmulation()
    361 {
    362     if (!m_emulateViewportEnabled)
    363         return;
    364     RuntimeEnabledFeatures::setCSSViewportEnabled(m_originalViewportEnabled);
    365     m_webViewImpl->settings()->setViewportEnabled(false);
    366     m_webViewImpl->settings()->setViewportMetaEnabled(false);
    367     m_webViewImpl->setIgnoreViewportTagScaleLimits(false);
    368     m_webViewImpl->setPageScaleFactorLimits(1, 1);
    369     m_webViewImpl->setZoomFactorOverride(0);
    370     m_emulateViewportEnabled = false;
    371 }
    372 
    373 void WebDevToolsAgentImpl::getAllocatedObjects(HashSet<const void*>& set)
    374 {
    375     class CountingVisitor : public WebDevToolsAgentClient::AllocatedObjectVisitor {
    376     public:
    377         CountingVisitor() : m_totalObjectsCount(0)
    378         {
    379         }
    380 
    381         virtual bool visitObject(const void* ptr)
    382         {
    383             ++m_totalObjectsCount;
    384             return true;
    385         }
    386         size_t totalObjectsCount() const
    387         {
    388             return m_totalObjectsCount;
    389         }
    390 
    391     private:
    392         size_t m_totalObjectsCount;
    393     };
    394 
    395     CountingVisitor counter;
    396     m_client->visitAllocatedObjects(&counter);
    397 
    398     class PointerCollector : public WebDevToolsAgentClient::AllocatedObjectVisitor {
    399     public:
    400         explicit PointerCollector(size_t maxObjectsCount)
    401             : m_maxObjectsCount(maxObjectsCount)
    402             , m_index(0)
    403             , m_success(true)
    404             , m_pointers(new const void*[maxObjectsCount])
    405         {
    406         }
    407         virtual ~PointerCollector()
    408         {
    409             delete[] m_pointers;
    410         }
    411         virtual bool visitObject(const void* ptr)
    412         {
    413             if (m_index == m_maxObjectsCount) {
    414                 m_success = false;
    415                 return false;
    416             }
    417             m_pointers[m_index++] = ptr;
    418             return true;
    419         }
    420 
    421         bool success() const { return m_success; }
    422 
    423         void copyTo(HashSet<const void*>& set)
    424         {
    425             for (size_t i = 0; i < m_index; i++)
    426                 set.add(m_pointers[i]);
    427         }
    428 
    429     private:
    430         const size_t m_maxObjectsCount;
    431         size_t m_index;
    432         bool m_success;
    433         const void** m_pointers;
    434     };
    435 
    436     // Double size to allow room for all objects that may have been allocated
    437     // since we counted them.
    438     size_t estimatedMaxObjectsCount = counter.totalObjectsCount() * 2;
    439     while (true) {
    440         PointerCollector collector(estimatedMaxObjectsCount);
    441         m_client->visitAllocatedObjects(&collector);
    442         if (collector.success()) {
    443             collector.copyTo(set);
    444             break;
    445         }
    446         estimatedMaxObjectsCount *= 2;
    447     }
    448 }
    449 
    450 void WebDevToolsAgentImpl::dumpUncountedAllocatedObjects(const HashMap<const void*, size_t>& map)
    451 {
    452     class InstrumentedObjectSizeProvider : public WebDevToolsAgentClient::InstrumentedObjectSizeProvider {
    453     public:
    454         InstrumentedObjectSizeProvider(const HashMap<const void*, size_t>& map) : m_map(map) { }
    455         virtual size_t objectSize(const void* ptr) const
    456         {
    457             HashMap<const void*, size_t>::const_iterator i = m_map.find(ptr);
    458             return i == m_map.end() ? 0 : i->value;
    459         }
    460 
    461     private:
    462         const HashMap<const void*, size_t>& m_map;
    463     };
    464 
    465     InstrumentedObjectSizeProvider provider(map);
    466     m_client->dumpUncountedAllocatedObjects(&provider);
    467 }
    468 
    469 void WebDevToolsAgentImpl::setTraceEventCallback(TraceEventCallback callback)
    470 {
    471     m_client->setTraceEventCallback(callback);
    472 }
    473 
    474 void WebDevToolsAgentImpl::startGPUEventsRecording()
    475 {
    476     m_client->startGPUEventsRecording();
    477 }
    478 
    479 void WebDevToolsAgentImpl::stopGPUEventsRecording()
    480 {
    481     m_client->stopGPUEventsRecording();
    482 }
    483 
    484 void WebDevToolsAgentImpl::processGPUEvent(double timestamp, int phase, bool foreign)
    485 {
    486     if (InspectorController* ic = inspectorController())
    487         ic->processGPUEvent(timestamp, phase, foreign, 0);
    488 }
    489 
    490 void WebDevToolsAgentImpl::processGPUEvent(const GPUEvent& event)
    491 {
    492     if (InspectorController* ic = inspectorController())
    493         ic->processGPUEvent(event.timestamp, event.phase, event.foreign, event.usedGPUMemoryBytes);
    494 }
    495 
    496 void WebDevToolsAgentImpl::dispatchKeyEvent(const PlatformKeyboardEvent& event)
    497 {
    498     m_generatingEvent = true;
    499     WebKeyboardEvent webEvent = WebKeyboardEventBuilder(event);
    500     if (!webEvent.keyIdentifier[0] && webEvent.type != WebInputEvent::Char)
    501         webEvent.setKeyIdentifierFromWindowsKeyCode();
    502     m_webViewImpl->handleInputEvent(webEvent);
    503     m_generatingEvent = false;
    504 }
    505 
    506 void WebDevToolsAgentImpl::dispatchMouseEvent(const PlatformMouseEvent& event)
    507 {
    508     m_generatingEvent = true;
    509     WebMouseEvent webEvent = WebMouseEventBuilder(m_webViewImpl->mainFrameImpl()->frameView(), event);
    510     m_webViewImpl->handleInputEvent(webEvent);
    511     m_generatingEvent = false;
    512 }
    513 
    514 void WebDevToolsAgentImpl::dispatchOnInspectorBackend(const WebString& message)
    515 {
    516     inspectorController()->dispatchMessageFromFrontend(message);
    517 }
    518 
    519 void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& point)
    520 {
    521     m_webViewImpl->inspectElementAt(point);
    522 }
    523 
    524 InspectorController* WebDevToolsAgentImpl::inspectorController()
    525 {
    526     if (Page* page = m_webViewImpl->page())
    527         return &page->inspectorController();
    528     return 0;
    529 }
    530 
    531 Frame* WebDevToolsAgentImpl::mainFrame()
    532 {
    533     if (Page* page = m_webViewImpl->page())
    534         return page->mainFrame();
    535     return 0;
    536 }
    537 
    538 // WebPageOverlay
    539 void WebDevToolsAgentImpl::paintPageOverlay(WebCanvas* canvas)
    540 {
    541     InspectorController* ic = inspectorController();
    542     if (ic) {
    543         GraphicsContext context(canvas);
    544         context.setCertainlyOpaque(false);
    545         ic->drawHighlight(context);
    546     }
    547 }
    548 
    549 void WebDevToolsAgentImpl::highlight()
    550 {
    551     m_webViewImpl->addPageOverlay(this, OverlayZOrders::highlight);
    552 }
    553 
    554 void WebDevToolsAgentImpl::hideHighlight()
    555 {
    556     m_webViewImpl->removePageOverlay(this);
    557 }
    558 
    559 bool WebDevToolsAgentImpl::sendMessageToFrontend(const String& message)
    560 {
    561     WebDevToolsAgentImpl* devToolsAgent = static_cast<WebDevToolsAgentImpl*>(m_webViewImpl->devToolsAgent());
    562     if (!devToolsAgent)
    563         return false;
    564     m_client->sendMessageToInspectorFrontend(message);
    565     return true;
    566 }
    567 
    568 void WebDevToolsAgentImpl::updateInspectorStateCookie(const String& state)
    569 {
    570     m_client->saveAgentRuntimeState(state);
    571 }
    572 
    573 void WebDevToolsAgentImpl::clearBrowserCache()
    574 {
    575     m_client->clearBrowserCache();
    576 }
    577 
    578 void WebDevToolsAgentImpl::clearBrowserCookies()
    579 {
    580     m_client->clearBrowserCookies();
    581 }
    582 
    583 void WebDevToolsAgentImpl::setProcessId(long processId)
    584 {
    585     inspectorController()->setProcessId(processId);
    586 }
    587 
    588 void WebDevToolsAgentImpl::setLayerTreeId(int layerTreeId)
    589 {
    590     inspectorController()->setLayerTreeId(layerTreeId);
    591 }
    592 
    593 void WebDevToolsAgentImpl::evaluateInWebInspector(long callId, const WebString& script)
    594 {
    595     InspectorController* ic = inspectorController();
    596     ic->evaluateForTestInFrontend(callId, script);
    597 }
    598 
    599 void WebDevToolsAgentImpl::willProcessTask()
    600 {
    601     if (InspectorController* ic = inspectorController())
    602         ic->willProcessTask();
    603 }
    604 
    605 void WebDevToolsAgentImpl::didProcessTask()
    606 {
    607     if (InspectorController* ic = inspectorController())
    608         ic->didProcessTask();
    609 }
    610 
    611 WebString WebDevToolsAgent::inspectorProtocolVersion()
    612 {
    613     return WebCore::inspectorProtocolVersion();
    614 }
    615 
    616 bool WebDevToolsAgent::supportsInspectorProtocolVersion(const WebString& version)
    617 {
    618     return WebCore::supportsInspectorProtocolVersion(version);
    619 }
    620 
    621 void WebDevToolsAgent::interruptAndDispatch(MessageDescriptor* rawDescriptor)
    622 {
    623     // rawDescriptor can't be a PassOwnPtr because interruptAndDispatch is a WebKit API function.
    624     OwnPtr<MessageDescriptor> descriptor = adoptPtr(rawDescriptor);
    625     OwnPtr<DebuggerTask> task = adoptPtr(new DebuggerTask(descriptor.release()));
    626     PageScriptDebugServer::interruptAndRun(task.release(), v8::Isolate::GetCurrent());
    627 }
    628 
    629 bool WebDevToolsAgent::shouldInterruptForMessage(const WebString& message)
    630 {
    631     String commandName;
    632     if (!InspectorBackendDispatcher::getCommandName(message, &commandName))
    633         return false;
    634     return commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_pauseCmd)
    635         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointCmd)
    636         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointByUrlCmd)
    637         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_removeBreakpointCmd)
    638         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kDebugger_setBreakpointsActiveCmd)
    639         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kProfiler_startCmd)
    640         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kProfiler_stopCmd)
    641         || commandName == InspectorBackendDispatcher::commandName(InspectorBackendDispatcher::kHeapProfiler_getHeapSnapshotCmd);
    642 }
    643 
    644 void WebDevToolsAgent::processPendingMessages()
    645 {
    646     PageScriptDebugServer::shared().runPendingTasks();
    647 }
    648 
    649 } // namespace blink
    650