diff options
author | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-27 11:54:39 +0000 |
---|---|---|
committer | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-27 11:54:39 +0000 |
commit | 87b603ad919c43e94758d36fd0ba0d3eca2382d5 (patch) | |
tree | 7ae907cbe7bd215324ca8203f605e109aa6e124c /webkit | |
parent | c13fcbd8fa1d88271f31da179fe920bb08007c55 (diff) | |
download | chromium_src-87b603ad919c43e94758d36fd0ba0d3eca2382d5.zip chromium_src-87b603ad919c43e94758d36fd0ba0d3eca2382d5.tar.gz chromium_src-87b603ad919c43e94758d36fd0ba0d3eca2382d5.tar.bz2 |
1. Implemented an agent providing RPC interface to v8 debugger of the inspected page.
2. Introduce new devtools IPC message to distinguish debugger messages and process them on IO thread so that debugger commands can be processed when v8 is stopped on a breakpoint bloking the render thread.
3. Added RPC message to allow devtool client evaluating JS expressions in the context of the inspected page.
Review URL: http://codereview.chromium.org/42594
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12639 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/SConscript | 5 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent.h | 21 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.cc | 28 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.h | 27 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_manager.cc | 88 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_manager.h | 51 | ||||
-rw-r--r-- | webkit/glue/devtools/js/debugger_agent.js | 201 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools.html | 1 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools.js | 49 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools_host_stub.js | 26 | ||||
-rw-r--r-- | webkit/glue/devtools/js/inspector_controller_impl.js | 42 | ||||
-rw-r--r-- | webkit/glue/devtools/tools_agent.h | 8 | ||||
-rw-r--r-- | webkit/glue/glue.vcproj | 24 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent.h | 5 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent_impl.cc | 33 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent_impl.h | 11 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsclient_delegate.h | 1 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsclient_impl.cc | 44 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsclient_impl.h | 3 | ||||
-rw-r--r-- | webkit/webkit.gyp | 5 |
20 files changed, 661 insertions, 12 deletions
diff --git a/webkit/glue/SConscript b/webkit/glue/SConscript index 124b7fa..5e364ae 100644 --- a/webkit/glue/SConscript +++ b/webkit/glue/SConscript @@ -46,6 +46,11 @@ input_files = [ 'devtools/devtools_rpc.cc', 'devtools/devtools_rpc.h', 'devtools/devtools_rpc_js.h', + 'devtools/debugger_agent.h', + 'devtools/debugger_agent_impl.cc', + 'devtools/debugger_agent_impl.h', + 'devtools/debugger_agent_manager.cc', + 'devtools/debugger_agent_manager.h', 'devtools/dom_agent.h', 'devtools/dom_agent_impl.cc', 'devtools/dom_agent_impl.h', diff --git a/webkit/glue/devtools/debugger_agent.h b/webkit/glue/devtools/debugger_agent.h new file mode 100644 index 0000000..a3d6fe0 --- /dev/null +++ b/webkit/glue/devtools/debugger_agent.h @@ -0,0 +1,21 @@ +// 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. + +#ifndef WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_H_ +#define WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_H_ + +#include "webkit/glue/devtools/devtools_rpc.h" + +#define DEBUGGER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ + /* Stops v8 execution as soon as it gets control. */ \ + METHOD0(DebugBreak) + +DEFINE_RPC_CLASS(DebuggerAgent, DEBUGGER_AGENT_STRUCT) + +#define DEBUGGER_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ + METHOD1(DebuggerOutput, std::string /* output text */) + +DEFINE_RPC_CLASS(DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT) + +#endif // WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_H_ diff --git a/webkit/glue/devtools/debugger_agent_impl.cc b/webkit/glue/devtools/debugger_agent_impl.cc new file mode 100644 index 0000000..fde98cb --- /dev/null +++ b/webkit/glue/devtools/debugger_agent_impl.cc @@ -0,0 +1,28 @@ +// 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 "config.h" + +#include <wtf/Assertions.h> +#undef LOG + +#include "webkit/glue/devtools/debugger_agent_impl.h" +#include "webkit/glue/devtools/debugger_agent_manager.h" + +DebuggerAgentImpl::DebuggerAgentImpl(DebuggerAgentDelegate* delegate) + : delegate_(delegate) { + DebuggerAgentManager::DebugAttach(this); +} + +DebuggerAgentImpl::~DebuggerAgentImpl() { + DebuggerAgentManager::DebugDetach(this); +} + +void DebuggerAgentImpl::DebugBreak() { + // TODO(yurys): implement +} + +void DebuggerAgentImpl::DebuggerOutput(const std::string& command) { + delegate_->DebuggerOutput(command); +} diff --git a/webkit/glue/devtools/debugger_agent_impl.h b/webkit/glue/devtools/debugger_agent_impl.h new file mode 100644 index 0000000..2eb6411 --- /dev/null +++ b/webkit/glue/devtools/debugger_agent_impl.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_IMPL_H_ +#define WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_IMPL_H_ + +#include "webkit/glue/devtools/debugger_agent.h" + +class DebuggerAgentImpl : public DebuggerAgent { + public: + explicit DebuggerAgentImpl(DebuggerAgentDelegate* delegate); + virtual ~DebuggerAgentImpl(); + + // DebuggerAgent implementation. + virtual void DebugBreak(); + + void DebuggerOutput(const std::string& out); + + private: + + DebuggerAgentDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(DebuggerAgentImpl); +}; + +#endif // WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_IMPL_H_ diff --git a/webkit/glue/devtools/debugger_agent_manager.cc b/webkit/glue/devtools/debugger_agent_manager.cc new file mode 100644 index 0000000..d6ab21c --- /dev/null +++ b/webkit/glue/devtools/debugger_agent_manager.cc @@ -0,0 +1,88 @@ +// 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 "config.h" + +#include <wtf/HashSet.h> +#undef LOG + +#include "base/string_util.h" +#include "webkit/glue/devtools/debugger_agent_impl.h" +#include "webkit/glue/devtools/debugger_agent_manager.h" + +#if USE(V8) +#include "v8/include/v8-debug.h" +#endif + +// static +void DebuggerAgentManager::V8DebugMessageHandler(const uint16_t* message, + int length, + void* data) { +#if USE(V8) + std::wstring out(reinterpret_cast<const wchar_t*>(message), length); + std::string out_utf8 = WideToUTF8(out); + DebuggerAgentManager::DebuggerOutput(out_utf8); +#endif +} + +// static +DebuggerAgentManager::AttachedAgentsSet* + DebuggerAgentManager::attached_agents_ = NULL; + +// static +void DebuggerAgentManager::DebugAttach(DebuggerAgentImpl* debugger_agent) { +#if USE(V8) + if (!attached_agents_) { + attached_agents_ = new AttachedAgentsSet(); + v8::Debug::SetMessageHandler(&DebuggerAgentManager::V8DebugMessageHandler); + } + attached_agents_->add(debugger_agent); +#endif +} + +// static +void DebuggerAgentManager::DebugDetach(DebuggerAgentImpl* debugger_agent) { +#if USE(V8) + if (!attached_agents_) { + NOTREACHED(); + return; + } + DCHECK(attached_agents_->contains(debugger_agent)); + attached_agents_->remove(debugger_agent); + if (attached_agents_->isEmpty()) { + v8::Debug::SetMessageHandler(NULL); + delete attached_agents_; + attached_agents_ = NULL; + } +#endif +} + +// static +void DebuggerAgentManager::DebuggerOutput(const std::string& out) { + DebuggerAgentImpl* agent = GetAgentForCurrentV8Context(); + if (!agent) { + return; + } + agent->DebuggerOutput(out); +} + +// static +void DebuggerAgentManager::ExecuteDebuggerCommand(const std::string& command) { +#if USE(V8) + std::wstring cmd_wstring = UTF8ToWide(command); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd_wstring.data()), + cmd_wstring.length()); +#endif +} + +// static +DebuggerAgentImpl* DebuggerAgentManager::GetAgentForCurrentV8Context() { + 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(); +} diff --git a/webkit/glue/devtools/debugger_agent_manager.h b/webkit/glue/devtools/debugger_agent_manager.h new file mode 100644 index 0000000..380bb0d --- /dev/null +++ b/webkit/glue/devtools/debugger_agent_manager.h @@ -0,0 +1,51 @@ +// 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. + +#ifndef WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_MANAGER_H_ +#define WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_MANAGER_H_ + +#include <wtf/HashSet.h> + +#include "base/basictypes.h" +#include "v8/include/v8-debug.h" + +class DebuggerAgentImpl; + +// 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 +// to the v8 debugger. This class coordinates communication between the debug +// agents and v8 debugger. It will set debug output handler as long as at least +// one debugger agent is attached and remove it when last debugger agent is +// detached. When message is received from debugger it will route it to the +// right debugger agent if there is one otherwise the message will be ignored. +// +// TODO(yurys): v8 may send a message(e.g. exception event) after which it +// would expect some actions from the handler. If there is no appropriate +// debugger agent to handle such messages the manager should perform the action +// itself, otherwise v8 may hang waiting for the action. +class DebuggerAgentManager { + public: + static void DebugAttach(DebuggerAgentImpl* debugger_agent); + static void DebugDetach(DebuggerAgentImpl* debugger_agent); + static void DebugCommand(const std::string& command); + + static void ExecuteDebuggerCommand(const std::string& command); + + private: + DebuggerAgentManager(); + ~DebuggerAgentManager(); + + static void V8DebugMessageHandler(const uint16_t* message, + int length, + void* data); + static void DebuggerOutput(const std::string& out); + static DebuggerAgentImpl* GetAgentForCurrentV8Context(); + + typedef HashSet<DebuggerAgentImpl*> AttachedAgentsSet; + static AttachedAgentsSet* attached_agents_; + + DISALLOW_COPY_AND_ASSIGN(DebuggerAgentManager); +}; + +#endif // WEBKIT_GLUE_DEVTOOLS_DEBUGGER_AGENT_MANAGER_H_ diff --git a/webkit/glue/devtools/js/debugger_agent.js b/webkit/glue/devtools/js/debugger_agent.js new file mode 100644 index 0000000..d1edb4d --- /dev/null +++ b/webkit/glue/devtools/js/debugger_agent.js @@ -0,0 +1,201 @@ +// 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. + +/** + * @fileoverview Provides communication interface to remote v8 debugger. See + * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol + */ +goog.provide('devtools.DebuggerAgent'); + + +/** + * @constructor + */ +devtools.DebuggerAgent = function() { + RemoteDebuggerAgent.DebuggerOutput = + goog.bind(this.handleDebuggerOutput_, this); +}; + + +/** + * Asynchronously requests for all parsed script sources. Response will be + * processed in handleScriptsResponse_. + */ +devtools.DebuggerAgent.prototype.requestScripts = function() { + var cmd = new devtools.DebugCommand("scripts");
+ RemoteDebuggerCommandExecutor.DebuggerCommand(cmd.toJSONProtocol());
+ // Force v8 execution so that it gets to processing the requested command. + devtools.tools.evaluateJavaSctipt("javascript:void(0)");
+}; + + +/** + * Handles output sent by v8 debugger. The output is either asynchronous event + * or response to a previously sent request. See protocol definitioun for more + * details on the output format. + * @param {string} output + */ +devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) { + debugPrint("handleDebuggerOutput_: " + output) + var msg; + try { + msg = new devtools.DebuggerMessage(output); + } catch(e) { + debugPrint("Failed to handle debugger reponse:\n" + e); + throw e; + } + + if (response.getType() == "response") { + if (msg.getCommand() == "scripts") { + this.handleScriptsResponse_(msg); + } + } +}; + + +/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { + debugPrint("handleScriptsResponse_: " + msg) +}; + + +
+/**
+ * JSON based commands sent to v8 debugger.
+ * @constructor
+ */
+devtools.DebugCommand = function(command, opt_arguments) {
+ this.command_ = command;
+ this.type_ = "request";
+ this.seq_ = ++devtools.DebugCommand.nextSeq_;
+ if (opt_arguments) {
+ this.arguments_ = opt_arguments;
+ }
+};
+
+
+/**
+ * Next unique number to be used as debugger request sequence number.
+ * @type {number}
+ */
+devtools.DebugCommand.nextSeq_ = 1;
+
+
+/**
+ * @return {number}
+ */
+devtools.DebugCommand.prototype.getSequenceNumber = function() {
+ return this.seq_;
+};
+
+
+/**
+ * @return {string}
+ */
+devtools.DebugCommand.prototype.toJSONProtocol = function() {
+ var json = {
+ 'seq': this.seq_,
+ 'type': this.type_,
+ 'command': this.command_
+ }
+ if (this.arguments_) {
+ json.arguments = this.arguments_;
+ }
+ return goog.json.serialize(json);
+};
+ + + +/** + * JSON messages sent from v8 debugger. See protocol definition for more + * details: http://code.google.com/p/v8/wiki/DebuggerProtocol + * @param {string} msg Raw protocol packet as JSON string. + * @constructor + */ +devtools.DebuggerMessage = function(msg) { + this.packet_ = msg; + this.refs_ = []; + if (this.packet_.refs) { + for (var i = 0; i < this.packet_.refs.length; i++) { + this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; + } + } +}; + + +/** + * @return {string} The packet type. + */ +devtools.DebuggerMessage.prototype.getType = function() { + return this.packet_.type; +}; + + +/** + * @return {?string} The packet event if the message is an event. + */ +devtools.DebuggerMessage.prototype.getEvent = function() { + return this.packet_.event; +}; + + +/** + * @return {?string} The packet command if the message is a response to a + * command. + */ +devtools.DebuggerMessage.prototype.getCommand = function() { + return this.packet_.command; +}; + + +/** + * @return {number} The packet request sequence. + */ +devtools.DebuggerMessage.prototype.getRequestSeq = function() { + return this.packet_.request_seq; +}; + + +/** + * @return {number} Whether the v8 is running after processing the request. + */ +devtools.DebuggerMessage.prototype.isRunning = function() { + return this.packet_.running ? true : false; +}; + + +/** + * @return {boolean} Whether the request succeeded. + */ +devtools.DebuggerMessage.prototype.isSuccess = function() { + return this.packet_.success ? true : false; +}; + + +/** + * @return {string} + */ +devtools.DebuggerMessage.prototype.getMessage = function() { + return this.packet_.message; +}; + + +/** + * @return {Object} Parsed message body json. + */ +devtools.DebuggerMessage.prototype.getBody = function() { + return this.packet_.body; +}; + + +/** + * @param {number} handle Object handle. + * @return {?Object} Returns the object with the handle if it was sent in this + * message(some objects referenced by handles may be missing in the message). + */ +devtools.DebuggerMessage.prototype.lookup = function(handle) { + return this.refs_[handle]; +}; diff --git a/webkit/glue/devtools/js/devtools.html b/webkit/glue/devtools/js/devtools.html index d9684d1..2e995d0 100644 --- a/webkit/glue/devtools/js/devtools.html +++ b/webkit/glue/devtools/js/devtools.html @@ -48,6 +48,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="utilities.js"></script> <script type="text/javascript" src="treeoutline.js"></script> <script type="text/javascript" src="devtools_callback.js"></script> + <script type="text/javascript" src="debugger_agent.js"></script> <script type="text/javascript" src="dom_agent.js"></script> <script type="text/javascript" src="net_agent.js"></script> <script type="text/javascript" src="inspector_controller.js"></script> diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js index 7456bd9..10a5ab9 100644 --- a/webkit/glue/devtools/js/devtools.js +++ b/webkit/glue/devtools/js/devtools.js @@ -9,14 +9,17 @@ */ goog.provide('devtools.Tools'); +goog.require('devtools.DebuggerAgent'); goog.require('devtools.DomAgent'); goog.require('devtools.NetAgent'); devtools.ToolsAgent = function() { + RemoteToolsAgent.DidEvaluateJavaSctipt = devtools.Callback.processCallback; RemoteToolsAgent.UpdateFocusedNode = goog.bind(this.updateFocusedNode, this); RemoteToolsAgent.FrameNavigate = goog.bind(this.frameNavigate, this); + this.debuggerAgent_ = new devtools.DebuggerAgent(); this.domAgent_ = new devtools.DomAgent(); this.netAgent_ = new devtools.NetAgent(); this.reset(); @@ -34,6 +37,24 @@ devtools.ToolsAgent.prototype.reset = function() { /** + * @param {string} script Sctipt exression to be evaluated in the context of the + * inspected page. + * @param {Function} callback + */ +devtools.ToolsAgent.prototype.evaluateJavaSctipt = function(script, callback) { + var callbackId = devtools.Callback.wrap(callback); + RemoteToolsAgent.EvaluateJavaSctipt(callbackId, script); +}; + + +/** + * @return {devtools.DebuggerAgent} Debugger agent instance. + */ +devtools.ToolsAgent.prototype.getDebuggerAgent = function() { + return this.debuggerAgent_; +}; + +/** * DomAgent accessor. * @return {devtools.DomAgent} Dom agent instance. */ @@ -77,7 +98,6 @@ devtools.ToolsAgent.prototype.setEnabled = function(enabled) { }; - /** * Evaluates js expression. * @param {string} expr @@ -87,11 +107,35 @@ devtools.ToolsAgent.prototype.evaluate = function(expr) { }; +/** + * Prints string to the inspector console or shows alert if the console doesn't + * exist. + * @param {string} text + */ +function debugPrint(text) { + var console = WebInspector.console;
+ if (console) {
+ console.addMessage(new WebInspector.ConsoleMessage(
+ "", undefined, 1, "", undefined, 1, text));
+ } else {
+ alert(text);
+ }
+} + + // Frontend global objects. -var devtools.tools; + + +/** + * Global instance of the tools agent. + * @type {devtools.ToolsAgent} + */ +devtools.tools = null; + var context = {}; // Used by WebCore's inspector routines. + /////////////////////////////////////////////////////////////////////////////// // Here and below are overrides to existing WebInspector methods only. // TODO(pfeldman): Patch WebCore and upstream changes. @@ -103,6 +147,7 @@ WebInspector.loaded = function() { oldLoaded.call(this); DevToolsHost.loaded(); + devtools.tools.getDebuggerAgent().requestScripts(); }; diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js index a0a696b..ddd7609 100644 --- a/webkit/glue/devtools/js/devtools_host_stub.js +++ b/webkit/glue/devtools/js/devtools_host_stub.js @@ -10,6 +10,25 @@ /** * @constructor */ +RemoteDebuggerAgentStub = function() { +}; + +RemoteDebuggerAgentStub.prototype.DebugAttach = function() { +}; + +RemoteDebuggerAgentStub.prototype.DebugDetach = function() { +}; + +RemoteDebuggerAgentStub.prototype.DebugCommand = function() { +}; + +RemoteDebuggerAgentStub.prototype.DebugBreak = function() { +}; + + +/** + * @constructor + */ RemoteDomAgentStub = function() { }; @@ -122,6 +141,12 @@ RemoteToolsAgentStub.prototype.evaluate = function(expr) { window.eval(expr); }; +RemoteToolsAgentStub.prototype.EvaluateJavaSctipt = function(callId, script) { + setTimeout(function() { + var result = eval(script); + RemoteToolsAgent.DidEvaluateJavaSctipt(callId, result); + }, 0); +}; /** * @constructor @@ -146,6 +171,7 @@ DevToolsHostStub.prototype.loaded = function() { if (!window['DevToolsHost']) { + window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub(); window['RemoteDomAgent'] = new RemoteDomAgentStub(); window['RemoteNetAgent'] = new RemoteNetAgentStub(); window['RemoteToolsAgent'] = new RemoteToolsAgentStub(); diff --git a/webkit/glue/devtools/js/inspector_controller_impl.js b/webkit/glue/devtools/js/inspector_controller_impl.js index 9c6028c..9540516 100644 --- a/webkit/glue/devtools/js/inspector_controller_impl.js +++ b/webkit/glue/devtools/js/inspector_controller_impl.js @@ -33,7 +33,7 @@ goog.inherits(devtools.InspectorControllerImpl, * {@inheritDoc}. */ devtools.InspectorControllerImpl.prototype.hiddenPanels = function() { - return "scripts,profiles,databases"; + return "profiles,databases"; }; @@ -53,7 +53,7 @@ devtools.InspectorControllerImpl.prototype.addSourceToFrame = /** * {@inheritDoc}. */ -devtools.InspectorController.prototype.addResourceSourceToFrame = +devtools.InspectorControllerImpl.prototype.addResourceSourceToFrame = function(identifier, element) { var self = this; tools.getNetAgent().getResourceContentAsync(identifier, function(source) { @@ -89,4 +89,42 @@ devtools.InspectorControllerImpl.prototype.inspectedWindow = function() { }; +/** + * @override + */ +devtools.InspectorControllerImpl.prototype.debuggerEnabled = function() {
+ return true;
+};
+ + +devtools.InspectorControllerImpl.prototype.currentCallFrame = function() {
+ // TODO(yurys);
+ return null;
+};
+ + +devtools.InspectorControllerImpl.prototype.removeBreakpoint = function(
+ sourceID, line) {
+};
+
+
+devtools.InspectorControllerImpl.prototype.resumeDebugger = function() {
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepIntoStatementInDebugger =
+ function() {
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOutOfFunctionInDebugger =
+ function() {
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOverStatementInDebugger =
+ function() {
+};
+ + var InspectorController = new devtools.InspectorControllerImpl(); diff --git a/webkit/glue/devtools/tools_agent.h b/webkit/glue/devtools/tools_agent.h index cc905bc..a2e1b18 100644 --- a/webkit/glue/devtools/tools_agent.h +++ b/webkit/glue/devtools/tools_agent.h @@ -17,7 +17,10 @@ METHOD1(HighlightDOMNode, int /* node_id */) \ \ /* Clears Dom Node highlight. */ \ - METHOD0(HideDOMNodeHighlight) + METHOD0(HideDOMNodeHighlight) \ + \ + /* Executes JavaScript in the context of the inspected window. */ \ + METHOD2(EvaluateJavaSctipt, int /* call_id */, String /* JS expression */) DEFINE_RPC_CLASS(ToolsAgent, TOOLS_AGENT_STRUCT) @@ -25,6 +28,9 @@ DEFINE_RPC_CLASS(ToolsAgent, TOOLS_AGENT_STRUCT) /* Updates focused node on the client. */ \ METHOD1(UpdateFocusedNode, int /* node_id */) \ \ + /* Response message to EvaluateJavaSctipt. */ \ + METHOD2(DidEvaluateJavaSctipt, int /* call_id */, String /* result */) \ + \ /* Updates focused node on the client. */ \ METHOD2(FrameNavigate, std::string /* url */, bool /* top_level */) diff --git a/webkit/glue/glue.vcproj b/webkit/glue/glue.vcproj index 7884ffe..8e166c4 100644 --- a/webkit/glue/glue.vcproj +++ b/webkit/glue/glue.vcproj @@ -883,6 +883,26 @@ Name="DevTools" > <File + RelativePath=".\devtools\debugger_agent.h" + > + </File> + <File + RelativePath=".\devtools\debugger_agent_impl.cc" + > + </File> + <File + RelativePath=".\devtools\debugger_agent_impl.h" + > + </File> + <File + RelativePath=".\devtools\debugger_agent_manager.cc" + > + </File> + <File + RelativePath=".\devtools\debugger_agent_manager.h" + > + </File> + <File RelativePath=".\devtools\devtools_rpc.cc" > </File> @@ -930,6 +950,10 @@ > </File> <File + RelativePath=".\devtools\js\debugger_agent.js" + > + </File> + <File RelativePath=".\devtools\js\devtools.html" > </File> diff --git a/webkit/glue/webdevtoolsagent.h b/webkit/glue/webdevtoolsagent.h index 02600f6..3f4f3937 100644 --- a/webkit/glue/webdevtoolsagent.h +++ b/webkit/glue/webdevtoolsagent.h @@ -16,8 +16,11 @@ class WebDevToolsAgent { virtual ~WebDevToolsAgent() {} virtual void DispatchMessageFromClient(const std::string& raw_msg) = 0; - virtual void InspectElement(int x, int y) = 0; + + // Asynchronously executes debugger command in the render thread. + static void ExecuteDebuggerCommand(const std::string& command); + private: DISALLOW_COPY_AND_ASSIGN(WebDevToolsAgent); }; diff --git a/webkit/glue/webdevtoolsagent_impl.cc b/webkit/glue/webdevtoolsagent_impl.cc index 1c41145..a096152 100644 --- a/webkit/glue/webdevtoolsagent_impl.cc +++ b/webkit/glue/webdevtoolsagent_impl.cc @@ -12,10 +12,13 @@ #include "Node.h" #include "Page.h" #include "PlatformString.h" +#include "ScriptValue.h" #include <wtf/OwnPtr.h> #undef LOG #include "base/values.h" +#include "webkit/glue/devtools/debugger_agent_impl.h" +#include "webkit/glue/devtools/debugger_agent_manager.h" #include "webkit/glue/devtools/dom_agent_impl.h" #include "webkit/glue/devtools/net_agent_impl.h" #include "webkit/glue/glue_util.h" @@ -29,6 +32,7 @@ using WebCore::Document; using WebCore::InspectorController; using WebCore::Node; using WebCore::Page; +using WebCore::ScriptValue; using WebCore::String; WebDevToolsAgentImpl::WebDevToolsAgentImpl( @@ -38,6 +42,7 @@ WebDevToolsAgentImpl::WebDevToolsAgentImpl( web_view_impl_(web_view_impl), document_(NULL), enabled_(false) { + debugger_agent_delegate_stub_.reset(new DebuggerAgentDelegateStub(this)); dom_agent_delegate_stub_.reset(new DomAgentDelegateStub(this)); net_agent_delegate_stub_.reset(new NetAgentDelegateStub(this)); tools_agent_delegate_stub_.reset(new ToolsAgentDelegateStub(this)); @@ -48,6 +53,8 @@ WebDevToolsAgentImpl::~WebDevToolsAgentImpl() { void WebDevToolsAgentImpl::SetEnabled(bool enabled) { if (enabled && !enabled_) { + debugger_agent_impl_.reset(new DebuggerAgentImpl( + debugger_agent_delegate_stub_.get())); dom_agent_impl_.reset(new DomAgentImpl(dom_agent_delegate_stub_.get())); net_agent_impl_.reset(new NetAgentImpl(net_agent_delegate_stub_.get())); if (document_) { @@ -56,6 +63,7 @@ void WebDevToolsAgentImpl::SetEnabled(bool enabled) { } enabled_ = true; } else if (!enabled) { + debugger_agent_impl_.reset(NULL); dom_agent_impl_.reset(NULL); net_agent_impl_.reset(NULL); enabled_ = false; @@ -108,6 +116,19 @@ void WebDevToolsAgentImpl::HideDOMNodeHighlight() { page->inspectorController()->hideHighlight(); } +void WebDevToolsAgentImpl::EvaluateJavaSctipt(int call_id, const String& js) { + Page* page = web_view_impl_->page(); + if (!page->mainFrame()) { + return; + } + ScriptValue result = page->mainFrame()->loader()->executeScript(js); + String result_string; + if (!result.hasNoValue()) { + result_string = result.toString(NULL); + } + tools_agent_delegate_stub_->DidEvaluateJavaSctipt(call_id, result_string); +} + void WebDevToolsAgentImpl::DispatchMessageFromClient( const std::string& raw_msg) { OwnPtr<ListValue> message( @@ -117,6 +138,13 @@ void WebDevToolsAgentImpl::DispatchMessageFromClient( if (!enabled_) return; + + if (debugger_agent_impl_.get() && + DebuggerAgentDispatch::Dispatch( + debugger_agent_impl_.get(), + *message.get())) + return; + if (DomAgentDispatch::Dispatch(dom_agent_impl_.get(), *message.get())) return; if (NetAgentDispatch::Dispatch(net_agent_impl_.get(), *message.get())) @@ -136,3 +164,8 @@ void WebDevToolsAgentImpl::InspectElement(int x, int y) { void WebDevToolsAgentImpl::SendRpcMessage(const std::string& raw_msg) { delegate_->SendMessageToClient(raw_msg); } + +// static +void WebDevToolsAgent::ExecuteDebuggerCommand(const std::string& command) { + DebuggerAgentManager::ExecuteDebuggerCommand(command); +} diff --git a/webkit/glue/webdevtoolsagent_impl.h b/webkit/glue/webdevtoolsagent_impl.h index 454f082..500299b 100644 --- a/webkit/glue/webdevtoolsagent_impl.h +++ b/webkit/glue/webdevtoolsagent_impl.h @@ -20,6 +20,8 @@ class Node; class String; } +class DebuggerAgentDelegateStub; +class DebuggerAgentImpl; class DomAgentImpl; class NetAgentImpl; class Value; @@ -41,6 +43,7 @@ class WebDevToolsAgentImpl virtual void SetEnabled(bool enabled); virtual void HighlightDOMNode(int node_id); virtual void HideDOMNodeHighlight(); + virtual void EvaluateJavaSctipt(int call_id, const String& js); // WebDevToolsAgent implementation. virtual void DispatchMessageFromClient(const std::string& raw_msg); @@ -55,19 +58,19 @@ class WebDevToolsAgentImpl WebFrame* frame, bool is_new_navigation); - DomAgentImpl* dom_agent_impl() { return dom_agent_impl_.get(); } NetAgentImpl* net_agent_impl() { return net_agent_impl_.get(); } - WebViewImpl* web_view_impl() { return web_view_impl_; } private: WebDevToolsAgentDelegate* delegate_; WebViewImpl* web_view_impl_; WebCore::Document* document_; - scoped_ptr<DomAgentImpl> dom_agent_impl_; - scoped_ptr<NetAgentImpl> net_agent_impl_; + scoped_ptr<DebuggerAgentDelegateStub> debugger_agent_delegate_stub_; scoped_ptr<DomAgentDelegateStub> dom_agent_delegate_stub_; scoped_ptr<NetAgentDelegateStub> net_agent_delegate_stub_; scoped_ptr<ToolsAgentDelegateStub> tools_agent_delegate_stub_; + scoped_ptr<DebuggerAgentImpl> debugger_agent_impl_; + scoped_ptr<DomAgentImpl> dom_agent_impl_; + scoped_ptr<NetAgentImpl> net_agent_impl_; bool enabled_; DISALLOW_COPY_AND_ASSIGN(WebDevToolsAgentImpl); }; diff --git a/webkit/glue/webdevtoolsclient_delegate.h b/webkit/glue/webdevtoolsclient_delegate.h index fc1b1d6..77ca962 100644 --- a/webkit/glue/webdevtoolsclient_delegate.h +++ b/webkit/glue/webdevtoolsclient_delegate.h @@ -14,6 +14,7 @@ class WebDevToolsClientDelegate { virtual ~WebDevToolsClientDelegate() {} virtual void SendMessageToAgent(const std::string& raw_msg) = 0; + virtual void SendDebuggerCommandToAgent(const std::string& command) = 0; private: DISALLOW_COPY_AND_ASSIGN(WebDevToolsClientDelegate); diff --git a/webkit/glue/webdevtoolsclient_impl.cc b/webkit/glue/webdevtoolsclient_impl.cc index 67b8974..588da84 100644 --- a/webkit/glue/webdevtoolsclient_impl.cc +++ b/webkit/glue/webdevtoolsclient_impl.cc @@ -20,6 +20,7 @@ #include "base/string_util.h" #include "base/values.h" +#include "webkit/glue/devtools/debugger_agent.h" #include "webkit/glue/devtools/devtools_rpc_js.h" #include "webkit/glue/devtools/dom_agent.h" #include "webkit/glue/devtools/net_agent.h" @@ -37,6 +38,8 @@ using WebCore::Node; using WebCore::Page; using WebCore::String; +DEFINE_RPC_JS_BOUND_OBJ(DebuggerAgent, DEBUGGER_AGENT_STRUCT, + DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT) DEFINE_RPC_JS_BOUND_OBJ(DomAgent, DOM_AGENT_STRUCT, DomAgentDelegate, DOM_AGENT_DELEGATE_STRUCT) DEFINE_RPC_JS_BOUND_OBJ(NetAgent, NET_AGENT_STRUCT, @@ -44,6 +47,35 @@ DEFINE_RPC_JS_BOUND_OBJ(NetAgent, NET_AGENT_STRUCT, DEFINE_RPC_JS_BOUND_OBJ(ToolsAgent, TOOLS_AGENT_STRUCT, ToolsAgentDelegate, TOOLS_AGENT_DELEGATE_STRUCT) +namespace { + +class RemoteDebuggerCommandExecutor : public CppBoundClass { + public: + RemoteDebuggerCommandExecutor( + WebDevToolsClientDelegate* delegate, + WebFrame* frame, + const std::wstring& classname) + : delegate_(delegate) { + BindToJavascript(frame, classname); + BindMethod("DebuggerCommand", + &RemoteDebuggerCommandExecutor::DebuggerCommand); + } + virtual ~RemoteDebuggerCommandExecutor() {} + + // The DebuggerCommand() function provided to Javascript. + void DebuggerCommand(const CppArgumentList& args, CppVariant* result) { + std::string command = args[0].ToString(); + result->SetNull(); + delegate_->SendDebuggerCommandToAgent(command); + } + + private: + WebDevToolsClientDelegate* delegate_; + DISALLOW_COPY_AND_ASSIGN(RemoteDebuggerCommandExecutor); +}; + +} // namespace + /*static*/ WebDevToolsClient* WebDevToolsClient::Create( WebView* view, @@ -58,9 +90,16 @@ WebDevToolsClientImpl::WebDevToolsClientImpl( delegate_(delegate), loaded_(false) { WebFrame* frame = web_view_impl_->GetMainFrame(); + + // Debugger commands should be sent using special method. + debugger_command_executor_obj_.set(new RemoteDebuggerCommandExecutor( + delegate, frame, L"RemoteDebuggerCommandExecutor")); + debugger_agent_obj_.set(new JsDebuggerAgentBoundObj( + this, frame, L"RemoteDebuggerAgent")); dom_agent_obj_.set(new JsDomAgentBoundObj(this, frame, L"RemoteDomAgent")); net_agent_obj_.set(new JsNetAgentBoundObj(this, frame, L"RemoteNetAgent")); - tools_agent_obj_.set(new JsToolsAgentBoundObj(this, frame, L"RemoteToolsAgent")); + tools_agent_obj_.set( + new JsToolsAgentBoundObj(this, frame, L"RemoteToolsAgent")); BindToJavascript(frame, L"DevToolsHost"); BindMethod("addSourceToFrame", &WebDevToolsClientImpl::JsAddSourceToFrame); @@ -82,7 +121,8 @@ void WebDevToolsClientImpl::DispatchMessageFromAgent( std::string expr; if (dom_agent_obj_->Dispatch(*message.get(), &expr) || net_agent_obj_->Dispatch(*message.get(), &expr) - || tools_agent_obj_->Dispatch(*message.get(), &expr)) { + || tools_agent_obj_->Dispatch(*message.get(), &expr) + || debugger_agent_obj_->Dispatch(*message.get(), &expr)) { web_view_impl_->GetMainFrame()->ExecuteScript(expr); } } diff --git a/webkit/glue/webdevtoolsclient_impl.h b/webkit/glue/webdevtoolsclient_impl.h index b2877a9..3309eeb 100644 --- a/webkit/glue/webdevtoolsclient_impl.h +++ b/webkit/glue/webdevtoolsclient_impl.h @@ -17,6 +17,7 @@ namespace WebCore { class String; } +class JsDebuggerAgentBoundObj; class JsDomAgentBoundObj; class JsNetAgentBoundObj; class JsToolsAgentBoundObj; @@ -44,6 +45,8 @@ class WebDevToolsClientImpl : public WebDevToolsClient, WebViewImpl* web_view_impl_; WebDevToolsClientDelegate* delegate_; + OwnPtr<CppBoundClass> debugger_command_executor_obj_; + OwnPtr<JsDebuggerAgentBoundObj> debugger_agent_obj_; OwnPtr<JsDomAgentBoundObj> dom_agent_obj_; OwnPtr<JsNetAgentBoundObj> net_agent_obj_; OwnPtr<JsToolsAgentBoundObj> tools_agent_obj_; diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index 1db3b81..1b05b40 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -4204,6 +4204,11 @@ 'glue/devtools/devtools_rpc.cc', 'glue/devtools/devtools_rpc.h', 'glue/devtools/devtools_rpc_js.h', + 'glue/devtools/debugger_agent.h', + 'glue/devtools/debugger_agent_impl.cc', + 'glue/devtools/debugger_agent_impl.h', + 'glue/devtools/debugger_agent_manager.cc', + 'glue/devtools/debugger_agent_manager.h', 'glue/devtools/dom_agent.h', 'glue/devtools/dom_agent_impl.cc', 'glue/devtools/dom_agent_impl.h', |