diff options
author | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-08 14:13:04 +0000 |
---|---|---|
committer | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-08 14:13:04 +0000 |
commit | 9b9d728c445b3c1c2ac0b3f66753a205dc2eafc3 (patch) | |
tree | d52354b9d35df88bff508b5936a7fd9b98f31d55 /webkit | |
parent | 51a5ea2a6ef9d361b62ef1e6f3590131ac395cea (diff) | |
download | chromium_src-9b9d728c445b3c1c2ac0b3f66753a205dc2eafc3.zip chromium_src-9b9d728c445b3c1c2ac0b3f66753a205dc2eafc3.tar.gz chromium_src-9b9d728c445b3c1c2ac0b3f66753a205dc2eafc3.tar.bz2 |
1. All debugger messages are dispatched in a static method on the IO thread. All responses from the v8 go to another static method where we should find out which devtool agent delegate should be used for sending the response. We use call_id to match request with the delegate its response should be sent to. We don't pass the delegate directly as it's designed to be accessed on the render thread only.
To match debug command response with its request the request sequence number is replaced with a number that is unique across the renderer(note that requests from different clients may have equal ids so we cannot rely on them). This happens before the command gets to the v8. When the command response is ready the original request_seq is restored. Before that the request_seq field is used to find out which devtools agent delegate should be used for sending the response.
2. For the debugger events we derive target agent from the current v8 execution context. If there is no agent attached to the RenderView owning that context 'continue' command is sent to the v8 automatically and the message is ignored.
Review URL: http://codereview.chromium.org/62106
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13347 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.cc | 14 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.h | 13 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_manager.cc | 165 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_manager.h | 17 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent.h | 4 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent_impl.cc | 10 |
6 files changed, 205 insertions, 18 deletions
diff --git a/webkit/glue/devtools/debugger_agent_impl.cc b/webkit/glue/devtools/debugger_agent_impl.cc index 6838d5b..dc475ab 100644 --- a/webkit/glue/devtools/debugger_agent_impl.cc +++ b/webkit/glue/devtools/debugger_agent_impl.cc @@ -16,6 +16,7 @@ #include "webkit/glue/devtools/debugger_agent_manager.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/glue/webview_impl.h" using WebCore::Document; using WebCore::Node; @@ -23,8 +24,13 @@ using WebCore::String; using WebCore::V8ClassIndex; using WebCore::V8Proxy; -DebuggerAgentImpl::DebuggerAgentImpl(DebuggerAgentDelegate* delegate) - : delegate_(delegate) { +DebuggerAgentImpl::DebuggerAgentImpl( + WebViewImpl* web_view_impl, + DebuggerAgentDelegate* delegate, + WebDevToolsAgent* webdevtools_agent) + : web_view_impl_(web_view_impl), + delegate_(delegate), + webdevtools_agent_(webdevtools_agent) { DebuggerAgentManager::DebugAttach(this); } @@ -86,3 +92,7 @@ String DebuggerAgentImpl::ExecuteUtilityFunction( v8::Handle<v8::String> res_json = v8::Handle<v8::String>::Cast(res_obj); return WebCore::toWebCoreString(res_json); } + +WebCore::Page* DebuggerAgentImpl::GetPage() { + return web_view_impl_->page(); +} diff --git a/webkit/glue/devtools/debugger_agent_impl.h b/webkit/glue/devtools/debugger_agent_impl.h index aa0db70..664d506 100644 --- a/webkit/glue/devtools/debugger_agent_impl.h +++ b/webkit/glue/devtools/debugger_agent_impl.h @@ -8,15 +8,21 @@ #include "v8.h" #include "webkit/glue/devtools/debugger_agent.h" +class WebDevToolsAgent; +class WebViewImpl; + namespace WebCore { class Document; class Node; +class Page; class String; } class DebuggerAgentImpl : public DebuggerAgent { public: - explicit DebuggerAgentImpl(DebuggerAgentDelegate* delegate); + DebuggerAgentImpl(WebViewImpl* web_view_impl, + DebuggerAgentDelegate* delegate, + WebDevToolsAgent* webdevtools_agent); virtual ~DebuggerAgentImpl(); // Initializes dom agent with the given document. @@ -35,9 +41,14 @@ class DebuggerAgentImpl : public DebuggerAgent { WebCore::Node* node, const WebCore::String& json_args); + WebCore::Page* GetPage(); + WebDevToolsAgent* webdevtools_agent() { return webdevtools_agent_; }; + private: v8::Persistent<v8::Context> context_; + WebViewImpl* web_view_impl_; DebuggerAgentDelegate* delegate_; + WebDevToolsAgent* webdevtools_agent_; DISALLOW_COPY_AND_ASSIGN(DebuggerAgentImpl); }; diff --git a/webkit/glue/devtools/debugger_agent_manager.cc b/webkit/glue/devtools/debugger_agent_manager.cc index d37c8d3..678c904 100644 --- a/webkit/glue/devtools/debugger_agent_manager.cc +++ b/webkit/glue/devtools/debugger_agent_manager.cc @@ -4,10 +4,15 @@ #include "config.h" +#include "Frame.h" +#include "v8_proxy.h" #include <wtf/HashSet.h> #undef LOG +#include "base/json_reader.h" +#include "base/json_writer.h" #include "base/string_util.h" +#include "base/values.h" #include "webkit/glue/devtools/debugger_agent_impl.h" #include "webkit/glue/devtools/debugger_agent_manager.h" @@ -15,6 +20,7 @@ #include "v8/include/v8-debug.h" #endif + // static void DebuggerAgentManager::V8DebugMessageHandler(const uint16_t* message, int length, @@ -71,29 +77,170 @@ void DebuggerAgentManager::DebugBreak(DebuggerAgentImpl* debugger_agent) { // static void DebuggerAgentManager::DebuggerOutput(const std::string& out) { - DebuggerAgentImpl* agent = GetAgentForCurrentV8Context(); + OwnPtr<Value> response(JSONReader::Read(out, + false /* allow_trailing_comma */)); + if (!response.get()) { + NOTREACHED(); + return; + } + if (!response->IsType(Value::TYPE_DICTIONARY)) { + NOTREACHED(); + return; + } + DictionaryValue* m = static_cast<DictionaryValue*>(response.get()); + + std::string type; + if (!m->GetString(L"type", &type)) { + NOTREACHED(); + return; + } + + // Agent that should be used for sending command response is determined based + // on the 'request_seq' field in the response body. + if (type == "response") { + SendCommandResponse(m); + return; + } + + // Agent that should be used for sending events is determined based + // on the active Frame. + DebuggerAgentImpl* agent = FindAgentForCurrentV8Context(); if (!agent) { + // Autocontinue execution on break and exception events if there is no + // handler. + std::wstring continue_cmd( + L"{\"seq\":1,\"type\":\"request\",\"command\":\"continue\"}"); + SendCommandToV8(continue_cmd); return; } agent->DebuggerOutput(out); } // static -void DebuggerAgentManager::ExecuteDebuggerCommand(const std::string& command) { +bool DebuggerAgentManager::SendCommandResponse(DictionaryValue* response) { + // TODO(yurys): there is a bug in v8 which converts original string seq into + // a json dictinary. + DictionaryValue* request_seq; + if (!response->GetDictionary(L"request_seq", &request_seq)) { + NOTREACHED(); + return false; + } + + int agent_ptr; + if (!request_seq->GetInteger(L"webdevtools_agent", &agent_ptr)) { + NOTREACHED(); + return false; + } + + Value* original_request_seq; + if (request_seq->Get(L"request_seq", &original_request_seq)) { + response->Set(L"request_seq", original_request_seq->DeepCopy()); + } else { + response->Remove(L"request_seq", NULL /* out_value */); + } + + DebuggerAgentImpl* debugger_agent = FindDebuggerAgentForToolsAgent( + reinterpret_cast<WebDevToolsAgent*>(agent_ptr)); + if (!debugger_agent) { + return false; + } + + std::string json; + JSONWriter::Write(response, false /* pretty_print */, &json); + debugger_agent->DebuggerOutput(json); + return true; +} + + +// static +void DebuggerAgentManager::ExecuteDebuggerCommand( + const std::string& command, + WebDevToolsAgent* webdevtools_agent) { + const std::string cmd = DebuggerAgentManager::ReplaceRequestSequenceId( + command, + webdevtools_agent); + + SendCommandToV8(UTF8ToWide(cmd)); +} + +// static +void DebuggerAgentManager::SendCommandToV8(const std::wstring& cmd) { #if USE(V8) - std::wstring cmd_wstring = UTF8ToWide(command); - v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd_wstring.data()), - cmd_wstring.length()); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.data()), + cmd.length()); #endif } + // static -DebuggerAgentImpl* DebuggerAgentManager::GetAgentForCurrentV8Context() { +DebuggerAgentImpl* DebuggerAgentManager::FindAgentForCurrentV8Context() { if (!attached_agents_) { return NULL; } DCHECK(!attached_agents_->isEmpty()); - // TODO(yurys): find agent for current v8 global context. Now we return first - // agent in the set. - return *attached_agents_->begin(); + + WebCore::Frame* frame = WebCore::V8Proxy::retrieveActiveFrame(); + if (!frame) { + return NULL; + } + WebCore::Page* page = frame->page(); + for (AttachedAgentsSet::iterator it = attached_agents_->begin(); + it != attached_agents_->end(); ++it) { + if ((*it)->GetPage() == page) { + return *it; + } + } + return NULL; +} + +const std::string DebuggerAgentManager::ReplaceRequestSequenceId( + const std::string& request, + WebDevToolsAgent* webdevtools_agent) { + OwnPtr<Value> message(JSONReader::Read(request, + false /* allow_trailing_comma */)); + if (!message.get()) { + return request; + } + if (!message->IsType(Value::TYPE_DICTIONARY)) { + return request; + } + DictionaryValue* m = static_cast<DictionaryValue*>(message.get()); + + std::string type; + if (!(m->GetString(L"type", &type) && type == "request")) { + return request; + } + + DictionaryValue new_seq; + Value* request_seq; + if (m->Get(L"seq", &request_seq)) { + new_seq.Set(L"request_seq", request_seq->DeepCopy()); + } + + // TODO(yurys): get rid of this hack, handler pointer should be passed + // into v8::Debug::SendCommand along with the command. + int agent_ptr = reinterpret_cast<int>(webdevtools_agent); + new_seq.Set(L"webdevtools_agent", Value::CreateIntegerValue(agent_ptr)); + + // TODO(yurys): fix v8 parser so that it handle objects as ids correctly. + std::string new_seq_str; + JSONWriter::Write(&new_seq, false /* pretty_print */, &new_seq_str); + m->SetString(L"seq", new_seq_str); + + std::string json; + JSONWriter::Write(m, false /* pretty_print */, &json); + return json; +} + +// Note that we cannot safely dereference 'webdevtools_agent' bacause the +// referenced agent may already have been detached and destroyed. +DebuggerAgentImpl* DebuggerAgentManager::FindDebuggerAgentForToolsAgent( + WebDevToolsAgent* webdevtools_agent) { + for (AttachedAgentsSet::iterator it = attached_agents_->begin(); + it != attached_agents_->end(); ++it) { + if ((*it)->webdevtools_agent() == webdevtools_agent) { + return *it; + } + } + return NULL; } diff --git a/webkit/glue/devtools/debugger_agent_manager.h b/webkit/glue/devtools/debugger_agent_manager.h index ba48966..39469b8 100644 --- a/webkit/glue/devtools/debugger_agent_manager.h +++ b/webkit/glue/devtools/debugger_agent_manager.h @@ -5,12 +5,15 @@ #ifndef WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_MANAGER_H_ #define WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_MANAGER_H_ +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include "base/basictypes.h" #include "v8/include/v8-debug.h" class DebuggerAgentImpl; +class DictionaryValue; +class WebDevToolsAgent; // There is single v8 instance per render process. Also there may be several // RenderViews and consequently devtools agents in the process that want to talk @@ -34,7 +37,8 @@ class DebuggerAgentManager { static void DebugBreak(DebuggerAgentImpl* debugger_agent); static void DebugCommand(const std::string& command); - static void ExecuteDebuggerCommand(const std::string& command); + static void ExecuteDebuggerCommand(const std::string& command, + WebDevToolsAgent* webdevtools_agent); private: DebuggerAgentManager(); @@ -44,7 +48,16 @@ class DebuggerAgentManager { int length, void* data); static void DebuggerOutput(const std::string& out); - static DebuggerAgentImpl* GetAgentForCurrentV8Context(); + static void SendCommandToV8(const std::wstring& cmd); + static bool SendCommandResponse(DictionaryValue* response); + + static DebuggerAgentImpl* FindAgentForCurrentV8Context(); + static DebuggerAgentImpl* FindDebuggerAgentForToolsAgent( + WebDevToolsAgent* webdevtools_agent); + + static const std::string ReplaceRequestSequenceId( + const std::string& request, + WebDevToolsAgent* webdevtools_agent); typedef HashSet<DebuggerAgentImpl*> AttachedAgentsSet; static AttachedAgentsSet* attached_agents_; diff --git a/webkit/glue/webdevtoolsagent.h b/webkit/glue/webdevtoolsagent.h index e96cfc1..30b7b5d5 100644 --- a/webkit/glue/webdevtoolsagent.h +++ b/webkit/glue/webdevtoolsagent.h @@ -24,7 +24,9 @@ class WebDevToolsAgent { virtual void InspectElement(int x, int y) = 0; // Asynchronously executes debugger command in the render thread. - static void ExecuteDebuggerCommand(const std::string& command); + // |webdevtools_agent| will be used for sending response. + static void ExecuteDebuggerCommand(const std::string& command, + WebDevToolsAgent* webdevtools_agent); private: DISALLOW_COPY_AND_ASSIGN(WebDevToolsAgent); diff --git a/webkit/glue/webdevtoolsagent_impl.cc b/webkit/glue/webdevtoolsagent_impl.cc index 5a4c4b4..e5cf8ad 100644 --- a/webkit/glue/webdevtoolsagent_impl.cc +++ b/webkit/glue/webdevtoolsagent_impl.cc @@ -59,7 +59,9 @@ void WebDevToolsAgentImpl::Attach() { return; } debugger_agent_impl_.set( - new DebuggerAgentImpl(debugger_agent_delegate_stub_.get())); + new DebuggerAgentImpl(web_view_impl_, + debugger_agent_delegate_stub_.get(), + this)); dom_agent_impl_.set(new DomAgentImpl(dom_agent_delegate_stub_.get())); net_agent_impl_.set(new NetAgentImpl(net_agent_delegate_stub_.get())); @@ -236,6 +238,8 @@ void WebDevToolsAgentImpl::SendRpcMessage(const std::string& raw_msg) { } // static -void WebDevToolsAgent::ExecuteDebuggerCommand(const std::string& command) { - DebuggerAgentManager::ExecuteDebuggerCommand(command); +void WebDevToolsAgent::ExecuteDebuggerCommand( + const std::string& command, + WebDevToolsAgent* webdevtools_agent) { + DebuggerAgentManager::ExecuteDebuggerCommand(command, webdevtools_agent); } |