diff options
author | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-30 08:19:40 +0000 |
---|---|---|
committer | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-30 08:19:40 +0000 |
commit | 46ce4c7d272138e15282ee102f9c6ff0508353c7 (patch) | |
tree | b0e00ae8d60ae169aa27f7cb8a522a8b255c21d1 /webkit/glue | |
parent | 646dce40970192643ce533518888dfaf9c736815 (diff) | |
download | chromium_src-46ce4c7d272138e15282ee102f9c6ff0508353c7.zip chromium_src-46ce4c7d272138e15282ee102f9c6ff0508353c7.tar.gz chromium_src-46ce4c7d272138e15282ee102f9c6ff0508353c7.tar.bz2 |
DevTools: Implement basic DOM edit operations.
Review URL: http://codereview.chromium.org/56005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12765 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/devtools/debugger_agent.h | 6 | ||||
-rw-r--r-- | webkit/glue/devtools/devtools_rpc.h | 72 | ||||
-rw-r--r-- | webkit/glue/devtools/devtools_rpc_js.h | 447 | ||||
-rw-r--r-- | webkit/glue/devtools/dom_agent.h | 17 | ||||
-rw-r--r-- | webkit/glue/devtools/dom_agent_impl.cc | 28 | ||||
-rw-r--r-- | webkit/glue/devtools/dom_agent_impl.h | 11 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools.js | 2 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools_host_stub.js | 29 | ||||
-rw-r--r-- | webkit/glue/devtools/js/dom_agent.js | 168 | ||||
-rw-r--r-- | webkit/glue/devtools/net_agent.h | 5 | ||||
-rw-r--r-- | webkit/glue/devtools/tools_agent.h | 5 |
11 files changed, 537 insertions, 253 deletions
diff --git a/webkit/glue/devtools/debugger_agent.h b/webkit/glue/devtools/debugger_agent.h index a3d6fe0..213cf28 100644 --- a/webkit/glue/devtools/debugger_agent.h +++ b/webkit/glue/devtools/debugger_agent.h @@ -7,13 +7,15 @@ #include "webkit/glue/devtools/devtools_rpc.h" -#define DEBUGGER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define DEBUGGER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, \ + METHOD4) \ /* 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) \ +#define DEBUGGER_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, \ + METHOD4) \ METHOD1(DebuggerOutput, std::string /* output text */) DEFINE_RPC_CLASS(DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT) diff --git a/webkit/glue/devtools/devtools_rpc.h b/webkit/glue/devtools/devtools_rpc.h index 6f134ba..1fca50d 100644 --- a/webkit/glue/devtools/devtools_rpc.h +++ b/webkit/glue/devtools/devtools_rpc.h @@ -6,7 +6,7 @@ // implementation. The client is responsible for defining the Rpc-enabled // interface in terms of its macros: // -// #define MYAPI_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) +// #define MYAPI_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4) // METHOD0(Method1) // METHOD3(Method2, int, String, Value) // METHOD1(Method3, int) @@ -122,10 +122,17 @@ struct RpcTypeTrait<std::string> { RpcTypeTrait<T2>::ApiType t2, \ RpcTypeTrait<T3>::ApiType t3) = 0; +#define TOOLS_RPC_API_METHOD4(Method, T1, T2, T3, T4) \ + virtual void Method(RpcTypeTrait<T1>::ApiType t1, \ + RpcTypeTrait<T2>::ApiType t2, \ + RpcTypeTrait<T3>::ApiType t3, \ + RpcTypeTrait<T4>::ApiType t4) = 0; + #define TOOLS_RPC_ENUM_LITERAL0(Method) METHOD_##Method, #define TOOLS_RPC_ENUM_LITERAL1(Method, T1) METHOD_##Method, #define TOOLS_RPC_ENUM_LITERAL2(Method, T1, T2) METHOD_##Method, #define TOOLS_RPC_ENUM_LITERAL3(Method, T1, T2, T3) METHOD_##Method, +#define TOOLS_RPC_ENUM_LITERAL4(Method, T1, T2, T3, T4) METHOD_##Method, /////////////////////////////////////////////////////// // RPC stub method implementations @@ -154,6 +161,15 @@ struct RpcTypeTrait<std::string> { &t3); \ } +#define TOOLS_RPC_STUB_METHOD4(Method, T1, T2, T3, T4) \ + virtual void Method(RpcTypeTrait<T1>::ApiType t1, \ + RpcTypeTrait<T2>::ApiType t2, \ + RpcTypeTrait<T3>::ApiType t3, \ + RpcTypeTrait<T4>::ApiType t4) { \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2, \ + &t3, &t4); \ + } + /////////////////////////////////////////////////////// // RPC dispatch method implementations @@ -201,6 +217,25 @@ case CLASS::METHOD_##Method: { \ return true; \ } +#define TOOLS_RPC_DISPATCH4(Method, T1, T2, T3, T4) \ +case CLASS::METHOD_##Method: { \ + RpcTypeTrait<T1>::DispatchType t1; \ + RpcTypeTrait<T2>::DispatchType t2; \ + RpcTypeTrait<T3>::DispatchType t3; \ + RpcTypeTrait<T4>::DispatchType t4; \ + DevToolsRpc::GetListValue(message, 2, &t1); \ + DevToolsRpc::GetListValue(message, 3, &t2); \ + DevToolsRpc::GetListValue(message, 4, &t3); \ + DevToolsRpc::GetListValue(message, 5, &t4); \ + delegate->Method( \ + RpcTypeTrait<T1>::Pass(t1), \ + RpcTypeTrait<T2>::Pass(t2), \ + RpcTypeTrait<T3>::Pass(t3), \ + RpcTypeTrait<T4>::Pass(t4) \ + ); \ + return true; \ +} + #define TOOLS_END_RPC_DISPATCH() \ } @@ -214,15 +249,20 @@ class Class {\ ~Class() {} \ \ enum MethodNames { \ - STRUCT(TOOLS_RPC_ENUM_LITERAL0, TOOLS_RPC_ENUM_LITERAL1, \ - TOOLS_RPC_ENUM_LITERAL2, TOOLS_RPC_ENUM_LITERAL3) \ + STRUCT( \ + TOOLS_RPC_ENUM_LITERAL0, \ + TOOLS_RPC_ENUM_LITERAL1, \ + TOOLS_RPC_ENUM_LITERAL2, \ + TOOLS_RPC_ENUM_LITERAL3, \ + TOOLS_RPC_ENUM_LITERAL4) \ }; \ \ STRUCT( \ TOOLS_RPC_API_METHOD0, \ TOOLS_RPC_API_METHOD1, \ TOOLS_RPC_API_METHOD2, \ - TOOLS_RPC_API_METHOD3) \ + TOOLS_RPC_API_METHOD3, \ + TOOLS_RPC_API_METHOD4) \ private: \ DISALLOW_COPY_AND_ASSIGN(Class); \ }; \ @@ -233,10 +273,11 @@ class Class##Stub : public Class, public DevToolsRpc { \ virtual ~Class##Stub() {} \ typedef Class CLASS; \ STRUCT( \ - TOOLS_RPC_STUB_METHOD0, \ - TOOLS_RPC_STUB_METHOD1, \ - TOOLS_RPC_STUB_METHOD2, \ - TOOLS_RPC_STUB_METHOD3) \ + TOOLS_RPC_STUB_METHOD0, \ + TOOLS_RPC_STUB_METHOD1, \ + TOOLS_RPC_STUB_METHOD2, \ + TOOLS_RPC_STUB_METHOD3, \ + TOOLS_RPC_STUB_METHOD4) \ private: \ DISALLOW_COPY_AND_ASSIGN(Class##Stub); \ }; \ @@ -266,7 +307,8 @@ class Class##Dispatch { \ TOOLS_RPC_DISPATCH0, \ TOOLS_RPC_DISPATCH1, \ TOOLS_RPC_DISPATCH2, \ - TOOLS_RPC_DISPATCH3) \ + TOOLS_RPC_DISPATCH3, \ + TOOLS_RPC_DISPATCH4) \ default: return false; \ } \ } \ @@ -345,6 +387,18 @@ class DevToolsRpc { SendValueMessage(message); } + template<class T1, class T2, class T3, class T4> + void InvokeAsync(int class_id, int method, T1 t1, T2 t2, T3 t3, T4 t4) { + ListValue message; + message.Append(CreateValue(&class_id)); + message.Append(CreateValue(&method)); + message.Append(CreateValue(t1)); + message.Append(CreateValue(t2)); + message.Append(CreateValue(t3)); + message.Append(CreateValue(t4)); + SendValueMessage(message); + } + static Value* ParseMessage(const std::string& raw_msg); static std::string Serialize(const Value& value); static void GetListValue(const ListValue& message, int index, bool* value); diff --git a/webkit/glue/devtools/devtools_rpc_js.h b/webkit/glue/devtools/devtools_rpc_js.h index 45b34c7..6dffeca 100644 --- a/webkit/glue/devtools/devtools_rpc_js.h +++ b/webkit/glue/devtools/devtools_rpc_js.h @@ -1,206 +1,241 @@ -// 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.
-
-// Additional set of macros for the JS RPC.
-
-#ifndef WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_
-#define WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_
-
-#include <string>
-
-#include <wtf/OwnPtr.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/values.h"
-#include "webkit/glue/cpp_bound_class.h"
-#include "webkit/glue/devtools/devtools_rpc.h"
-#include "webkit/glue/glue_util.h"
-#include "webkit/glue/webframe.h"
-
-///////////////////////////////////////////////////////
-// JS RPC binds and stubs
-
-template<typename T>
-struct RpcJsTypeTrait {
-};
-
-template<>
-struct RpcJsTypeTrait<bool> {
- static bool Pass(const CppVariant& var) {
- return var.ToBoolean();
- }
-};
-
-template<>
-struct RpcJsTypeTrait<int> {
- static int Pass(const CppVariant& var) {
- return var.ToInt32();
- }
-};
-
-template<>
-struct RpcJsTypeTrait<String> {
- static String Pass(const CppVariant& var) {
- return webkit_glue::StdStringToString(var.ToString());
- }
-};
-
-template<>
-struct RpcJsTypeTrait<std::string> {
- static std::string Pass(const CppVariant& var) {
- return var.ToString();
- }
-};
-
-#define TOOLS_RPC_JS_BIND_METHOD0(Method) \
- BindMethod(#Method, &OCLASS::Js##Method);
-
-#define TOOLS_RPC_JS_BIND_METHOD1(Method, T1) \
- BindMethod(#Method, &OCLASS::Js##Method);
-
-#define TOOLS_RPC_JS_BIND_METHOD2(Method, T1, T2) \
- BindMethod(#Method, &OCLASS::Js##Method);
-
-#define TOOLS_RPC_JS_BIND_METHOD3(Method, T1, T2, T3) \
- BindMethod(#Method, &OCLASS::Js##Method);
-
-#define TOOLS_RPC_JS_STUB_METHOD0(Method) \
- void Js##Method(const CppArgumentList& args, CppVariant* result) { \
- InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method); \
- result->SetNull(); \
- }
-
-#define TOOLS_RPC_JS_STUB_METHOD1(Method, T1) \
- void Js##Method(const CppArgumentList& args, CppVariant* result) { \
- T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \
- InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1); \
- result->SetNull(); \
- }
-
-#define TOOLS_RPC_JS_STUB_METHOD2(Method, T1, T2) \
- void Js##Method(const CppArgumentList& args, CppVariant* result) { \
- T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \
- T2 t2 = RpcJsTypeTrait<T2>::Pass(args[1]); \
- InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2); \
- result->SetNull(); \
- }
-
-#define TOOLS_RPC_JS_STUB_METHOD3(Method, T1, T2, T3) \
- void Js##Method(const CppArgumentList& args, CppVariant* result) { \
- T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \
- T2 t2 = RpcJsTypeTrait<T2>::Pass(args[1]); \
- T3 t3 = RpcJsTypeTrait<T3>::Pass(args[2]); \
- InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2, \
- &t3); \
- result->SetNull(); \
- }
-
-///////////////////////////////////////////////////////
-// JS RPC dispatch method implementations
-
-#define TOOLS_RPC_JS_DISPATCH0(Method) \
-case CLASS::METHOD_##Method: { \
- *expr = StringPrintf("%s.%s()", js_obj.c_str(), #Method); \
- return true; \
-}
-
-#define TOOLS_RPC_JS_DISPATCH1(Method, T1) \
-case CLASS::METHOD_##Method: { \
- Value* t1; \
- message.Get(2, &t1); \
- *expr = StringPrintf("%s.%s(%s)", js_obj.c_str(), #Method, \
- DevToolsRpc::Serialize(*t1).c_str()); \
- return true; \
-}
-
-#define TOOLS_RPC_JS_DISPATCH2(Method, T1, T2) \
-case CLASS::METHOD_##Method: { \
- Value* t1; \
- Value* t2; \
- message.Get(2, &t1); \
- message.Get(3, &t2); \
- *expr = StringPrintf("%s.%s(%s, %s)", js_obj.c_str(), #Method, \
- DevToolsRpc::Serialize(*t1).c_str(), \
- DevToolsRpc::Serialize(*t2).c_str()); \
- return true; \
-}
-
-#define TOOLS_RPC_JS_DISPATCH3(Method, T1, T2, T3) \
-case CLASS::METHOD_##Method: { \
- Value* t1; \
- Value* t2; \
- Value* t3; \
- message.Get(2, &t1); \
- message.Get(3, &t2); \
- message.Get(4, &t3); \
- *expr = StringPrintf("%s.%s(%s, %s, %s)", js_obj.c_str(), #Method, \
- DevToolsRpc::Serialize(*t1).c_str(), \
- DevToolsRpc::Serialize(*t2).c_str(), \
- DevToolsRpc::Serialize(*t3).c_str()); \
- return true; \
-}
-
-#define DEFINE_RPC_JS_DISPATCH(Class, STRUCT) \
-class Js##Class##Dispatch { \
- public: \
- explicit Js##Class##Dispatch(const std::wstring& classname) \
- : js_obj(WideToUTF8(classname)) {} \
- virtual ~Js##Class##Dispatch() {} \
- \
- bool Dispatch(const ListValue& message, std::string* expr) { \
- int class_id; \
- message.GetInteger(0, &class_id); \
- if (class_id != RpcTypeToNumber<Class>::number) { \
- return false; \
- } \
- int method; \
- message.GetInteger(1, &method); \
- typedef Class CLASS; \
- switch (method) { \
- STRUCT( \
- TOOLS_RPC_JS_DISPATCH0, \
- TOOLS_RPC_JS_DISPATCH1, \
- TOOLS_RPC_JS_DISPATCH2, \
- TOOLS_RPC_JS_DISPATCH3) \
- default: return false; \
- } \
- } \
- private: \
- std::string js_obj; \
- DISALLOW_COPY_AND_ASSIGN(Js##Class##Dispatch); \
-};
-
-///////////////////////////////////////////////////////
-// JS RPC main obj macro
-
-#define DEFINE_RPC_JS_BOUND_OBJ(Class, STRUCT, DClass, DELEGATE_STRUCT) \
-DEFINE_RPC_JS_DISPATCH(DClass, DELEGATE_STRUCT) \
-class Js##Class##BoundObj : public Class##Stub, \
- public CppBoundClass, \
- public Js##DClass##Dispatch { \
- public: \
- Js##Class##BoundObj(Delegate* rpc_delegate, WebFrame* frame, \
- const std::wstring& classname) \
- : Class##Stub(rpc_delegate), \
- Js##DClass##Dispatch(classname) { \
- BindToJavascript(frame, classname); \
- STRUCT( \
- TOOLS_RPC_JS_BIND_METHOD0, \
- TOOLS_RPC_JS_BIND_METHOD1, \
- TOOLS_RPC_JS_BIND_METHOD2, \
- TOOLS_RPC_JS_BIND_METHOD3) \
- } \
- virtual ~Js##Class##BoundObj() {} \
- typedef Js##Class##BoundObj OCLASS; \
- STRUCT( \
- TOOLS_RPC_JS_STUB_METHOD0, \
- TOOLS_RPC_JS_STUB_METHOD1, \
- TOOLS_RPC_JS_STUB_METHOD2, \
- TOOLS_RPC_JS_STUB_METHOD3) \
- private: \
- DISALLOW_COPY_AND_ASSIGN(Js##Class##BoundObj); \
-};
-
-#endif // WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_
+// 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. + +// Additional set of macros for the JS RPC. + +#ifndef WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_ +#define WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_ + +#include <string> + +#include <wtf/OwnPtr.h> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/values.h" +#include "webkit/glue/cpp_bound_class.h" +#include "webkit/glue/devtools/devtools_rpc.h" +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webframe.h" + +/////////////////////////////////////////////////////// +// JS RPC binds and stubs + +template<typename T> +struct RpcJsTypeTrait { +}; + +template<> +struct RpcJsTypeTrait<bool> { + static bool Pass(const CppVariant& var) { + return var.ToBoolean(); + } +}; + +template<> +struct RpcJsTypeTrait<int> { + static int Pass(const CppVariant& var) { + return var.ToInt32(); + } +}; + +template<> +struct RpcJsTypeTrait<String> { + static String Pass(const CppVariant& var) { + return webkit_glue::StdStringToString(var.ToString()); + } +}; + +template<> +struct RpcJsTypeTrait<std::string> { + static std::string Pass(const CppVariant& var) { + return var.ToString(); + } +}; + +#define TOOLS_RPC_JS_BIND_METHOD0(Method) \ + BindMethod(#Method, &OCLASS::Js##Method); + +#define TOOLS_RPC_JS_BIND_METHOD1(Method, T1) \ + BindMethod(#Method, &OCLASS::Js##Method); + +#define TOOLS_RPC_JS_BIND_METHOD2(Method, T1, T2) \ + BindMethod(#Method, &OCLASS::Js##Method); + +#define TOOLS_RPC_JS_BIND_METHOD3(Method, T1, T2, T3) \ + BindMethod(#Method, &OCLASS::Js##Method); + +#define TOOLS_RPC_JS_BIND_METHOD4(Method, T1, T2, T3, T4) \ + BindMethod(#Method, &OCLASS::Js##Method); + +#define TOOLS_RPC_JS_STUB_METHOD0(Method) \ + void Js##Method(const CppArgumentList& args, CppVariant* result) { \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method); \ + result->SetNull(); \ + } + +#define TOOLS_RPC_JS_STUB_METHOD1(Method, T1) \ + void Js##Method(const CppArgumentList& args, CppVariant* result) { \ + T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1); \ + result->SetNull(); \ + } + +#define TOOLS_RPC_JS_STUB_METHOD2(Method, T1, T2) \ + void Js##Method(const CppArgumentList& args, CppVariant* result) { \ + T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \ + T2 t2 = RpcJsTypeTrait<T2>::Pass(args[1]); \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2); \ + result->SetNull(); \ + } + +#define TOOLS_RPC_JS_STUB_METHOD3(Method, T1, T2, T3) \ + void Js##Method(const CppArgumentList& args, CppVariant* result) { \ + T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \ + T2 t2 = RpcJsTypeTrait<T2>::Pass(args[1]); \ + T3 t3 = RpcJsTypeTrait<T3>::Pass(args[2]); \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2, \ + &t3); \ + result->SetNull(); \ + } + +#define TOOLS_RPC_JS_STUB_METHOD4(Method, T1, T2, T3, T4) \ + void Js##Method(const CppArgumentList& args, CppVariant* result) { \ + T1 t1 = RpcJsTypeTrait<T1>::Pass(args[0]); \ + T2 t2 = RpcJsTypeTrait<T2>::Pass(args[1]); \ + T3 t3 = RpcJsTypeTrait<T3>::Pass(args[2]); \ + T4 t4 = RpcJsTypeTrait<T4>::Pass(args[3]); \ + InvokeAsync(RpcTypeToNumber<CLASS>::number, METHOD_##Method, &t1, &t2, \ + &t3, &t4); \ + result->SetNull(); \ + } + +/////////////////////////////////////////////////////// +// JS RPC dispatch method implementations + +#define TOOLS_RPC_JS_DISPATCH0(Method) \ +case CLASS::METHOD_##Method: { \ + *expr = StringPrintf("%s.%s()", js_obj.c_str(), #Method); \ + return true; \ +} + +#define TOOLS_RPC_JS_DISPATCH1(Method, T1) \ +case CLASS::METHOD_##Method: { \ + Value* t1; \ + message.Get(2, &t1); \ + *expr = StringPrintf("%s.%s(%s)", js_obj.c_str(), #Method, \ + DevToolsRpc::Serialize(*t1).c_str()); \ + return true; \ +} + +#define TOOLS_RPC_JS_DISPATCH2(Method, T1, T2) \ +case CLASS::METHOD_##Method: { \ + Value* t1; \ + Value* t2; \ + message.Get(2, &t1); \ + message.Get(3, &t2); \ + *expr = StringPrintf("%s.%s(%s, %s)", js_obj.c_str(), #Method, \ + DevToolsRpc::Serialize(*t1).c_str(), \ + DevToolsRpc::Serialize(*t2).c_str()); \ + return true; \ +} + +#define TOOLS_RPC_JS_DISPATCH3(Method, T1, T2, T3) \ +case CLASS::METHOD_##Method: { \ + Value* t1; \ + Value* t2; \ + Value* t3; \ + message.Get(2, &t1); \ + message.Get(3, &t2); \ + message.Get(4, &t3); \ + *expr = StringPrintf("%s.%s(%s, %s, %s)", js_obj.c_str(), #Method, \ + DevToolsRpc::Serialize(*t1).c_str(), \ + DevToolsRpc::Serialize(*t2).c_str(), \ + DevToolsRpc::Serialize(*t3).c_str()); \ + return true; \ +} + +#define TOOLS_RPC_JS_DISPATCH4(Method, T1, T2, T3, T4) \ +case CLASS::METHOD_##Method: { \ + Value* t1; \ + Value* t2; \ + Value* t3; \ + Value* t4; \ + message.Get(2, &t1); \ + message.Get(3, &t2); \ + message.Get(4, &t3); \ + message.Get(5, &t4); \ + *expr = StringPrintf("%s.%s(%s, %s, %s, %s)", js_obj.c_str(), #Method, \ + DevToolsRpc::Serialize(*t1).c_str(), \ + DevToolsRpc::Serialize(*t2).c_str(), \ + DevToolsRpc::Serialize(*t3).c_str(), \ + DevToolsRpc::Serialize(*t4).c_str()); \ + return true; \ +} + +#define DEFINE_RPC_JS_DISPATCH(Class, STRUCT) \ +class Js##Class##Dispatch { \ + public: \ + explicit Js##Class##Dispatch(const std::wstring& classname) \ + : js_obj(WideToUTF8(classname)) {} \ + virtual ~Js##Class##Dispatch() {} \ + \ + bool Dispatch(const ListValue& message, std::string* expr) { \ + int class_id; \ + message.GetInteger(0, &class_id); \ + if (class_id != RpcTypeToNumber<Class>::number) { \ + return false; \ + } \ + int method; \ + message.GetInteger(1, &method); \ + typedef Class CLASS; \ + switch (method) { \ + STRUCT( \ + TOOLS_RPC_JS_DISPATCH0, \ + TOOLS_RPC_JS_DISPATCH1, \ + TOOLS_RPC_JS_DISPATCH2, \ + TOOLS_RPC_JS_DISPATCH3, \ + TOOLS_RPC_JS_DISPATCH4) \ + default: return false; \ + } \ + } \ + private: \ + std::string js_obj; \ + DISALLOW_COPY_AND_ASSIGN(Js##Class##Dispatch); \ +}; + +/////////////////////////////////////////////////////// +// JS RPC main obj macro + +#define DEFINE_RPC_JS_BOUND_OBJ(Class, STRUCT, DClass, DELEGATE_STRUCT) \ +DEFINE_RPC_JS_DISPATCH(DClass, DELEGATE_STRUCT) \ +class Js##Class##BoundObj : public Class##Stub, \ + public CppBoundClass, \ + public Js##DClass##Dispatch { \ + public: \ + Js##Class##BoundObj(Delegate* rpc_delegate, WebFrame* frame, \ + const std::wstring& classname) \ + : Class##Stub(rpc_delegate), \ + Js##DClass##Dispatch(classname) { \ + BindToJavascript(frame, classname); \ + STRUCT( \ + TOOLS_RPC_JS_BIND_METHOD0, \ + TOOLS_RPC_JS_BIND_METHOD1, \ + TOOLS_RPC_JS_BIND_METHOD2, \ + TOOLS_RPC_JS_BIND_METHOD3, \ + TOOLS_RPC_JS_BIND_METHOD4) \ + } \ + virtual ~Js##Class##BoundObj() {} \ + typedef Js##Class##BoundObj OCLASS; \ + STRUCT( \ + TOOLS_RPC_JS_STUB_METHOD0, \ + TOOLS_RPC_JS_STUB_METHOD1, \ + TOOLS_RPC_JS_STUB_METHOD2, \ + TOOLS_RPC_JS_STUB_METHOD3, \ + TOOLS_RPC_JS_STUB_METHOD4) \ + private: \ + DISALLOW_COPY_AND_ASSIGN(Js##Class##BoundObj); \ +}; + +#endif // WEBKIT_GLUE_DEVTOOLS_DEVTOOLS_RPC_JS_H_ diff --git a/webkit/glue/devtools/dom_agent.h b/webkit/glue/devtools/dom_agent.h index 33306de..205e4d9 100644 --- a/webkit/glue/devtools/dom_agent.h +++ b/webkit/glue/devtools/dom_agent.h @@ -11,7 +11,7 @@ // WebDevToolsAgent. It is capable of sending DOM tree to the client as well // as providing DOM notifications for the nodes known to the client. // DomAgent's environment is represented with the DomAgentDelegate interface. -#define DOM_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define DOM_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4) \ /* Requests that the document root element is sent to the delegate. */ \ METHOD0(GetDocumentElement) \ \ @@ -19,13 +19,16 @@ METHOD2(GetChildNodes, int /* call_id */, int /* id */) \ \ /* Sets attribute value in the element with given id. */ \ - METHOD3(SetAttribute, int /* id */, String /* name */, String /* value */) \ + METHOD4(SetAttribute, int /* call_id */, int /* id */, String /* name */, \ + String /* value */) \ \ /* Removes attribute from the element with given id. */ \ - METHOD2(RemoveAttribute, int /* id */, String /* name */) \ + METHOD3(RemoveAttribute, int /* call_id */, int /* id */, \ + String /* name */) \ \ /* Sets text node value in the node with given id. */ \ - METHOD2(SetTextNodeValue, int /* id */, String /* text */) \ + METHOD3(SetTextNodeValue, int /* call_id */, int /* id */, \ + String /* text */) \ \ /* Perform search. */ \ METHOD2(PerformSearch, int /* call_id */, String /* query */) \ @@ -37,13 +40,17 @@ DEFINE_RPC_CLASS(DomAgent, DOM_AGENT_STRUCT) -#define DOM_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define DOM_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, \ + METHOD4) \ /* Response to GetChildNodes. */ \ METHOD1(DidGetChildNodes, int /* call_id */) \ \ /* Perform search. */ \ METHOD2(DidPerformSearch, int /* call_id */, Value /* results */) \ \ + /* Ack for the Set/RemoveAttribute, SetTextNodeValue. */ \ + METHOD2(DidApplyDomChange, int /* call_id */, bool /* success */) \ + \ /* Notifies the delegate that element's attributes are updated. */ \ METHOD2(AttributesUpdated, int /* id */, Value /* attributes */) \ \ diff --git a/webkit/glue/devtools/dom_agent_impl.cc b/webkit/glue/devtools/dom_agent_impl.cc index 6d6471c..d946a7e 100644 --- a/webkit/glue/devtools/dom_agent_impl.cc +++ b/webkit/glue/devtools/dom_agent_impl.cc @@ -69,7 +69,9 @@ DomAgentImpl::~DomAgentImpl() { } void DomAgentImpl::SetDocument(Document* doc) { - DiscardBindings(); + if (documents_.size() && doc == documents_.begin()->get()) { + return; + } ListHashSet<RefPtr<Document> > copy = documents_; for (ListHashSet<RefPtr<Document> >::iterator it = copy.begin(); @@ -84,6 +86,8 @@ void DomAgentImpl::SetDocument(Document* doc) { GetDocumentElement(); document_element_requested_ = false; } + } else { + DiscardBindings(); } } @@ -289,33 +293,49 @@ int DomAgentImpl::PushNodePathToClient(Node* node_to_select) { } void DomAgentImpl::SetAttribute( + int call_id, int element_id, const String& name, const String& value) { Node* node = GetNodeForId(element_id); if (node && (node->nodeType() == Node::ELEMENT_NODE)) { Element* element = static_cast<Element*>(node); - ExceptionCode ec = 0; + ExceptionCode ec = 0; element->setAttribute(name, value, ec); + delegate_->DidApplyDomChange(call_id, ec == 0); + } else { + delegate_->DidApplyDomChange(call_id, false); } } -void DomAgentImpl::RemoveAttribute(int element_id, const String& name) { +void DomAgentImpl::RemoveAttribute( + int call_id, + int element_id, + const String& name) { Node* node = GetNodeForId(element_id); if (node && (node->nodeType() == Node::ELEMENT_NODE)) { Element* element = static_cast<Element*>(node); ExceptionCode ec = 0; element->removeAttribute(name, ec); + delegate_->DidApplyDomChange(call_id, ec == 0); + } else { + delegate_->DidApplyDomChange(call_id, false); } } -void DomAgentImpl::SetTextNodeValue(int element_id, const String& value) { +void DomAgentImpl::SetTextNodeValue( + int call_id, + int element_id, + const String& value) { Node* node = GetNodeForId(element_id); if (node && (node->nodeType() == Node::TEXT_NODE)) { Text* text_node = static_cast<Text*>(node); ExceptionCode ec = 0; // TODO(pfeldman): Add error handling text_node->replaceWholeText(value, ec); + delegate_->DidApplyDomChange(call_id, ec == 0); + } else { + delegate_->DidApplyDomChange(call_id, false); } } diff --git a/webkit/glue/devtools/dom_agent_impl.h b/webkit/glue/devtools/dom_agent_impl.h index 3f02669..0a8eb31 100644 --- a/webkit/glue/devtools/dom_agent_impl.h +++ b/webkit/glue/devtools/dom_agent_impl.h @@ -35,11 +35,18 @@ class DomAgentImpl : public DomAgent { void GetDocumentElement(); void GetChildNodes(int call_id, int element_id); void SetAttribute( + int call_id, int element_id, const WebCore::String& name, const WebCore::String& value); - void RemoveAttribute(int element_id, const WebCore::String& name); - void SetTextNodeValue(int element_id, const WebCore::String& value); + void RemoveAttribute( + int call_id, + int element_id, + const WebCore::String& name); + void SetTextNodeValue( + int call_id, + int element_id, + const WebCore::String& value); void PerformSearch(int call_id, const String& query); void DiscardBindings(); diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js index 39a81fc..31d7782 100644 --- a/webkit/glue/devtools/js/devtools.js +++ b/webkit/glue/devtools/js/devtools.js @@ -145,7 +145,7 @@ var webkitUpdateChildren = WebInspector.ElementsTreeElement.prototype.updateChildren = function() { var self = this; - devtools.tools.getDomAgent().getChildNodesAsync(this.representedObject.id, + devtools.tools.getDomAgent().getChildNodesAsync(this.representedObject, function() { webkitUpdateChildren.call(self); }); diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js index c820d67..17b49e8 100644 --- a/webkit/glue/devtools/js/devtools_host_stub.js +++ b/webkit/glue/devtools/js/devtools_host_stub.js @@ -95,15 +95,24 @@ RemoteDomAgentStub.prototype.GetChildNodes = function(callId, id) { }; -RemoteDomAgentStub.prototype.SetAttribute = function() { +RemoteDomAgentStub.prototype.SetAttribute = function(callId) { + setTimeout(function() { + RemoteDomAgent.DidApplyDomChange(callId, true); + }, 0); }; -RemoteDomAgentStub.prototype.RemoveAttribute = function() { +RemoteDomAgentStub.prototype.RemoveAttribute = function(callId) { + setTimeout(function() { + RemoteDomAgent.DidApplyDomChange(callId, true); + }, 0); }; -RemoteDomAgentStub.prototype.SetTextNodeValue = function() { +RemoteDomAgentStub.prototype.SetTextNodeValue = function(callId) { + setTimeout(function() { + RemoteDomAgent.DidApplyDomChange(callId, true); + }, 0); }; @@ -144,6 +153,18 @@ RemoteToolsAgentStub.prototype.EvaluateJavaSctipt = function(callId, script) { }, 0); }; + +/** + * @constructor + */ +RemoteDebuggerCommandExecutorStub = function() { +}; + + +RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function() { +}; + + /** * @constructor */ @@ -168,6 +189,8 @@ DevToolsHostStub.prototype.loaded = function() { if (!window['DevToolsHost']) { window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub(); + window['RemoteDebuggerCommandExecutor'] = + new RemoteDebuggerCommandExecutorStub(); window['RemoteDomAgent'] = new RemoteDomAgentStub(); window['RemoteNetAgent'] = new RemoteNetAgentStub(); window['RemoteToolsAgent'] = new RemoteToolsAgentStub(); diff --git a/webkit/glue/devtools/js/dom_agent.js b/webkit/glue/devtools/js/dom_agent.js index 0590e6b..ebcba55 100644 --- a/webkit/glue/devtools/js/dom_agent.js +++ b/webkit/glue/devtools/js/dom_agent.js @@ -36,10 +36,10 @@ devtools.PayloadIndex = { devtools.DomNode = function(doc, payload) { this.ownerDocument = doc; - this.id = payload[devtools.PayloadIndex.ID]; + this.id_ = payload[devtools.PayloadIndex.ID]; this.nodeType = payload[devtools.PayloadIndex.TYPE]; this.nodeName = payload[devtools.PayloadIndex.NAME]; - this.nodeValue = payload[devtools.PayloadIndex.VALUE]; + this.nodeValue_ = payload[devtools.PayloadIndex.VALUE]; this.textContent = this.nodeValue; this.attributes = []; @@ -65,14 +65,37 @@ devtools.DomNode = function(doc, payload) { /** + * Overrides for getters and setters. + */ +devtools.DomNode.prototype = { + get nodeValue() { + return this.nodeValue_; + }, + + set nodeValue(value) { + if (this.nodeType != Node.TEXT_NODE) { + return; + } + var self = this; + this.ownerDocument.domAgent_.setTextNodeValueAsync(this, value, + function() { + self.nodeValue_ = value; + self.textContent = value; + }); + } +}; + + +/** * Sets attributes for a given node based on a given attrs payload. * @param {Array.<string>} attrs Attribute key-value pairs to set. * @private */ devtools.DomNode.prototype.setAttributesPayload_ = function(attrs) { for (var i = 0; i < attrs.length; i += 2) { - this.attributes.push({"name" : attrs[i], "value" : attrs[i+1]}); - this.attributesMap_[attrs[i]] = attrs[i+1]; + var attr = {"name" : attrs[i], "value" : attrs[i+1]}; + this.attributes.push(attr); + this.attributesMap_[attrs[i]] = attr; } }; @@ -164,18 +187,62 @@ devtools.DomNode.prototype.renumber_ = function() { /** * Returns attribute value. * @param {string} name Attribute name to get value for. - @ @return {string} Attribute value. + * @return {string} Attribute value. */ devtools.DomNode.prototype.getAttribute = function(name) { - return this.attributesMap_[name]; + var attr = this.attributesMap_[name]; + return attr ? attr.value : undefined; +}; + + +/** + * Sends 'set attribute' command to the remote agent. + * @param {string} name Attribute name to set value for. + * @param {string} value Attribute value to set. + */ +devtools.DomNode.prototype.setAttribute = function(name, value) { + var self = this; + this.ownerDocument.domAgent_.setAttributeAsync(this, name, value, + function() { + var attr = self.attributesMap_[name]; + if (attr) { + attr.value = value; + } else { + attr = {"name" : name, "value" : value}; + self.attributesMap_[name] = attr; + self.attributes_.push(attr); + } + }); +}; + + +/** + * Sends 'remove attribute' command to the remote agent. + * @param {string} name Attribute name to set value for. + */ +devtools.DomNode.prototype.removeAttribute = function(name) { + var self = this; + this.ownerDocument.domAgent_.removeAttributeAsync(this, name, function() { + if (!success) { + return; + } + delete self.attributesMap_[name]; + for (var i = 0; i < self.attributes_.length; ++i) { + if (self.attributes_[i].name == name) { + self.attributes_.splice(i, 1); + break; + } + } + }); }; /** * Remote Dom document abstraction. + * @param {devtools.DomAgent} domAgent owner agent. * @constructor. */ -devtools.DomDocument = function() { +devtools.DomDocument = function(domAgent) { devtools.DomNode.call(this, null, [ 0, // id @@ -190,6 +257,7 @@ devtools.DomDocument = function() { getComputedStyle : function() {}, getMatchedCSSRules : function() {} }; + this.domAgent_ = domAgent; }; goog.inherits(devtools.DomDocument, devtools.DomNode); @@ -256,6 +324,12 @@ devtools.DomAgent = function() { devtools.Callback.processCallback; RemoteDomAgent.DidPerformSearch = devtools.Callback.processCallback; + RemoteDomAgent.DidApplyDomChange = + devtools.Callback.processCallback; + RemoteDomAgent.DidRemoveAttribute = + devtools.Callback.processCallback; + RemoteDomAgent.DidSetTextNodeValue = + devtools.Callback.processCallback; RemoteDomAgent.AttributesUpdated = goog.bind(this.attributesUpdated, this); RemoteDomAgent.SetDocumentElement = @@ -297,8 +371,7 @@ devtools.DomAgent = function() { * Rests dom agent to its initial state. */ devtools.DomAgent.prototype.reset = function() { - RemoteDomAgent.DiscardBindings(); - this.document_ = new devtools.DomDocument(); + this.document_ = new devtools.DomDocument(this); this.idToDomNode_ = { 0 : this.document_ }; this.searchResults_ = []; }; @@ -325,25 +398,86 @@ devtools.DomAgent.prototype.getDocumentElementAsync = function() { /** * Asynchronously fetches children from the element with given id. - * @param {number} parentId Element to get children for. + * @param {devtools.DomNode} parent Element to get children for. * @param {function(devtools.DomNode):undefined} opt_callback Callback with * the result. */ -devtools.DomAgent.prototype.getChildNodesAsync = function(parentId, +devtools.DomAgent.prototype.getChildNodesAsync = function(parent, opt_callback) { - var children = this.idToDomNode_[parentId].children; + var children = parent.children; if (children && opt_callback) { opt_callback(children); return; } - var self = this; var mycallback = function() { if (opt_callback) { - opt_callback(self.idToDomNode_[parentId].children); + opt_callback(parent.children); } }; var callId = devtools.Callback.wrap(mycallback); - RemoteDomAgent.GetChildNodes(callId, parentId); + RemoteDomAgent.GetChildNodes(callId, parent.id_); +}; + + +/** + * Sends 'set attribute' command to the remote agent. + * @param {devtools.DomNode} node Node to change. + * @param {string} name Attribute name to set value for. + * @param {string} value Attribute value to set. + * @param {function():undefined} opt_callback Callback on success. + */ +devtools.DomAgent.prototype.setAttributeAsync = function(node, name, value, + callback) { + var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback); + RemoteDomAgent.SetAttribute(devtools.Callback.wrap(mycallback), + node.id_, name, value); +}; + + +/** + * Sends 'remove attribute' command to the remote agent. + * @param {devtools.DomNode} node Node to change. + * @param {string} name Attribute name to set value for. + * @param {function():undefined} opt_callback Callback on success. + */ +devtools.DomAgent.prototype.removeAttributeAsync = function(node, name, + callback) { + var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback); + RemoteDomAgent.RemoveAttribute(devtools.Callback.wrap(mycallback), + node.id_, name); +}; + + +/** + * Sends 'set text node value' command to the remote agent. + * @param {devtools.DomNode} node Node to change. + * @param {string} text Text value to set. + * @param {function():undefined} opt_callback Callback on success. + */ +devtools.DomAgent.prototype.setTextNodeValueAsync = function(node, text, + callback) { + var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback); + RemoteDomAgent.SetTextNodeValue(devtools.Callback.wrap(mycallback), + node.id_, text); +}; + + +/** + * Universal callback wrapper for edit dom operations. + * @param {devtools.DomNode} node Node to apply local changes on. + * @param {Function} callback Post-operation call. + * @param {boolean} success True iff operation has completed successfully. + */ +devtools.DomAgent.prototype.didApplyDomChange_ = function(node, + callback, success) { + if (!success) { + return; + } + callback(); + var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node); + if (elem) { + elem._updateTitle(); + } }; @@ -403,7 +537,7 @@ devtools.DomAgent.prototype.setChildNodes = function(parentId, payloads) { devtools.DomAgent.prototype.bindNodes_ = function(children) { for (var i = 0; i < children.length; ++i) { var child = children[i]; - this.idToDomNode_[child.id] = child; + this.idToDomNode_[child.id_] = child; if (child.children) { this.bindNodes_(child.children); } @@ -428,7 +562,7 @@ devtools.DomAgent.prototype.childNodeInserted = function( var parent = this.idToDomNode_[parentId]; var prev = this.idToDomNode_[prevId]; var node = parent.insertChild_(prev, payload); - this.idToDomNode_[node.id] = node; + this.idToDomNode_[node.id_] = node; var event = { target : node, relatedNode : parent }; this.document_.fireDomEvent_("DOMNodeInserted", event); }; diff --git a/webkit/glue/devtools/net_agent.h b/webkit/glue/devtools/net_agent.h index 0921c26..87459f0 100644 --- a/webkit/glue/devtools/net_agent.h +++ b/webkit/glue/devtools/net_agent.h @@ -11,7 +11,7 @@ // WebDevToolsAgent. It is capable of sniffing network calls and passing the // HTTPRequest-related data to the client. // NetAgent's environment is represented with the NetAgentDelegate interface. -#define NET_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define NET_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4) \ /* Requests that the agent sends content of the resource with given id to the delegate. */ \ METHOD3(GetResourceContent, int /* call_id */, int /* identifier */, \ @@ -19,7 +19,8 @@ DEFINE_RPC_CLASS(NetAgent, NET_AGENT_STRUCT) -#define NET_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define NET_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, \ + METHOD4) \ /* Notifies the delegate that a request is about to be sent out. */ \ METHOD2(WillSendRequest, int, Value) \ \ diff --git a/webkit/glue/devtools/tools_agent.h b/webkit/glue/devtools/tools_agent.h index 0ca14d3..8db0de6 100644 --- a/webkit/glue/devtools/tools_agent.h +++ b/webkit/glue/devtools/tools_agent.h @@ -9,7 +9,7 @@ // Tools agent provides API for enabling / disabling other agents as well as // API for auxiliary UI functions such as dom elements highlighting. -#define TOOLS_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define TOOLS_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4) \ /* Highlights Dom node with given ID */ \ METHOD1(HighlightDOMNode, int /* node_id */) \ \ @@ -21,7 +21,8 @@ DEFINE_RPC_CLASS(ToolsAgent, TOOLS_AGENT_STRUCT) -#define TOOLS_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \ +#define TOOLS_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, \ + METHOD4) \ /* Updates focused node on the client. */ \ METHOD1(UpdateFocusedNode, int /* node_id */) \ \ |