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.
7 #include <wtf/HashSet.h>
8 #include <wtf/RefPtr.h>
9 #include <wtf/Vector.h>
14 #include "V8Binding.h"
15 #include "V8DOMWindow.h"
20 #include "grit/webkit_resources.h"
21 #include "third_party/WebKit/WebKit/chromium/src/WebViewImpl.h"
22 #include "webkit/glue/devtools/debugger_agent_impl.h"
23 #include "webkit/glue/devtools/debugger_agent_manager.h"
24 #include "webkit/glue/webdevtoolsagent_impl.h"
25 #include "webkit/glue/webkit_glue.h"
27 using WebCore::DOMWindow
;
28 using WebCore::Document
;
31 using WebCore::String
;
32 using WebCore::V8ClassIndex
;
33 using WebCore::V8Custom
;
34 using WebCore::V8DOMWindow
;
35 using WebCore::V8DOMWrapper
;
36 using WebCore::V8Proxy
;
37 using WebKit::WebViewImpl
;
39 DebuggerAgentImpl::DebuggerAgentImpl(
40 WebViewImpl
* web_view_impl
,
41 DebuggerAgentDelegate
* delegate
,
42 WebDevToolsAgentImpl
* webdevtools_agent
)
43 : web_view_impl_(web_view_impl
),
45 webdevtools_agent_(webdevtools_agent
),
46 auto_continue_on_exception_(false) {
47 DebuggerAgentManager::DebugAttach(this);
50 DebuggerAgentImpl::~DebuggerAgentImpl() {
51 DebuggerAgentManager::DebugDetach(this);
54 void DebuggerAgentImpl::GetContextId() {
55 delegate_
->SetContextId(webdevtools_agent_
->host_id());
58 void DebuggerAgentImpl::DebuggerOutput(const String
& command
) {
59 delegate_
->DebuggerOutput(command
);
60 webdevtools_agent_
->ForceRepaint();
64 void DebuggerAgentImpl::CreateUtilityContext(
66 v8::Persistent
<v8::Context
>* context
) {
67 v8::HandleScope scope
;
69 // TODO(pfeldman): Validate against Soeren.
70 // Set up the DOM window as the prototype of the new global object.
71 v8::Handle
<v8::Context
> window_context
=
72 V8Proxy::context(frame
);
73 v8::Handle
<v8::Object
> window_global
= window_context
->Global();
74 v8::Handle
<v8::Object
> window_wrapper
=
75 V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW
, window_global
);
77 ASSERT(V8DOMWindow::toNative(window_wrapper
) == frame
->domWindow());
79 v8::Handle
<v8::ObjectTemplate
> global_template
= v8::ObjectTemplate::New();
81 // TODO(yurys): provide a function in v8 bindings that would make the
82 // utility context more like main world context of the inspected frame,
83 // otherwise we need to manually make it satisfy various invariants
84 // that V8Proxy::getEntered and some other V8Proxy methods expect to find
85 // on v8 contexts on the contexts stack.
86 // See V8Proxy::createNewContext.
88 // Install a security handler with V8.
89 global_template
->SetAccessCheckCallbacks(
90 V8DOMWindow::namedSecurityCheck
,
91 V8DOMWindow::indexedSecurityCheck
,
92 v8::Integer::New(V8ClassIndex::DOMWINDOW
));
93 // We set number of internal fields to match that in V8DOMWindow wrapper.
94 // See http://crbug.com/28961
95 global_template
->SetInternalFieldCount(
96 V8DOMWindow::internalFieldCount
);
98 *context
= v8::Context::New(
99 NULL
/* no extensions */,
101 v8::Handle
<v8::Object
>());
102 v8::Context::Scope
context_scope(*context
);
103 v8::Handle
<v8::Object
> global
= (*context
)->Global();
105 v8::Handle
<v8::String
> implicit_proto_string
= v8::String::New("__proto__");
106 global
->Set(implicit_proto_string
, window_wrapper
);
108 // Give the code running in the new context a way to get access to the
110 global
->Set(v8::String::New("contentWindow"), window_global
);
112 // Inject javascript into the context.
113 base::StringPiece injectjs_webkit
=
114 webkit_glue::GetDataResource(IDR_DEVTOOLS_INJECT_WEBKIT_JS
);
116 v8::String::New(injectjs_webkit
.as_string().c_str()))->Run();
117 base::StringPiece inject_dispatchjs
= webkit_glue::GetDataResource(
118 IDR_DEVTOOLS_INJECT_DISPATCH_JS
);
119 v8::Script::Compile(v8::String::New(
120 inject_dispatchjs
.as_string().c_str()))->Run();
123 String
DebuggerAgentImpl::ExecuteUtilityFunction(
124 v8::Handle
<v8::Context
> context
,
127 const String
&function_name
,
128 const String
& json_args
,
131 v8::HandleScope scope
;
132 ASSERT(!context
.IsEmpty());
133 if (context
.IsEmpty()) {
134 *exception
= "No window context.";
137 v8::Context::Scope
context_scope(context
);
139 DebuggerAgentManager::UtilityContextScope utility_scope
;
141 v8::Handle
<v8::Object
> dispatch_object
= v8::Handle
<v8::Object
>::Cast(
142 context
->Global()->Get(v8::String::New(object
)));
144 v8::Handle
<v8::Value
> dispatch_function
=
145 dispatch_object
->Get(v8::String::New("dispatch"));
146 ASSERT(dispatch_function
->IsFunction());
147 v8::Handle
<v8::Function
> function
= v8::Handle
<v8::Function
>::Cast(dispatch_function
);
149 v8::Handle
<v8::String
> function_name_wrapper
= v8::Handle
<v8::String
>(
150 v8::String::New(function_name
.utf8().data()));
151 v8::Handle
<v8::String
> json_args_wrapper
= v8::Handle
<v8::String
>(
152 v8::String::New(json_args
.utf8().data()));
153 v8::Handle
<v8::Number
> call_id_wrapper
= v8::Handle
<v8::Number
>(
154 v8::Number::New(async
? call_id
: 0));
156 v8::Handle
<v8::Value
> args
[] = {
157 function_name_wrapper
,
162 v8::TryCatch try_catch
;
163 v8::Handle
<v8::Value
> res_obj
= function
->Call(context
->Global(), 3, args
);
164 if (try_catch
.HasCaught()) {
165 v8::Local
<v8::Message
> message
= try_catch
.Message();
166 if (message
.IsEmpty())
167 *exception
= "Unknown exception";
169 *exception
= WebCore::toWebCoreString(message
->Get());
172 return WebCore::toWebCoreStringWithNullCheck(res_obj
);
176 void DebuggerAgentImpl::ExecuteVoidJavaScript(v8::Handle
<v8::Context
> context
) {
177 v8::HandleScope scope
;
178 ASSERT(!context
.IsEmpty());
179 v8::Context::Scope
context_scope(context
);
180 DebuggerAgentManager::UtilityContextScope utility_scope
;
182 v8::Handle
<v8::Value
> function
=
183 context
->Global()->Get(v8::String::New("devtools$$void"));
184 ASSERT(function
->IsFunction());
185 v8::Handle
<v8::Value
> args
[] = {
186 v8::Local
<v8::Value
>()
188 v8::Handle
<v8::Function
>::Cast(function
)->Call(context
->Global(), 0, args
);
191 WebCore::Page
* DebuggerAgentImpl::GetPage() {
192 return web_view_impl_
->page();