OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "Document.h" | |
10 #include "DOMWindow.h" | |
11 #include "Frame.h" | |
12 #include "InspectorBackend.h" | |
13 #include "InspectorController.h" | |
14 #include "Node.h" | |
15 #include "Page.h" | |
16 #include "PlatformString.h" | |
17 #include "SecurityOrigin.h" | |
18 #include "Settings.h" | |
19 #include "V8Binding.h" | |
20 #include "V8CustomBinding.h" | |
21 #include "V8Proxy.h" | |
22 #include "V8Utilities.h" | |
23 #include <wtf/OwnPtr.h> | |
24 #include <wtf/Vector.h> | |
25 #undef LOG | |
26 | |
27 #include "base/string_util.h" | |
28 #include "webkit/api/public/WebFrame.h" | |
29 #include "webkit/api/public/WebScriptSource.h" | |
30 #include "webkit/glue/devtools/bound_object.h" | |
31 #include "webkit/glue/devtools/debugger_agent.h" | |
32 #include "webkit/glue/devtools/devtools_rpc_js.h" | |
33 #include "webkit/glue/devtools/tools_agent.h" | |
34 #include "webkit/glue/glue_util.h" | |
35 #include "webkit/glue/webdevtoolsclient_delegate.h" | |
36 #include "webkit/glue/webdevtoolsclient_impl.h" | |
37 #include "webkit/glue/webview_impl.h" | |
38 | |
39 using namespace WebCore; | |
40 using WebKit::WebFrame; | |
41 using WebKit::WebScriptSource; | |
42 using WebKit::WebString; | |
43 using WebKit::WebView; | |
44 | |
45 static v8::Local<v8::String> ToV8String(const String& s) { | |
46 if (s.isNull()) | |
47 return v8::Local<v8::String>(); | |
48 | |
49 return v8::String::New(reinterpret_cast<const uint16_t*>(s.characters()), | |
50 s.length()); | |
51 } | |
52 | |
53 DEFINE_RPC_JS_BOUND_OBJ(DebuggerAgent, DEBUGGER_AGENT_STRUCT, | |
54 DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT) | |
55 DEFINE_RPC_JS_BOUND_OBJ(ToolsAgent, TOOLS_AGENT_STRUCT, | |
56 ToolsAgentDelegate, TOOLS_AGENT_DELEGATE_STRUCT) | |
57 | |
58 class ToolsAgentNativeDelegateImpl : public ToolsAgentNativeDelegate { | |
59 public: | |
60 struct ResourceContentRequestData { | |
61 String mime_type; | |
62 RefPtr<Node> frame; | |
63 }; | |
64 | |
65 ToolsAgentNativeDelegateImpl(WebFrameImpl* frame) : frame_(frame) {} | |
66 virtual ~ToolsAgentNativeDelegateImpl() {} | |
67 | |
68 // ToolsAgentNativeDelegate implementation. | |
69 virtual void DidGetResourceContent(int request_id, const String& content) { | |
70 if (!resource_content_requests_.contains(request_id)) { | |
71 NOTREACHED(); | |
72 return; | |
73 } | |
74 ResourceContentRequestData request = | |
75 resource_content_requests_.take(request_id); | |
76 | |
77 InspectorController* ic = frame_->frame()->page()->inspectorController(); | |
78 if (request.frame && request.frame->attached()) { | |
79 ic->inspectorBackend()->addSourceToFrame(request.mime_type, | |
80 content, | |
81 request.frame.get()); | |
82 } | |
83 } | |
84 | |
85 bool WaitingForResponse(int resource_id, Node* frame) { | |
86 if (resource_content_requests_.contains(resource_id)) { | |
87 DCHECK(resource_content_requests_.get(resource_id).frame.get() == frame) | |
88 << "Only one frame is expected to display given resource"; | |
89 return true; | |
90 } | |
91 return false; | |
92 } | |
93 | |
94 void RequestSent(int resource_id, String mime_type, Node* frame) { | |
95 ResourceContentRequestData data; | |
96 data.mime_type = mime_type; | |
97 data.frame = frame; | |
98 DCHECK(!resource_content_requests_.contains(resource_id)); | |
99 resource_content_requests_.set(resource_id, data); | |
100 } | |
101 | |
102 private: | |
103 WebFrameImpl* frame_; | |
104 HashMap<int, ResourceContentRequestData> resource_content_requests_; | |
105 DISALLOW_COPY_AND_ASSIGN(ToolsAgentNativeDelegateImpl); | |
106 }; | |
107 | |
108 // static | |
109 WebDevToolsClient* WebDevToolsClient::Create( | |
110 WebView* view, | |
111 WebDevToolsClientDelegate* delegate, | |
112 const WebString& application_locale) { | |
113 return new WebDevToolsClientImpl( | |
114 static_cast<WebViewImpl*>(view), | |
115 delegate, | |
116 webkit_glue::WebStringToString(application_locale)); | |
117 } | |
118 | |
119 WebDevToolsClientImpl::WebDevToolsClientImpl( | |
120 WebViewImpl* web_view_impl, | |
121 WebDevToolsClientDelegate* delegate, | |
122 const String& application_locale) | |
123 : web_view_impl_(web_view_impl), | |
124 delegate_(delegate), | |
125 application_locale_(application_locale), | |
126 loaded_(false) { | |
127 WebFrameImpl* frame = web_view_impl_->main_frame(); | |
128 v8::HandleScope scope; | |
129 v8::Handle<v8::Context> frame_context = V8Proxy::context(frame->frame()); | |
130 | |
131 debugger_agent_obj_.set(new JsDebuggerAgentBoundObj( | |
132 this, frame_context, "RemoteDebuggerAgent")); | |
133 tools_agent_obj_.set( | |
134 new JsToolsAgentBoundObj(this, frame_context, "RemoteToolsAgent")); | |
135 | |
136 // Debugger commands should be sent using special method. | |
137 debugger_command_executor_obj_.set( | |
138 new BoundObject(frame_context, this, "RemoteDebuggerCommandExecutor")); | |
139 debugger_command_executor_obj_->AddProtoFunction( | |
140 "DebuggerCommand", | |
141 WebDevToolsClientImpl::JsDebuggerCommand); | |
142 debugger_command_executor_obj_->Build(); | |
143 | |
144 dev_tools_host_.set(new BoundObject(frame_context, this, "DevToolsHost")); | |
145 dev_tools_host_->AddProtoFunction( | |
146 "reset", | |
147 WebDevToolsClientImpl::JsReset); | |
148 dev_tools_host_->AddProtoFunction( | |
149 "addSourceToFrame", | |
150 WebDevToolsClientImpl::JsAddSourceToFrame); | |
151 dev_tools_host_->AddProtoFunction( | |
152 "addResourceSourceToFrame", | |
153 WebDevToolsClientImpl::JsAddResourceSourceToFrame); | |
154 dev_tools_host_->AddProtoFunction( | |
155 "loaded", | |
156 WebDevToolsClientImpl::JsLoaded); | |
157 dev_tools_host_->AddProtoFunction( | |
158 "search", | |
159 WebCore::V8Custom::v8InspectorBackendSearchCallback); | |
160 dev_tools_host_->AddProtoFunction( | |
161 "getPlatform", | |
162 WebDevToolsClientImpl::JsGetPlatform); | |
163 dev_tools_host_->AddProtoFunction( | |
164 "activateWindow", | |
165 WebDevToolsClientImpl::JsActivateWindow); | |
166 dev_tools_host_->AddProtoFunction( | |
167 "closeWindow", | |
168 WebDevToolsClientImpl::JsCloseWindow); | |
169 dev_tools_host_->AddProtoFunction( | |
170 "dockWindow", | |
171 WebDevToolsClientImpl::JsDockWindow); | |
172 dev_tools_host_->AddProtoFunction( | |
173 "undockWindow", | |
174 WebDevToolsClientImpl::JsUndockWindow); | |
175 dev_tools_host_->AddProtoFunction( | |
176 "toggleInspectElementMode", | |
177 WebDevToolsClientImpl::JsToggleInspectElementMode); | |
178 dev_tools_host_->AddProtoFunction( | |
179 "getApplicationLocale", | |
180 WebDevToolsClientImpl::JsGetApplicationLocale); | |
181 dev_tools_host_->AddProtoFunction( | |
182 "hiddenPanels", | |
183 WebDevToolsClientImpl::JsHiddenPanels); | |
184 dev_tools_host_->Build(); | |
185 } | |
186 | |
187 WebDevToolsClientImpl::~WebDevToolsClientImpl() { | |
188 } | |
189 | |
190 void WebDevToolsClientImpl::DispatchMessageFromAgent( | |
191 const WebString& class_name, | |
192 const WebString& method_name, | |
193 const WebString& param1, | |
194 const WebString& param2, | |
195 const WebString& param3) { | |
196 if (ToolsAgentNativeDelegateDispatch::Dispatch( | |
197 tools_agent_native_delegate_impl_.get(), | |
198 webkit_glue::WebStringToString(class_name), | |
199 webkit_glue::WebStringToString(method_name), | |
200 webkit_glue::WebStringToString(param1), | |
201 webkit_glue::WebStringToString(param2), | |
202 webkit_glue::WebStringToString(param3))) { | |
203 return; | |
204 } | |
205 | |
206 Vector<String> v; | |
207 v.append(webkit_glue::WebStringToString(class_name)); | |
208 v.append(webkit_glue::WebStringToString(method_name)); | |
209 v.append(webkit_glue::WebStringToString(param1)); | |
210 v.append(webkit_glue::WebStringToString(param2)); | |
211 v.append(webkit_glue::WebStringToString(param3)); | |
212 if (!loaded_) { | |
213 pending_incoming_messages_.append(v); | |
214 return; | |
215 } | |
216 ExecuteScript(v); | |
217 } | |
218 | |
219 void WebDevToolsClientImpl::AddResourceSourceToFrame(int resource_id, | |
220 String mime_type, | |
221 Node* frame) { | |
222 if (tools_agent_native_delegate_impl_->WaitingForResponse(resource_id, | |
223 frame)) { | |
224 return; | |
225 } | |
226 tools_agent_obj_->GetResourceContent(resource_id, resource_id); | |
227 tools_agent_native_delegate_impl_->RequestSent(resource_id, mime_type, frame); | |
228 } | |
229 | |
230 void WebDevToolsClientImpl::ExecuteScript(const Vector<String>& v) { | |
231 WebFrameImpl* frame = web_view_impl_->main_frame(); | |
232 v8::HandleScope scope; | |
233 v8::Handle<v8::Context> frame_context = V8Proxy::context(frame->frame()); | |
234 v8::Context::Scope context_scope(frame_context); | |
235 v8::Handle<v8::Value> dispatch_function = | |
236 frame_context->Global()->Get(v8::String::New("devtools$$dispatch")); | |
237 ASSERT(dispatch_function->IsFunction()); | |
238 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(dispatch_fu
nction); | |
239 v8::Handle<v8::Value> args[] = { | |
240 ToV8String(v.at(0)), | |
241 ToV8String(v.at(1)), | |
242 ToV8String(v.at(2)), | |
243 ToV8String(v.at(3)), | |
244 ToV8String(v.at(4)), | |
245 }; | |
246 function->Call(frame_context->Global(), 5, args); | |
247 } | |
248 | |
249 void WebDevToolsClientImpl::SendRpcMessage(const String& class_name, | |
250 const String& method_name, | |
251 const String& param1, | |
252 const String& param2, | |
253 const String& param3) { | |
254 delegate_->SendMessageToAgent( | |
255 webkit_glue::StringToWebString(class_name), | |
256 webkit_glue::StringToWebString(method_name), | |
257 webkit_glue::StringToWebString(param1), | |
258 webkit_glue::StringToWebString(param2), | |
259 webkit_glue::StringToWebString(param3)); | |
260 } | |
261 | |
262 // static | |
263 v8::Handle<v8::Value> WebDevToolsClientImpl::JsReset( | |
264 const v8::Arguments& args) { | |
265 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
266 v8::External::Cast(*args.Data())->Value()); | |
267 WebFrameImpl* frame = client->web_view_impl_->main_frame(); | |
268 client->tools_agent_native_delegate_impl_.set( | |
269 new ToolsAgentNativeDelegateImpl(frame)); | |
270 return v8::Undefined(); | |
271 } | |
272 | |
273 // static | |
274 v8::Handle<v8::Value> WebDevToolsClientImpl::JsAddSourceToFrame( | |
275 const v8::Arguments& args) { | |
276 if (args.Length() < 2) { | |
277 return v8::Undefined(); | |
278 } | |
279 | |
280 v8::TryCatch exception_catcher; | |
281 | |
282 String mime_type = WebCore::toWebCoreStringWithNullCheck(args[0]); | |
283 if (mime_type.isEmpty() || exception_catcher.HasCaught()) { | |
284 return v8::Undefined(); | |
285 } | |
286 String source_string = WebCore::toWebCoreStringWithNullCheck(args[1]); | |
287 if (source_string.isEmpty() || exception_catcher.HasCaught()) { | |
288 return v8::Undefined(); | |
289 } | |
290 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(args[2]); | |
291 Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(wrapper); | |
292 if (!node || !node->attached()) { | |
293 return v8::Undefined(); | |
294 } | |
295 | |
296 Page* page = V8Proxy::retrieveFrameForEnteredContext()->page(); | |
297 InspectorController* inspectorController = page->inspectorController(); | |
298 return WebCore::v8Boolean(inspectorController->inspectorBackend()-> | |
299 addSourceToFrame(mime_type, source_string, node)); | |
300 } | |
301 | |
302 // static | |
303 v8::Handle<v8::Value> WebDevToolsClientImpl::JsAddResourceSourceToFrame( | |
304 const v8::Arguments& args) { | |
305 int resource_id = static_cast<int>(args[0]->NumberValue()); | |
306 String mime_type = WebCore::toWebCoreStringWithNullCheck(args[1]); | |
307 if (mime_type.isEmpty()) { | |
308 return v8::Undefined(); | |
309 } | |
310 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(args[2]); | |
311 Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(wrapper); | |
312 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
313 v8::External::Cast(*args.Data())->Value()); | |
314 client->AddResourceSourceToFrame(resource_id, mime_type, node); | |
315 return v8::Undefined(); | |
316 } | |
317 | |
318 // static | |
319 v8::Handle<v8::Value> WebDevToolsClientImpl::JsLoaded( | |
320 const v8::Arguments& args) { | |
321 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
322 v8::External::Cast(*args.Data())->Value()); | |
323 client->loaded_ = true; | |
324 | |
325 // Grant the devtools page the ability to have source view iframes. | |
326 Page* page = V8Proxy::retrieveFrameForEnteredContext()->page(); | |
327 SecurityOrigin* origin = page->mainFrame()->domWindow()->securityOrigin(); | |
328 origin->grantUniversalAccess(); | |
329 | |
330 for (Vector<Vector<String> >::iterator it = | |
331 client->pending_incoming_messages_.begin(); | |
332 it != client->pending_incoming_messages_.end(); | |
333 ++it) { | |
334 client->ExecuteScript(*it); | |
335 } | |
336 client->pending_incoming_messages_.clear(); | |
337 return v8::Undefined(); | |
338 } | |
339 | |
340 // static | |
341 v8::Handle<v8::Value> WebDevToolsClientImpl::JsGetPlatform( | |
342 const v8::Arguments& args) { | |
343 #if defined OS_MACOSX | |
344 return v8String("mac-leopard"); | |
345 #elif defined OS_LINUX | |
346 return v8String("linux"); | |
347 #else | |
348 return v8String("windows"); | |
349 #endif | |
350 } | |
351 | |
352 // static | |
353 v8::Handle<v8::Value> WebDevToolsClientImpl::JsActivateWindow( | |
354 const v8::Arguments& args) { | |
355 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
356 v8::External::Cast(*args.Data())->Value()); | |
357 client->delegate_->ActivateWindow(); | |
358 return v8::Undefined(); | |
359 } | |
360 | |
361 // static | |
362 v8::Handle<v8::Value> WebDevToolsClientImpl::JsCloseWindow( | |
363 const v8::Arguments& args) { | |
364 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
365 v8::External::Cast(*args.Data())->Value()); | |
366 client->delegate_->CloseWindow(); | |
367 return v8::Undefined(); | |
368 } | |
369 | |
370 // static | |
371 v8::Handle<v8::Value> WebDevToolsClientImpl::JsDockWindow( | |
372 const v8::Arguments& args) { | |
373 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
374 v8::External::Cast(*args.Data())->Value()); | |
375 client->delegate_->DockWindow(); | |
376 return v8::Undefined(); | |
377 } | |
378 | |
379 // static | |
380 v8::Handle<v8::Value> WebDevToolsClientImpl::JsUndockWindow( | |
381 const v8::Arguments& args) { | |
382 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
383 v8::External::Cast(*args.Data())->Value()); | |
384 client->delegate_->UndockWindow(); | |
385 return v8::Undefined(); | |
386 } | |
387 | |
388 // static | |
389 v8::Handle<v8::Value> WebDevToolsClientImpl::JsToggleInspectElementMode( | |
390 const v8::Arguments& args) { | |
391 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
392 v8::External::Cast(*args.Data())->Value()); | |
393 int enabled = static_cast<int>(args[0]->BooleanValue()); | |
394 client->delegate_->ToggleInspectElementMode(enabled); | |
395 return v8::Undefined(); | |
396 } | |
397 | |
398 // static | |
399 v8::Handle<v8::Value> WebDevToolsClientImpl::JsGetApplicationLocale( | |
400 const v8::Arguments& args) { | |
401 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
402 v8::External::Cast(*args.Data())->Value()); | |
403 return v8String(client->application_locale_); | |
404 } | |
405 | |
406 // static | |
407 v8::Handle<v8::Value> WebDevToolsClientImpl::JsHiddenPanels( | |
408 const v8::Arguments& args) { | |
409 Page* page = V8Proxy::retrieveFrameForEnteredContext()->page(); | |
410 return v8String(page->settings()->databasesEnabled() ? "" : "databases"); | |
411 } | |
412 | |
413 // static | |
414 v8::Handle<v8::Value> WebDevToolsClientImpl::JsDebuggerCommand( | |
415 const v8::Arguments& args) { | |
416 WebDevToolsClientImpl* client = static_cast<WebDevToolsClientImpl*>( | |
417 v8::External::Cast(*args.Data())->Value()); | |
418 String command = WebCore::toWebCoreStringWithNullCheck(args[0]); | |
419 WebString std_command = webkit_glue::StringToWebString(command); | |
420 client->delegate_->SendDebuggerCommandToAgent(std_command); | |
421 return v8::Undefined(); | |
422 } | |
OLD | NEW |