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