• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "BoundObject.h"
35 #include "DebuggerAgentImpl.h"
36 #include "DebuggerAgentManager.h"
37 #include "Document.h"
38 #include "EventListener.h"
39 #include "InjectedScriptHost.h"
40 #include "InspectorBackend.h"
41 #include "InspectorController.h"
42 #include "InspectorFrontend.h"
43 #include "InspectorResource.h"
44 #include "Node.h"
45 #include "Page.h"
46 #include "PlatformString.h"
47 #include "ProfilerAgentImpl.h"
48 #include "ResourceError.h"
49 #include "ResourceRequest.h"
50 #include "ResourceResponse.h"
51 #include "ScriptObject.h"
52 #include "ScriptState.h"
53 #include "ScriptValue.h"
54 #include "V8Binding.h"
55 #include "V8InspectorBackend.h"
56 #include "V8Proxy.h"
57 #include "V8Utilities.h"
58 #include "WebDataSource.h"
59 #include "WebDevToolsAgentClient.h"
60 #include "WebDevToolsMessageData.h"
61 #include "WebFrameImpl.h"
62 #include "WebString.h"
63 #include "WebURL.h"
64 #include "WebURLError.h"
65 #include "WebURLRequest.h"
66 #include "WebURLResponse.h"
67 #include "WebViewImpl.h"
68 #include <wtf/Noncopyable.h>
69 #include <wtf/OwnPtr.h>
70 
71 using WebCore::Document;
72 using WebCore::DocumentLoader;
73 using WebCore::FrameLoader;
74 using WebCore::InjectedScriptHost;
75 using WebCore::InspectorBackend;
76 using WebCore::InspectorController;
77 using WebCore::InspectorFrontend;
78 using WebCore::InspectorResource;
79 using WebCore::Node;
80 using WebCore::Page;
81 using WebCore::ResourceError;
82 using WebCore::ResourceRequest;
83 using WebCore::ResourceResponse;
84 using WebCore::SafeAllocation;
85 using WebCore::ScriptObject;
86 using WebCore::ScriptState;
87 using WebCore::ScriptValue;
88 using WebCore::String;
89 using WebCore::V8ClassIndex;
90 using WebCore::V8DOMWrapper;
91 using WebCore::V8InspectorBackend;
92 using WebCore::V8Proxy;
93 
94 namespace WebKit {
95 
96 namespace {
97 
InspectorBackendWeakReferenceCallback(v8::Persistent<v8::Value> object,void * parameter)98 void InspectorBackendWeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter)
99 {
100     InspectorBackend* backend = static_cast<InspectorBackend*>(parameter);
101     backend->deref();
102     object.Dispose();
103 }
104 
SetApuAgentEnabledInUtilityContext(v8::Handle<v8::Context> context,bool enabled)105 void SetApuAgentEnabledInUtilityContext(v8::Handle<v8::Context> context, bool enabled)
106 {
107     v8::HandleScope handleScope;
108     v8::Context::Scope contextScope(context);
109     v8::Handle<v8::Object> dispatcher = v8::Local<v8::Object>::Cast(
110         context->Global()->Get(v8::String::New("ApuAgentDispatcher")));
111     if (dispatcher.IsEmpty())
112         return;
113     dispatcher->Set(v8::String::New("enabled"), v8::Boolean::New(enabled));
114 }
115 
116 // TODO(pfeldman): Make this public in WebDevToolsAgent API.
117 static const char kApuAgentFeatureName[] = "apu-agent";
118 
119 // Keep these in sync with the ones in inject_dispatch.js.
120 static const char kTimelineFeatureName[] = "timeline-profiler";
121 static const char kResourceTrackingFeatureName[] = "resource-tracking";
122 
123 class IORPCDelegate : public DevToolsRPC::Delegate, public Noncopyable {
124 public:
IORPCDelegate()125     IORPCDelegate() { }
~IORPCDelegate()126     virtual ~IORPCDelegate() { }
sendRpcMessage(const WebDevToolsMessageData & data)127     virtual void sendRpcMessage(const WebDevToolsMessageData& data)
128     {
129         WebDevToolsAgentClient::sendMessageToFrontendOnIOThread(data);
130     }
131 };
132 
133 } //  namespace
134 
WebDevToolsAgentImpl(WebViewImpl * webViewImpl,WebDevToolsAgentClient * client)135 WebDevToolsAgentImpl::WebDevToolsAgentImpl(
136     WebViewImpl* webViewImpl,
137     WebDevToolsAgentClient* client)
138     : m_hostId(client->hostIdentifier())
139     , m_client(client)
140     , m_webViewImpl(webViewImpl)
141     , m_apuAgentEnabled(false)
142     , m_resourceTrackingWasEnabled(false)
143     , m_attached(false)
144 {
145     m_debuggerAgentDelegateStub.set(new DebuggerAgentDelegateStub(this));
146     m_toolsAgentDelegateStub.set(new ToolsAgentDelegateStub(this));
147     m_apuAgentDelegateStub.set(new ApuAgentDelegateStub(this));
148 }
149 
~WebDevToolsAgentImpl()150 WebDevToolsAgentImpl::~WebDevToolsAgentImpl()
151 {
152     DebuggerAgentManager::onWebViewClosed(m_webViewImpl);
153     disposeUtilityContext();
154 }
155 
disposeUtilityContext()156 void WebDevToolsAgentImpl::disposeUtilityContext()
157 {
158     if (!m_utilityContext.IsEmpty()) {
159         m_utilityContext.Dispose();
160         m_utilityContext.Clear();
161     }
162 }
163 
unhideResourcesPanelIfNecessary()164 void WebDevToolsAgentImpl::unhideResourcesPanelIfNecessary()
165 {
166     InspectorController* ic = m_webViewImpl->page()->inspectorController();
167     ic->ensureResourceTrackingSettingsLoaded();
168     String command = String::format("[\"setResourcesPanelEnabled\", %s]",
169         ic->resourceTrackingEnabled() ? "true" : "false");
170     m_toolsAgentDelegateStub->dispatchOnClient(command);
171 }
172 
attach()173 void WebDevToolsAgentImpl::attach()
174 {
175     if (m_attached)
176         return;
177     m_debuggerAgentImpl.set(
178         new DebuggerAgentImpl(m_webViewImpl,
179                               m_debuggerAgentDelegateStub.get(),
180                               this));
181     resetInspectorFrontendProxy();
182     unhideResourcesPanelIfNecessary();
183     // Allow controller to send messages to the frontend.
184     InspectorController* ic = inspectorController();
185 
186     { // TODO(yurys): the source should have already been pushed by the frontend.
187         v8::HandleScope scope;
188         v8::Context::Scope contextScope(m_utilityContext);
189         v8::Handle<v8::Value> constructorValue = m_utilityContext->Global()->Get(
190             v8::String::New("injectedScriptConstructor"));
191         if (constructorValue->IsFunction()) {
192             String source = WebCore::toWebCoreString(constructorValue);
193             ic->injectedScriptHost()->setInjectedScriptSource("(" + source + ")");
194         }
195     }
196 
197     ic->setWindowVisible(true, false);
198     m_attached = true;
199 }
200 
detach()201 void WebDevToolsAgentImpl::detach()
202 {
203     // Prevent controller from sending messages to the frontend.
204     InspectorController* ic = m_webViewImpl->page()->inspectorController();
205     ic->hideHighlight();
206     ic->close();
207     disposeUtilityContext();
208     m_debuggerAgentImpl.set(0);
209     m_attached = false;
210     m_apuAgentEnabled = false;
211 }
212 
didNavigate()213 void WebDevToolsAgentImpl::didNavigate()
214 {
215     DebuggerAgentManager::onNavigate();
216 }
217 
didCommitProvisionalLoad(WebFrameImpl * webframe,bool isNewNavigation)218 void WebDevToolsAgentImpl::didCommitProvisionalLoad(WebFrameImpl* webframe, bool isNewNavigation)
219 {
220     if (!m_attached)
221         return;
222     WebDataSource* ds = webframe->dataSource();
223     const WebURLRequest& request = ds->request();
224     WebURL url = ds->hasUnreachableURL() ?
225         ds->unreachableURL() :
226         request.url();
227     if (!webframe->parent()) {
228         resetInspectorFrontendProxy();
229         m_toolsAgentDelegateStub->frameNavigate(WebCore::KURL(url).string());
230         SetApuAgentEnabledInUtilityContext(m_utilityContext, m_apuAgentEnabled);
231         unhideResourcesPanelIfNecessary();
232     }
233 }
234 
didClearWindowObject(WebFrameImpl * webframe)235 void WebDevToolsAgentImpl::didClearWindowObject(WebFrameImpl* webframe)
236 {
237     DebuggerAgentManager::setHostId(webframe, m_hostId);
238     if (m_attached) {
239         // Push context id into the client if it is already attached.
240         m_debuggerAgentDelegateStub->setContextId(m_hostId);
241     }
242 }
243 
forceRepaint()244 void WebDevToolsAgentImpl::forceRepaint()
245 {
246     m_client->forceRepaint();
247 }
248 
dispatchOnInspectorController(int callId,const String & functionName,const String & jsonArgs)249 void WebDevToolsAgentImpl::dispatchOnInspectorController(int callId, const String& functionName, const String& jsonArgs)
250 {
251     String result;
252     String exception;
253     result = m_debuggerAgentImpl->executeUtilityFunction(m_utilityContext, callId,
254         "InspectorControllerDispatcher", functionName, jsonArgs, false /* is sync */, &exception);
255     m_toolsAgentDelegateStub->didDispatchOn(callId, result, exception);
256 }
257 
dispatchOnInjectedScript(int callId,int injectedScriptId,const String & functionName,const String & jsonArgs,bool async)258 void WebDevToolsAgentImpl::dispatchOnInjectedScript(int callId, int injectedScriptId, const String& functionName, const String& jsonArgs, bool async)
259 {
260     inspectorController()->inspectorBackend()->dispatchOnInjectedScript(
261         callId,
262         injectedScriptId,
263         functionName,
264         jsonArgs,
265         async);
266 }
267 
dispatchMessageFromFrontend(const WebDevToolsMessageData & data)268 void WebDevToolsAgentImpl::dispatchMessageFromFrontend(const WebDevToolsMessageData& data)
269 {
270     if (ToolsAgentDispatch::dispatch(this, data))
271         return;
272 
273     if (!m_attached)
274         return;
275 
276     if (m_debuggerAgentImpl.get() && DebuggerAgentDispatch::dispatch(m_debuggerAgentImpl.get(), data))
277         return;
278 }
279 
inspectElementAt(const WebPoint & point)280 void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& point)
281 {
282     m_webViewImpl->inspectElementAt(point);
283 }
284 
setRuntimeFeatureEnabled(const WebString & feature,bool enabled)285 void WebDevToolsAgentImpl::setRuntimeFeatureEnabled(const WebString& feature, bool enabled)
286 {
287     if (feature == kApuAgentFeatureName)
288         setApuAgentEnabled(enabled);
289     else if (feature == kTimelineFeatureName)
290         setTimelineProfilingEnabled(enabled);
291     else if (feature == kResourceTrackingFeatureName) {
292         InspectorController* ic = m_webViewImpl->page()->inspectorController();
293         if (enabled)
294           ic->enableResourceTracking(false /* not sticky */, false /* no reload */);
295         else
296           ic->disableResourceTracking(false /* not sticky */);
297     }
298 }
299 
sendRpcMessage(const WebDevToolsMessageData & data)300 void WebDevToolsAgentImpl::sendRpcMessage(const WebDevToolsMessageData& data)
301 {
302     m_client->sendMessageToFrontend(data);
303 }
304 
compileUtilityScripts()305 void WebDevToolsAgentImpl::compileUtilityScripts()
306 {
307     v8::HandleScope handleScope;
308     v8::Context::Scope contextScope(m_utilityContext);
309     // Inject javascript into the context.
310     WebCString injectedScriptJs = m_client->injectedScriptSource();
311     v8::Script::Compile(v8::String::New(
312         injectedScriptJs.data(),
313         injectedScriptJs.length()))->Run();
314     WebCString injectDispatchJs = m_client->injectedScriptDispatcherSource();
315     v8::Script::Compile(v8::String::New(
316         injectDispatchJs.data(),
317         injectDispatchJs.length()))->Run();
318 }
319 
initDevToolsAgentHost()320 void WebDevToolsAgentImpl::initDevToolsAgentHost()
321 {
322     BoundObject devtoolsAgentHost(m_utilityContext, this, "DevToolsAgentHost");
323     devtoolsAgentHost.addProtoFunction(
324         "dispatch",
325         WebDevToolsAgentImpl::jsDispatchOnClient);
326     devtoolsAgentHost.addProtoFunction(
327         "dispatchToApu",
328         WebDevToolsAgentImpl::jsDispatchToApu);
329     devtoolsAgentHost.addProtoFunction(
330         "evaluateOnSelf",
331         WebDevToolsAgentImpl::jsEvaluateOnSelf);
332     devtoolsAgentHost.addProtoFunction(
333         "runtimeFeatureStateChanged",
334         WebDevToolsAgentImpl::jsOnRuntimeFeatureStateChanged);
335     devtoolsAgentHost.build();
336 
337     v8::HandleScope scope;
338     v8::Context::Scope utilityScope(m_utilityContext);
339     // Call custom code to create inspector backend wrapper in the utility context
340     // instead of calling V8DOMWrapper::convertToV8Object that would create the
341     // wrapper in the Page main frame context.
342     v8::Handle<v8::Object> backendWrapper = createInspectorBackendV8Wrapper();
343     if (backendWrapper.IsEmpty())
344         return;
345     m_utilityContext->Global()->Set(v8::String::New("InspectorBackend"), backendWrapper);
346 }
347 
createInspectorBackendV8Wrapper()348 v8::Local<v8::Object> WebDevToolsAgentImpl::createInspectorBackendV8Wrapper()
349 {
350     V8ClassIndex::V8WrapperType descriptorType = V8ClassIndex::INSPECTORBACKEND;
351     v8::Handle<v8::Function> function = V8InspectorBackend::GetTemplate()->GetFunction();
352     if (function.IsEmpty()) {
353         // Return if allocation failed.
354         return v8::Local<v8::Object>();
355     }
356     v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
357     if (instance.IsEmpty()) {
358         // Avoid setting the wrapper if allocation failed.
359         return v8::Local<v8::Object>();
360     }
361     InspectorBackend* backend = m_webViewImpl->page()->inspectorController()->inspectorBackend();
362     V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(descriptorType), backend);
363     // Create a weak reference to the v8 wrapper of InspectorBackend to deref
364     // InspectorBackend when the wrapper is garbage collected.
365     backend->ref();
366     v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance);
367     weakHandle.MakeWeak(backend, &InspectorBackendWeakReferenceCallback);
368     return instance;
369 }
370 
resetInspectorFrontendProxy()371 void WebDevToolsAgentImpl::resetInspectorFrontendProxy()
372 {
373     disposeUtilityContext();
374     m_debuggerAgentImpl->createUtilityContext(m_webViewImpl->page()->mainFrame(), &m_utilityContext);
375     compileUtilityScripts();
376     initDevToolsAgentHost();
377 
378     v8::HandleScope scope;
379     v8::Context::Scope contextScope(m_utilityContext);
380     ScriptState* state = ScriptState::forContext(
381         v8::Local<v8::Context>::New(m_utilityContext));
382     InspectorController* ic = inspectorController();
383     ic->setFrontendProxyObject(state, ScriptObject(state, m_utilityContext->Global()));
384 }
385 
setApuAgentEnabled(bool enabled)386 void WebDevToolsAgentImpl::setApuAgentEnabled(bool enabled)
387 {
388     m_apuAgentEnabled = enabled;
389     SetApuAgentEnabledInUtilityContext(m_utilityContext, enabled);
390     InspectorController* ic = m_webViewImpl->page()->inspectorController();
391     if (enabled) {
392         m_resourceTrackingWasEnabled = ic->resourceTrackingEnabled();
393         ic->startTimelineProfiler();
394         if (!m_resourceTrackingWasEnabled) {
395             // TODO(knorton): Introduce some kind of agents dependency here so that
396             // user could turn off resource tracking while apu agent is on.
397             ic->enableResourceTracking(false, false);
398         }
399         m_debuggerAgentImpl->setAutoContinueOnException(true);
400     } else {
401       ic->stopTimelineProfiler();
402       if (!m_resourceTrackingWasEnabled)
403           ic->disableResourceTracking(false);
404       m_resourceTrackingWasEnabled = false;
405     }
406     m_client->runtimeFeatureStateChanged(
407         kApuAgentFeatureName,
408         enabled);
409 }
410 
411 // static
jsDispatchOnClient(const v8::Arguments & args)412 v8::Handle<v8::Value> WebDevToolsAgentImpl::jsDispatchOnClient(const v8::Arguments& args)
413 {
414     v8::TryCatch exceptionCatcher;
415     String message = WebCore::toWebCoreStringWithNullCheck(args[0]);
416     if (message.isEmpty() || exceptionCatcher.HasCaught())
417         return v8::Undefined();
418     WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(v8::External::Cast(*args.Data())->Value());
419     agent->m_toolsAgentDelegateStub->dispatchOnClient(message);
420     return v8::Undefined();
421 }
422 
423 // static
jsDispatchToApu(const v8::Arguments & args)424 v8::Handle<v8::Value> WebDevToolsAgentImpl::jsDispatchToApu(const v8::Arguments& args)
425 {
426     v8::TryCatch exceptionCatcher;
427     String message = WebCore::toWebCoreStringWithNullCheck(args[0]);
428     if (message.isEmpty() || exceptionCatcher.HasCaught())
429         return v8::Undefined();
430     WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(
431         v8::External::Cast(*args.Data())->Value());
432     agent->m_apuAgentDelegateStub->dispatchToApu(message);
433     return v8::Undefined();
434 }
435 
436 // static
jsEvaluateOnSelf(const v8::Arguments & args)437 v8::Handle<v8::Value> WebDevToolsAgentImpl::jsEvaluateOnSelf(const v8::Arguments& args)
438 {
439     String code;
440     {
441         v8::TryCatch exceptionCatcher;
442         code = WebCore::toWebCoreStringWithNullCheck(args[0]);
443         if (code.isEmpty() || exceptionCatcher.HasCaught())
444             return v8::Undefined();
445     }
446     WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(v8::External::Cast(*args.Data())->Value());
447     v8::Context::Scope(agent->m_utilityContext);
448     V8Proxy* proxy = V8Proxy::retrieve(agent->m_webViewImpl->page()->mainFrame());
449     v8::Local<v8::Value> result = proxy->runScript(v8::Script::Compile(v8::String::New(code.utf8().data())), true);
450     return result;
451 }
452 
453 // static
jsOnRuntimeFeatureStateChanged(const v8::Arguments & args)454 v8::Handle<v8::Value> WebDevToolsAgentImpl::jsOnRuntimeFeatureStateChanged(const v8::Arguments& args)
455 {
456     v8::TryCatch exceptionCatcher;
457     String feature = WebCore::toWebCoreStringWithNullCheck(args[0]);
458     bool enabled = args[1]->ToBoolean()->Value();
459     if (feature.isEmpty() || exceptionCatcher.HasCaught())
460         return v8::Undefined();
461     WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(v8::External::Cast(*args.Data())->Value());
462     agent->m_client->runtimeFeatureStateChanged(feature, enabled);
463     return v8::Undefined();
464 }
465 
466 
inspectorController()467 WebCore::InspectorController* WebDevToolsAgentImpl::inspectorController()
468 {
469     if (Page* page = m_webViewImpl->page())
470         return page->inspectorController();
471     return 0;
472 }
473 
474 
475 //------- plugin resource load notifications ---------------
identifierForInitialRequest(unsigned long resourceId,WebFrame * frame,const WebURLRequest & request)476 void WebDevToolsAgentImpl::identifierForInitialRequest(
477     unsigned long resourceId,
478     WebFrame* frame,
479     const WebURLRequest& request)
480 {
481     if (InspectorController* ic = inspectorController()) {
482         WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(frame);
483         FrameLoader* frameLoader = webFrameImpl->frame()->loader();
484         DocumentLoader* loader = frameLoader->activeDocumentLoader();
485         ic->identifierForInitialRequest(resourceId, loader, request.toResourceRequest());
486     }
487 }
488 
willSendRequest(unsigned long resourceId,const WebURLRequest & request)489 void WebDevToolsAgentImpl::willSendRequest(unsigned long resourceId, const WebURLRequest& request)
490 {
491     if (InspectorController* ic = inspectorController())
492         ic->willSendRequest(resourceId, request.toResourceRequest(), ResourceResponse());
493 }
494 
didReceiveData(unsigned long resourceId,int length)495 void WebDevToolsAgentImpl::didReceiveData(unsigned long resourceId, int length)
496 {
497     if (InspectorController* ic = inspectorController())
498         ic->didReceiveContentLength(resourceId, length);
499 }
500 
didReceiveResponse(unsigned long resourceId,const WebURLResponse & response)501 void WebDevToolsAgentImpl::didReceiveResponse(unsigned long resourceId, const WebURLResponse& response)
502 {
503     if (InspectorController* ic = inspectorController())
504         ic->didReceiveResponse(resourceId, response.toResourceResponse());
505 }
506 
didFinishLoading(unsigned long resourceId)507 void WebDevToolsAgentImpl::didFinishLoading(unsigned long resourceId)
508 {
509     if (InspectorController* ic = inspectorController())
510         ic->didFinishLoading(resourceId);
511 }
512 
didFailLoading(unsigned long resourceId,const WebURLError & error)513 void WebDevToolsAgentImpl::didFailLoading(unsigned long resourceId, const WebURLError& error)
514 {
515     ResourceError resourceError;
516     if (InspectorController* ic = inspectorController())
517         ic->didFailLoading(resourceId, resourceError);
518 }
519 
evaluateInWebInspector(long callId,const WebString & script)520 void WebDevToolsAgentImpl::evaluateInWebInspector(long callId, const WebString& script)
521 {
522     InspectorController* ic = inspectorController();
523     ic->evaluateForTestInFrontend(callId, script);
524 }
525 
setTimelineProfilingEnabled(bool enabled)526 void WebDevToolsAgentImpl::setTimelineProfilingEnabled(bool enabled)
527 {
528     InspectorController* ic = inspectorController();
529     if (enabled)
530         ic->startTimelineProfiler();
531     else
532         ic->stopTimelineProfiler();
533 }
534 
create(WebView * webview,WebDevToolsAgentClient * client)535 WebDevToolsAgent* WebDevToolsAgent::create(WebView* webview, WebDevToolsAgentClient* client)
536 {
537     return new WebDevToolsAgentImpl(static_cast<WebViewImpl*>(webview), client);
538 }
539 
executeDebuggerCommand(const WebString & command,int callerId)540 void WebDevToolsAgent::executeDebuggerCommand(const WebString& command, int callerId)
541 {
542     DebuggerAgentManager::executeDebuggerCommand(command, callerId);
543 }
544 
debuggerPauseScript()545 void WebDevToolsAgent::debuggerPauseScript()
546 {
547     DebuggerAgentManager::pauseScript();
548 }
549 
setMessageLoopDispatchHandler(MessageLoopDispatchHandler handler)550 void WebDevToolsAgent::setMessageLoopDispatchHandler(MessageLoopDispatchHandler handler)
551 {
552     DebuggerAgentManager::setMessageLoopDispatchHandler(handler);
553 }
554 
dispatchMessageFromFrontendOnIOThread(const WebDevToolsMessageData & data)555 bool WebDevToolsAgent::dispatchMessageFromFrontendOnIOThread(const WebDevToolsMessageData& data)
556 {
557     IORPCDelegate transport;
558     ProfilerAgentDelegateStub stub(&transport);
559     ProfilerAgentImpl agent(&stub);
560     return ProfilerAgentDispatch::dispatch(&agent, data);
561 }
562 
563 } // namespace WebKit
564