diff options
author | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-10 13:52:30 +0000 |
---|---|---|
committer | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-10 13:52:30 +0000 |
commit | 98f5f88b53f774cee109503b0225a5bfb9deb550 (patch) | |
tree | 32af75ae9784181c85e577327d8020192658c519 /chrome/browser/debugger/debugger_remote_service.cc | |
parent | 198d8d43c5ccff8d0d48bbd3fef31917aa9d3db6 (diff) | |
download | chromium_src-98f5f88b53f774cee109503b0225a5bfb9deb550.zip chromium_src-98f5f88b53f774cee109503b0225a5bfb9deb550.tar.gz chromium_src-98f5f88b53f774cee109503b0225a5bfb9deb550.tar.bz2 |
DevTools. Add V8 Application Remote Debugging Protocol support by apavlov. Original CL: http://codereview.chromium.org/56109
Review URL: http://codereview.chromium.org/66031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13502 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/debugger/debugger_remote_service.cc')
-rw-r--r-- | chrome/browser/debugger/debugger_remote_service.cc | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/chrome/browser/debugger/debugger_remote_service.cc b/chrome/browser/debugger/debugger_remote_service.cc new file mode 100644 index 0000000..de7e364 --- /dev/null +++ b/chrome/browser/debugger/debugger_remote_service.cc @@ -0,0 +1,262 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/debugger/debugger_remote_service.h" + +#include "base/json_reader.h" +#include "base/json_writer.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/debugger/devtools_manager.h" +#include "chrome/browser/debugger/devtools_protocol_handler.h" +#include "chrome/browser/debugger/devtools_remote_message.h" +#include "chrome/browser/debugger/inspectable_tab_proxy.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/devtools_messages.h" +#include "chrome/common/render_messages.h" + +const std::string DebuggerRemoteServiceCommand::kAttach = "attach"; +const std::string DebuggerRemoteServiceCommand::kDetach = "detach"; +const std::string DebuggerRemoteServiceCommand::kDebuggerCommand = + "debugger_command"; +const std::string DebuggerRemoteServiceCommand::kEvaluateJavascript = + "evaluate_javascript"; + +const std::string DebuggerRemoteService::kToolName = "V8Debugger"; +const std::wstring DebuggerRemoteService::kDataWide = L"data"; +const std::wstring DebuggerRemoteService::kResultWide = L"result"; + +DebuggerRemoteService::DebuggerRemoteService(DevToolsProtocolHandler* delegate) + : delegate_(delegate) {} + +DebuggerRemoteService::~DebuggerRemoteService() {} + +// message from remote debugger +void DebuggerRemoteService::HandleMessage( + const DevToolsRemoteMessage& message) { + static const std::wstring kCommandWide = L"command"; + const std::string destination = message.destination(); + scoped_ptr<Value> request(JSONReader::Read(message.content(), true)); + if (request.get() == NULL) { + // Bad JSON + NOTREACHED(); + return; + } + DictionaryValue* content; + if (!request->IsType(Value::TYPE_DICTIONARY)) { + NOTREACHED(); // Broken protocol :( + return; + } + content = static_cast<DictionaryValue*>(request.get()); + if (!content->HasKey(kCommandWide)) { + NOTREACHED(); // Broken protocol :( + return; + } + std::string command; + DictionaryValue response; + + content->GetString(kCommandWide, &command); + response.SetString(kCommandWide, command); + bool send_response = true; + if (destination.size() == 0) { + // Unknown command (bad format?) + NOTREACHED(); + response.SetInteger(kResultWide, Result::kUnknownCommand); + SendResponse(response, message.tool(), message.destination()); + return; + } + int32 tab_uid = -1; + StringToInt(destination, &tab_uid); + + if (command == DebuggerRemoteServiceCommand::kAttach) { + // TODO(apavlov): handle 0 for a new tab + response.SetString(kCommandWide, DebuggerRemoteServiceCommand::kAttach); + AttachTab(destination, &response); + } else if (command == DebuggerRemoteServiceCommand::kDetach) { + response.SetString(kCommandWide, DebuggerRemoteServiceCommand::kDetach); + DetachTab(destination, &response); + } else if (command == DebuggerRemoteServiceCommand::kDebuggerCommand) { + if (tab_uid != -1) { + DevToolsManager* manager = g_browser_process->devtools_manager(); + if (manager == NULL) { + response.SetInteger(kResultWide, Result::kDebuggerError); + } + WebContents* web_contents = ToWebContents(tab_uid); + if (web_contents != NULL) { + DevToolsClientHost* client_host = + manager->GetDevToolsClientHostFor(*web_contents); + if (client_host != NULL) { + std::string v8_command; + DictionaryValue* v8_command_value; + content->GetDictionary(kDataWide, &v8_command_value); + JSONWriter::Write(v8_command_value, false, &v8_command); + g_browser_process->devtools_manager()->ForwardToDevToolsAgent( + *client_host, DevToolsAgentMsg_DebuggerCommand(v8_command)); + send_response = false; + // Do not send response right now as the JSON will be received from + // the V8 debugger asynchronously + } else { + // tab_uid is not being debugged (Attach has not been invoked) + response.SetInteger(kResultWide, Result::kIllegalTabState); + } + } else { + // Unknown tab_uid from remote debugger + response.SetInteger(kResultWide, Result::kUnknownTab); + } + } else { + // Invalid tab_uid from remote debugger (perhaps NaN) + response.SetInteger(kResultWide, Result::kUnknownTab); + } + } else if (command == DebuggerRemoteServiceCommand::kEvaluateJavascript) { + if (tab_uid != -1) { + WebContents* web_contents = ToWebContents(tab_uid); + if (web_contents != NULL) { + RenderViewHost* rvh = web_contents->render_view_host(); + if (rvh != NULL) { + std::wstring javascript; + content->GetString(kDataWide, &javascript); + rvh->Send(new ViewMsg_ScriptEvalRequest( + rvh->routing_id(), L"", javascript)); + send_response = false; + } else { + // No RenderViewHost + response.SetInteger(kResultWide, Result::kDebuggerError); + } + } else { + // Unknown tab_uid from remote debugger + response.SetInteger(kResultWide, Result::kUnknownTab); + } + } + } else { + // Unknown command + NOTREACHED(); + response.SetInteger(kResultWide, Result::kUnknownCommand); + } + + if (send_response) { + SendResponse(response, message.tool(), message.destination()); + } +} + +void DebuggerRemoteService::SendResponse(const Value& response, + const std::string& tool, + const std::string& destination) { + std::string response_content; + JSONWriter::Write(&response, false, &response_content); + scoped_ptr<DevToolsRemoteMessage> response_message( + DevToolsRemoteMessageBuilder::instance().Create(tool, + destination, + response_content)); + delegate_->Send(*response_message.get()); +} + +WebContents* DebuggerRemoteService::ToWebContents(int32 tab_uid) { + const InspectableTabProxy::ControllersMap& navcon_map = + delegate_->inspectable_tab_proxy()->controllers_map(false); + InspectableTabProxy::ControllersMap::const_iterator it = + navcon_map.find(tab_uid); + if (it != navcon_map.end()) { + TabContents* tab_contents = it->second->active_contents(); + if (tab_contents == NULL) { + return NULL; + } else { + return tab_contents->AsWebContents(); + } + } else { + return NULL; + } +} + +void DebuggerRemoteService::DebuggerOutput(int32 tab_id, + const std::string& message) { + std::string content; + content.append("{\"command\":\"") + .append(DebuggerRemoteServiceCommand::kDebuggerCommand) + .append("\",\"result\":") + .append(IntToString(Result::kOk)) + .append(",\"data\":") + .append(message) + .append("}"); + scoped_ptr<DevToolsRemoteMessage> response_message( + DevToolsRemoteMessageBuilder::instance().Create( + kToolName, + IntToString(tab_id), + content)); + delegate_->Send(*(response_message.get())); +} + +void DebuggerRemoteService::AttachTab(const std::string& destination, + DictionaryValue* response) { + int32 tab_uid = -1; + StringToInt(destination, &tab_uid); + if (tab_uid < 0) { + // Bad tab_uid received from remote debugger (perhaps NaN) + response->SetInteger(kDataWide, Result::kUnknownTab); + return; + } + if (tab_uid == 0) { // single tab_uid + // We've been asked to open a new tab with URL. + // TODO(apavlov): implement + NOTIMPLEMENTED(); + response->SetInteger(kDataWide, Result::kUnknownTab); + return; + } + WebContents* web_contents = ToWebContents(tab_uid); + if (web_contents == NULL) { + // No active web contents with tab_uid + response->SetInteger(kDataWide, Result::kUnknownTab); + return; + } + if (g_browser_process->devtools_manager()->GetDevToolsClientHostFor( + *web_contents) == NULL) { + DevToolsClientHost* client_host = + InspectableTabProxy::NewClientHost(tab_uid, this); + DevToolsManager* manager = g_browser_process->devtools_manager(); + if (manager != NULL) { + manager->RegisterDevToolsClientHostFor(*web_contents, client_host); + manager->ForwardToDevToolsAgent(*client_host, DevToolsAgentMsg_Attach()); + response->SetInteger(kDataWide, Result::kOk); + } else { + response->SetInteger(kDataWide, Result::kDebuggerError); + } + } else { + // DevToolsClientHost for this tab already registered + response->SetInteger(kDataWide, Result::kIllegalTabState); + } +} + +void DebuggerRemoteService::DetachTab(const std::string& destination, + DictionaryValue* response) { + int32 tab_uid = -1; + StringToInt(destination, &tab_uid); + if (tab_uid == -1) { + // Bad tab_uid received from remote debugger (NaN) + response->SetInteger(kDataWide, Result::kUnknownTab); + return; + } + WebContents* web_contents = ToWebContents(tab_uid); + if (web_contents == NULL) { + // Unknown tab + response->SetInteger(kDataWide, Result::kUnknownTab); + } else { + DevToolsManager* manager = g_browser_process->devtools_manager(); + if (manager != NULL) { + DevToolsClientHost* client_host = + manager->GetDevToolsClientHostFor(*web_contents); + if (client_host != NULL) { + manager->ForwardToDevToolsAgent( + *client_host, DevToolsAgentMsg_Detach()); + client_host->InspectedTabClosing(); + response->SetInteger(kDataWide, Result::kOk); + } else { + // No client host registered + response->SetInteger(kDataWide, Result::kUnknownTab); + } + } else { + // No DevToolsManager + response->SetInteger(kResultWide, Result::kDebuggerError); + } + } +} |