|
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 "PageGroup.h" |
|
47 #include "PlatformString.h" |
|
48 #include "ProfilerAgentImpl.h" |
|
49 #include "ResourceError.h" |
|
50 #include "ResourceRequest.h" |
|
51 #include "ResourceResponse.h" |
|
52 #include "ScriptDebugServer.h" |
|
53 #include "ScriptObject.h" |
|
54 #include "ScriptState.h" |
|
55 #include "ScriptValue.h" |
|
56 #include "V8Binding.h" |
|
57 #include "V8InspectorBackend.h" |
|
58 #include "V8Proxy.h" |
|
59 #include "V8Utilities.h" |
|
60 #include "WebDataSource.h" |
|
61 #include "WebDevToolsAgentClient.h" |
|
62 #include "WebDevToolsMessageData.h" |
|
63 #include "WebDevToolsMessageTransport.h" |
|
64 #include "WebFrameImpl.h" |
|
65 #include "WebRect.h" |
|
66 #include "WebString.h" |
|
67 #include "WebURL.h" |
|
68 #include "WebURLError.h" |
|
69 #include "WebURLRequest.h" |
|
70 #include "WebURLResponse.h" |
|
71 #include "WebViewClient.h" |
|
72 #include "WebViewImpl.h" |
|
73 #include <wtf/Noncopyable.h> |
|
74 #include <wtf/OwnPtr.h> |
|
75 |
|
76 using WebCore::Document; |
|
77 using WebCore::DocumentLoader; |
|
78 using WebCore::FrameLoader; |
|
79 using WebCore::InjectedScriptHost; |
|
80 using WebCore::InspectorBackend; |
|
81 using WebCore::InspectorController; |
|
82 using WebCore::InspectorFrontend; |
|
83 using WebCore::InspectorResource; |
|
84 using WebCore::Node; |
|
85 using WebCore::Page; |
|
86 using WebCore::ResourceError; |
|
87 using WebCore::ResourceRequest; |
|
88 using WebCore::ResourceResponse; |
|
89 using WebCore::SafeAllocation; |
|
90 using WebCore::ScriptObject; |
|
91 using WebCore::ScriptState; |
|
92 using WebCore::ScriptValue; |
|
93 using WebCore::String; |
|
94 using WebCore::V8DOMWrapper; |
|
95 using WebCore::V8InspectorBackend; |
|
96 using WebCore::V8Proxy; |
|
97 |
|
98 namespace WebKit { |
|
99 |
|
100 namespace { |
|
101 |
|
102 void InspectorBackendWeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter) |
|
103 { |
|
104 InspectorBackend* backend = static_cast<InspectorBackend*>(parameter); |
|
105 backend->deref(); |
|
106 object.Dispose(); |
|
107 } |
|
108 |
|
109 static const char kResourceTrackingFeatureName[] = "resource-tracking"; |
|
110 static const char kTimelineFeatureName[] = "timeline-profiler"; |
|
111 static const char kApuAgentFeatureName[] = "apu-agent"; |
|
112 |
|
113 class IORPCDelegate : public DevToolsRPC::Delegate, public Noncopyable { |
|
114 public: |
|
115 IORPCDelegate() : m_transport(0) { } |
|
116 explicit IORPCDelegate(WebDevToolsMessageTransport* transport) : m_transport(transport) { } |
|
117 virtual ~IORPCDelegate() { } |
|
118 virtual void sendRpcMessage(const WebDevToolsMessageData& data) |
|
119 { |
|
120 if (m_transport) |
|
121 m_transport->sendMessageToFrontendOnIOThread(data); |
|
122 } |
|
123 |
|
124 private: |
|
125 WebDevToolsMessageTransport* m_transport; |
|
126 }; |
|
127 |
|
128 class ClientMessageLoopAdapter : public WebCore::ScriptDebugServer::ClientMessageLoop { |
|
129 public: |
|
130 static void ensureClientMessageLoopCreated(WebDevToolsAgentClient* client) |
|
131 { |
|
132 if (s_instance) |
|
133 return; |
|
134 s_instance = new ClientMessageLoopAdapter(client->createClientMessageLoop()); |
|
135 WebCore::ScriptDebugServer::shared().setClientMessageLoop(s_instance); |
|
136 } |
|
137 |
|
138 static void inspectedViewClosed(WebViewImpl* view) |
|
139 { |
|
140 if (s_instance) |
|
141 s_instance->m_frozenViews.remove(view); |
|
142 } |
|
143 |
|
144 static void didNavigate() |
|
145 { |
|
146 // Release render thread if necessary. |
|
147 if (s_instance && s_instance->m_running) |
|
148 WebCore::ScriptDebugServer::shared().continueProgram(); |
|
149 } |
|
150 |
|
151 private: |
|
152 ClientMessageLoopAdapter(PassOwnPtr<WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop> messageLoop) |
|
153 : m_running(false) |
|
154 , m_messageLoop(messageLoop) { } |
|
155 |
|
156 |
|
157 virtual void run(Page* page) |
|
158 { |
|
159 if (m_running) |
|
160 return; |
|
161 m_running = true; |
|
162 |
|
163 Vector<WebViewImpl*> views; |
|
164 |
|
165 // 1. Disable input events. |
|
166 HashSet<Page*>::const_iterator end = page->group().pages().end(); |
|
167 for (HashSet<Page*>::const_iterator it = page->group().pages().begin(); it != end; ++it) { |
|
168 WebViewImpl* view = WebViewImpl::fromPage(*it); |
|
169 m_frozenViews.add(view); |
|
170 views.append(view); |
|
171 view->setIgnoreInputEvents(true); |
|
172 } |
|
173 |
|
174 // 2. Disable active objects |
|
175 WebView::willEnterModalLoop(); |
|
176 |
|
177 // 3. Process messages until quitNow is called. |
|
178 m_messageLoop->run(); |
|
179 |
|
180 // 4. Resume active objects |
|
181 WebView::didExitModalLoop(); |
|
182 |
|
183 // 5. Resume input events. |
|
184 for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) { |
|
185 if (m_frozenViews.contains(*it)) { |
|
186 // The view was not closed during the dispatch. |
|
187 (*it)->setIgnoreInputEvents(false); |
|
188 } |
|
189 } |
|
190 |
|
191 // 6. All views have been resumed, clear the set. |
|
192 m_frozenViews.clear(); |
|
193 |
|
194 m_running = false; |
|
195 } |
|
196 |
|
197 virtual void quitNow() |
|
198 { |
|
199 m_messageLoop->quitNow(); |
|
200 } |
|
201 |
|
202 bool m_running; |
|
203 OwnPtr<WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop> m_messageLoop; |
|
204 typedef HashSet<WebViewImpl*> FrozenViewsSet; |
|
205 FrozenViewsSet m_frozenViews; |
|
206 static ClientMessageLoopAdapter* s_instance; |
|
207 |
|
208 }; |
|
209 |
|
210 ClientMessageLoopAdapter* ClientMessageLoopAdapter::s_instance = 0; |
|
211 |
|
212 } // namespace |
|
213 |
|
214 WebDevToolsAgentImpl::WebDevToolsAgentImpl( |
|
215 WebViewImpl* webViewImpl, |
|
216 WebDevToolsAgentClient* client) |
|
217 : m_hostId(client->hostIdentifier()) |
|
218 , m_client(client) |
|
219 , m_webViewImpl(webViewImpl) |
|
220 , m_apuAgentEnabled(false) |
|
221 , m_resourceTrackingWasEnabled(false) |
|
222 , m_attached(false) |
|
223 { |
|
224 DebuggerAgentManager::setExposeV8DebuggerProtocol( |
|
225 client->exposeV8DebuggerProtocol()); |
|
226 m_debuggerAgentDelegateStub.set(new DebuggerAgentDelegateStub(this)); |
|
227 m_toolsAgentDelegateStub.set(new ToolsAgentDelegateStub(this)); |
|
228 m_apuAgentDelegateStub.set(new ApuAgentDelegateStub(this)); |
|
229 } |
|
230 |
|
231 WebDevToolsAgentImpl::~WebDevToolsAgentImpl() |
|
232 { |
|
233 DebuggerAgentManager::onWebViewClosed(m_webViewImpl); |
|
234 ClientMessageLoopAdapter::inspectedViewClosed(m_webViewImpl); |
|
235 disposeUtilityContext(); |
|
236 } |
|
237 |
|
238 void WebDevToolsAgentImpl::disposeUtilityContext() |
|
239 { |
|
240 if (!m_utilityContext.IsEmpty()) { |
|
241 m_utilityContext.Dispose(); |
|
242 m_utilityContext.Clear(); |
|
243 } |
|
244 } |
|
245 |
|
246 void WebDevToolsAgentImpl::attach() |
|
247 { |
|
248 if (m_attached) |
|
249 return; |
|
250 |
|
251 if (!m_client->exposeV8DebuggerProtocol()) |
|
252 ClientMessageLoopAdapter::ensureClientMessageLoopCreated(m_client); |
|
253 |
|
254 m_debuggerAgentImpl.set( |
|
255 new DebuggerAgentImpl(m_webViewImpl, |
|
256 m_debuggerAgentDelegateStub.get(), |
|
257 this)); |
|
258 createInspectorFrontendProxy(); |
|
259 |
|
260 // Allow controller to send messages to the frontend. |
|
261 InspectorController* ic = inspectorController(); |
|
262 |
|
263 { // TODO(yurys): the source should have already been pushed by the frontend. |
|
264 v8::HandleScope scope; |
|
265 v8::Context::Scope contextScope(m_utilityContext); |
|
266 v8::Handle<v8::Value> constructorValue = m_utilityContext->Global()->Get( |
|
267 v8::String::New("injectedScriptConstructor")); |
|
268 if (constructorValue->IsFunction()) { |
|
269 String source = WebCore::toWebCoreString(constructorValue); |
|
270 ic->injectedScriptHost()->setInjectedScriptSource("(" + source + ")"); |
|
271 } |
|
272 } |
|
273 |
|
274 setInspectorFrontendProxyToInspectorController(); |
|
275 m_attached = true; |
|
276 } |
|
277 |
|
278 void WebDevToolsAgentImpl::detach() |
|
279 { |
|
280 // Prevent controller from sending messages to the frontend. |
|
281 InspectorController* ic = m_webViewImpl->page()->inspectorController(); |
|
282 ic->disconnectFrontend(); |
|
283 ic->hideHighlight(); |
|
284 ic->close(); |
|
285 disposeUtilityContext(); |
|
286 m_debuggerAgentImpl.set(0); |
|
287 m_attached = false; |
|
288 m_apuAgentEnabled = false; |
|
289 } |
|
290 |
|
291 void WebDevToolsAgentImpl::didNavigate() |
|
292 { |
|
293 ClientMessageLoopAdapter::didNavigate(); |
|
294 DebuggerAgentManager::onNavigate(); |
|
295 } |
|
296 |
|
297 void WebDevToolsAgentImpl::didClearWindowObject(WebFrameImpl* webframe) |
|
298 { |
|
299 DebuggerAgentManager::setHostId(webframe, m_hostId); |
|
300 if (m_attached) { |
|
301 // Push context id into the client if it is already attached. |
|
302 m_debuggerAgentDelegateStub->setContextId(m_hostId); |
|
303 } |
|
304 } |
|
305 |
|
306 void WebDevToolsAgentImpl::forceRepaint() |
|
307 { |
|
308 m_client->forceRepaint(); |
|
309 } |
|
310 |
|
311 void WebDevToolsAgentImpl::dispatchOnInspectorController(int callId, const String& functionName, const String& jsonArgs) |
|
312 { |
|
313 String result; |
|
314 String exception; |
|
315 result = m_debuggerAgentImpl->executeUtilityFunction(m_utilityContext, callId, |
|
316 "InspectorControllerDispatcher", functionName, jsonArgs, false /* is sync */, &exception); |
|
317 m_toolsAgentDelegateStub->didDispatchOn(callId, result, exception); |
|
318 } |
|
319 |
|
320 void WebDevToolsAgentImpl::dispatchOnInjectedScript(int callId, int injectedScriptId, const String& functionName, const String& jsonArgs, bool async) |
|
321 { |
|
322 inspectorController()->inspectorBackend()->dispatchOnInjectedScript( |
|
323 callId, |
|
324 injectedScriptId, |
|
325 functionName, |
|
326 jsonArgs, |
|
327 async); |
|
328 } |
|
329 |
|
330 void WebDevToolsAgentImpl::dispatchMessageFromFrontend(const WebDevToolsMessageData& data) |
|
331 { |
|
332 if (ToolsAgentDispatch::dispatch(this, data)) |
|
333 return; |
|
334 |
|
335 if (!m_attached) |
|
336 return; |
|
337 |
|
338 if (m_debuggerAgentImpl.get() && DebuggerAgentDispatch::dispatch(m_debuggerAgentImpl.get(), data)) |
|
339 return; |
|
340 } |
|
341 |
|
342 void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& point) |
|
343 { |
|
344 m_webViewImpl->inspectElementAt(point); |
|
345 } |
|
346 |
|
347 void WebDevToolsAgentImpl::setRuntimeFeatureEnabled(const WebString& feature, bool enabled) |
|
348 { |
|
349 if (feature == kApuAgentFeatureName) |
|
350 setApuAgentEnabled(enabled); |
|
351 else if (feature == kTimelineFeatureName) |
|
352 setTimelineProfilingEnabled(enabled); |
|
353 else if (feature == kResourceTrackingFeatureName) { |
|
354 InspectorController* ic = m_webViewImpl->page()->inspectorController(); |
|
355 if (enabled) |
|
356 ic->enableResourceTracking(false /* not sticky */, false /* no reload */); |
|
357 else |
|
358 ic->disableResourceTracking(false /* not sticky */); |
|
359 } |
|
360 } |
|
361 |
|
362 void WebDevToolsAgentImpl::sendRpcMessage(const WebDevToolsMessageData& data) |
|
363 { |
|
364 m_client->sendMessageToFrontend(data); |
|
365 } |
|
366 |
|
367 void WebDevToolsAgentImpl::compileUtilityScripts() |
|
368 { |
|
369 v8::HandleScope handleScope; |
|
370 v8::Context::Scope contextScope(m_utilityContext); |
|
371 // Inject javascript into the context. |
|
372 WebCString injectedScriptJs = m_client->injectedScriptSource(); |
|
373 v8::Script::Compile(v8::String::New( |
|
374 injectedScriptJs.data(), |
|
375 injectedScriptJs.length()))->Run(); |
|
376 WebCString injectDispatchJs = m_client->injectedScriptDispatcherSource(); |
|
377 v8::Script::Compile(v8::String::New( |
|
378 injectDispatchJs.data(), |
|
379 injectDispatchJs.length()))->Run(); |
|
380 } |
|
381 |
|
382 void WebDevToolsAgentImpl::initDevToolsAgentHost() |
|
383 { |
|
384 BoundObject devtoolsAgentHost(m_utilityContext, this, "DevToolsAgentHost"); |
|
385 devtoolsAgentHost.addProtoFunction( |
|
386 "dispatch", |
|
387 WebDevToolsAgentImpl::jsDispatchOnClient); |
|
388 devtoolsAgentHost.build(); |
|
389 |
|
390 v8::HandleScope scope; |
|
391 v8::Context::Scope utilityScope(m_utilityContext); |
|
392 // Call custom code to create inspector backend wrapper in the utility context |
|
393 // instead of calling V8DOMWrapper::convertToV8Object that would create the |
|
394 // wrapper in the Page main frame context. |
|
395 v8::Handle<v8::Object> backendWrapper = createInspectorBackendV8Wrapper(); |
|
396 if (backendWrapper.IsEmpty()) |
|
397 return; |
|
398 m_utilityContext->Global()->Set(v8::String::New("InspectorBackend"), backendWrapper); |
|
399 } |
|
400 |
|
401 v8::Local<v8::Object> WebDevToolsAgentImpl::createInspectorBackendV8Wrapper() |
|
402 { |
|
403 v8::Handle<v8::Function> function = V8InspectorBackend::GetTemplate()->GetFunction(); |
|
404 if (function.IsEmpty()) { |
|
405 // Return if allocation failed. |
|
406 return v8::Local<v8::Object>(); |
|
407 } |
|
408 v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); |
|
409 if (instance.IsEmpty()) { |
|
410 // Avoid setting the wrapper if allocation failed. |
|
411 return v8::Local<v8::Object>(); |
|
412 } |
|
413 InspectorBackend* backend = m_webViewImpl->page()->inspectorController()->inspectorBackend(); |
|
414 V8DOMWrapper::setDOMWrapper(instance, &V8InspectorBackend::info, backend); |
|
415 // Create a weak reference to the v8 wrapper of InspectorBackend to deref |
|
416 // InspectorBackend when the wrapper is garbage collected. |
|
417 backend->ref(); |
|
418 v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance); |
|
419 weakHandle.MakeWeak(backend, &InspectorBackendWeakReferenceCallback); |
|
420 return instance; |
|
421 } |
|
422 |
|
423 void WebDevToolsAgentImpl::createInspectorFrontendProxy() |
|
424 { |
|
425 disposeUtilityContext(); |
|
426 m_utilityContext = v8::Context::New(); |
|
427 compileUtilityScripts(); |
|
428 initDevToolsAgentHost(); |
|
429 WebCString debuggerScriptJs = m_client->debuggerScriptSource(); |
|
430 WebCore::ScriptDebugServer::shared().setDebuggerScriptSource( |
|
431 WebCore::String(debuggerScriptJs.data(), debuggerScriptJs.length())); |
|
432 } |
|
433 |
|
434 void WebDevToolsAgentImpl::setInspectorFrontendProxyToInspectorController() |
|
435 { |
|
436 v8::HandleScope scope; |
|
437 ScriptState* state = ScriptState::forContext( |
|
438 v8::Local<v8::Context>::New(m_utilityContext)); |
|
439 InspectorController* ic = inspectorController(); |
|
440 ic->connectFrontend(ScriptObject(state, m_utilityContext->Global())); |
|
441 } |
|
442 |
|
443 void WebDevToolsAgentImpl::setApuAgentEnabled(bool enabled) |
|
444 { |
|
445 m_apuAgentEnabled = enabled; |
|
446 InspectorController* ic = m_webViewImpl->page()->inspectorController(); |
|
447 if (enabled) { |
|
448 m_resourceTrackingWasEnabled = ic->resourceTrackingEnabled(); |
|
449 ic->startTimelineProfiler(); |
|
450 if (!m_resourceTrackingWasEnabled) { |
|
451 // TODO(knorton): Introduce some kind of agents dependency here so that |
|
452 // user could turn off resource tracking while apu agent is on. |
|
453 ic->enableResourceTracking(false, false); |
|
454 } |
|
455 m_debuggerAgentImpl->setAutoContinueOnException(true); |
|
456 } else { |
|
457 ic->stopTimelineProfiler(); |
|
458 if (!m_resourceTrackingWasEnabled) |
|
459 ic->disableResourceTracking(false); |
|
460 m_resourceTrackingWasEnabled = false; |
|
461 } |
|
462 m_client->runtimeFeatureStateChanged( |
|
463 kApuAgentFeatureName, |
|
464 enabled); |
|
465 } |
|
466 |
|
467 // static |
|
468 v8::Handle<v8::Value> WebDevToolsAgentImpl::jsDispatchOnClient(const v8::Arguments& args) |
|
469 { |
|
470 v8::TryCatch exceptionCatcher; |
|
471 String message = WebCore::toWebCoreStringWithNullCheck(args[0]); |
|
472 if (message.isEmpty() || exceptionCatcher.HasCaught()) |
|
473 return v8::Undefined(); |
|
474 |
|
475 WebDevToolsAgentImpl* agent = static_cast<WebDevToolsAgentImpl*>(v8::External::Cast(*args.Data())->Value()); |
|
476 |
|
477 if (!agent->m_apuAgentEnabled) { |
|
478 agent->m_toolsAgentDelegateStub->dispatchOnClient(message); |
|
479 return v8::Undefined(); |
|
480 } |
|
481 |
|
482 String method = WebCore::toWebCoreStringWithNullCheck(args[1]); |
|
483 if (method.isEmpty() || exceptionCatcher.HasCaught()) |
|
484 return v8::Undefined(); |
|
485 |
|
486 if (method != "addRecordToTimeline" && method != "updateResource" && method != "addResource") |
|
487 return v8::Undefined(); |
|
488 |
|
489 agent->m_apuAgentDelegateStub->dispatchToApu(message); |
|
490 return v8::Undefined(); |
|
491 } |
|
492 |
|
493 WebCore::InspectorController* WebDevToolsAgentImpl::inspectorController() |
|
494 { |
|
495 if (Page* page = m_webViewImpl->page()) |
|
496 return page->inspectorController(); |
|
497 return 0; |
|
498 } |
|
499 |
|
500 |
|
501 //------- plugin resource load notifications --------------- |
|
502 void WebDevToolsAgentImpl::identifierForInitialRequest( |
|
503 unsigned long resourceId, |
|
504 WebFrame* frame, |
|
505 const WebURLRequest& request) |
|
506 { |
|
507 if (InspectorController* ic = inspectorController()) { |
|
508 WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(frame); |
|
509 FrameLoader* frameLoader = webFrameImpl->frame()->loader(); |
|
510 DocumentLoader* loader = frameLoader->activeDocumentLoader(); |
|
511 ic->identifierForInitialRequest(resourceId, loader, request.toResourceRequest()); |
|
512 } |
|
513 } |
|
514 |
|
515 void WebDevToolsAgentImpl::willSendRequest(unsigned long resourceId, WebURLRequest& request) |
|
516 { |
|
517 if (InspectorController* ic = inspectorController()) |
|
518 ic->willSendRequest(resourceId, request.toMutableResourceRequest(), ResourceResponse()); |
|
519 } |
|
520 |
|
521 void WebDevToolsAgentImpl::didReceiveData(unsigned long resourceId, int length) |
|
522 { |
|
523 if (InspectorController* ic = inspectorController()) |
|
524 ic->didReceiveContentLength(resourceId, length); |
|
525 } |
|
526 |
|
527 void WebDevToolsAgentImpl::didReceiveResponse(unsigned long resourceId, const WebURLResponse& response) |
|
528 { |
|
529 if (InspectorController* ic = inspectorController()) |
|
530 ic->didReceiveResponse(resourceId, response.toResourceResponse()); |
|
531 } |
|
532 |
|
533 void WebDevToolsAgentImpl::didFinishLoading(unsigned long resourceId) |
|
534 { |
|
535 if (InspectorController* ic = inspectorController()) |
|
536 ic->didFinishLoading(resourceId); |
|
537 } |
|
538 |
|
539 void WebDevToolsAgentImpl::didFailLoading(unsigned long resourceId, const WebURLError& error) |
|
540 { |
|
541 ResourceError resourceError; |
|
542 if (InspectorController* ic = inspectorController()) |
|
543 ic->didFailLoading(resourceId, resourceError); |
|
544 } |
|
545 |
|
546 void WebDevToolsAgentImpl::inspectorDestroyed() |
|
547 { |
|
548 // Our lifetime is bound to the WebViewImpl. |
|
549 } |
|
550 |
|
551 void WebDevToolsAgentImpl::openInspectorFrontend(InspectorController*) |
|
552 { |
|
553 } |
|
554 |
|
555 void WebDevToolsAgentImpl::highlight(Node* node) |
|
556 { |
|
557 // InspectorController does the actuall tracking of the highlighted node |
|
558 // and the drawing of the highlight. Here we just make sure to invalidate |
|
559 // the rects of the old and new nodes. |
|
560 hideHighlight(); |
|
561 } |
|
562 |
|
563 void WebDevToolsAgentImpl::hideHighlight() |
|
564 { |
|
565 // FIXME: able to invalidate a smaller rect. |
|
566 // FIXME: Is it important to just invalidate the rect of the node region |
|
567 // given that this is not on a critical codepath? In order to do so, we'd |
|
568 // have to take scrolling into account. |
|
569 const WebSize& size = m_webViewImpl->size(); |
|
570 WebRect damagedRect(0, 0, size.width, size.height); |
|
571 if (m_webViewImpl->client()) |
|
572 m_webViewImpl->client()->didInvalidateRect(damagedRect); |
|
573 } |
|
574 |
|
575 void WebDevToolsAgentImpl::populateSetting(const String& key, String* value) |
|
576 { |
|
577 WebString string; |
|
578 m_webViewImpl->inspectorSetting(key, &string); |
|
579 *value = string; |
|
580 } |
|
581 |
|
582 void WebDevToolsAgentImpl::storeSetting(const String& key, const String& value) |
|
583 { |
|
584 m_webViewImpl->setInspectorSetting(key, value); |
|
585 } |
|
586 |
|
587 bool WebDevToolsAgentImpl::sendMessageToFrontend(const WebCore::String& message) |
|
588 { |
|
589 WebDevToolsAgentImpl* devToolsAgent = static_cast<WebDevToolsAgentImpl*>(m_webViewImpl->devToolsAgent()); |
|
590 if (!devToolsAgent) |
|
591 return false; |
|
592 |
|
593 if (devToolsAgent->m_apuAgentEnabled && devToolsAgent->m_apuAgentDelegateStub) { |
|
594 devToolsAgent->m_apuAgentDelegateStub->dispatchToApu(message); |
|
595 return true; |
|
596 } |
|
597 |
|
598 WebVector<WebString> arguments(size_t(1)); |
|
599 arguments[0] = message; |
|
600 WebDevToolsMessageData data; |
|
601 data.className = "ToolsAgentDelegate"; |
|
602 data.methodName = "dispatchOnClient"; |
|
603 data.arguments.swap(arguments); |
|
604 devToolsAgent->sendRpcMessage(data); |
|
605 return true; |
|
606 } |
|
607 |
|
608 void WebDevToolsAgentImpl::resourceTrackingWasEnabled() |
|
609 { |
|
610 m_client->runtimeFeatureStateChanged(kResourceTrackingFeatureName, true); |
|
611 } |
|
612 |
|
613 void WebDevToolsAgentImpl::resourceTrackingWasDisabled() |
|
614 { |
|
615 m_client->runtimeFeatureStateChanged(kResourceTrackingFeatureName, false); |
|
616 } |
|
617 |
|
618 void WebDevToolsAgentImpl::timelineProfilerWasStarted() |
|
619 { |
|
620 m_client->runtimeFeatureStateChanged(kTimelineFeatureName, true); |
|
621 } |
|
622 |
|
623 void WebDevToolsAgentImpl::timelineProfilerWasStopped() |
|
624 { |
|
625 m_client->runtimeFeatureStateChanged(kTimelineFeatureName, false); |
|
626 } |
|
627 |
|
628 void WebDevToolsAgentImpl::evaluateInWebInspector(long callId, const WebString& script) |
|
629 { |
|
630 InspectorController* ic = inspectorController(); |
|
631 ic->evaluateForTestInFrontend(callId, script); |
|
632 } |
|
633 |
|
634 void WebDevToolsAgentImpl::setTimelineProfilingEnabled(bool enabled) |
|
635 { |
|
636 InspectorController* ic = inspectorController(); |
|
637 if (enabled) |
|
638 ic->startTimelineProfiler(); |
|
639 else |
|
640 ic->stopTimelineProfiler(); |
|
641 } |
|
642 |
|
643 void WebDevToolsAgent::executeDebuggerCommand(const WebString& command, int callerId) |
|
644 { |
|
645 DebuggerAgentManager::executeDebuggerCommand(command, callerId); |
|
646 } |
|
647 |
|
648 void WebDevToolsAgent::debuggerPauseScript() |
|
649 { |
|
650 DebuggerAgentManager::pauseScript(); |
|
651 } |
|
652 |
|
653 void WebDevToolsAgent::setMessageLoopDispatchHandler(MessageLoopDispatchHandler handler) |
|
654 { |
|
655 DebuggerAgentManager::setMessageLoopDispatchHandler(handler); |
|
656 } |
|
657 |
|
658 bool WebDevToolsAgent::dispatchMessageFromFrontendOnIOThread(WebDevToolsMessageTransport* transport, const WebDevToolsMessageData& data) |
|
659 { |
|
660 IORPCDelegate delegate(transport); |
|
661 ProfilerAgentDelegateStub stub(&delegate); |
|
662 ProfilerAgentImpl agent(&stub); |
|
663 return ProfilerAgentDispatch::dispatch(&agent, data); |
|
664 } |
|
665 |
|
666 } // namespace WebKit |