diff -r 000000000000 -r 4f2f89ce4247 WebKit/chromium/src/DevToolsRPC.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebKit/chromium/src/DevToolsRPC.h Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DevTools RPC subsystem is a simple string serialization-based rpc +// implementation. The client is responsible for defining the Rpc-enabled +// interface in terms of its macros: +// +// #define MYAPI_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) +// METHOD0(Method1) +// METHOD1(Method3, int) +// (snippet above should be multiline macro, add trailing backslashes) +// +// DEFINE_RPC_CLASS(MyApi, MYAPI_STRUCT) +// +// The snippet above will generate three classes: MyApi, MyApiStub and +// MyApiDispatch. +// +// 1. For each method defined in the marco MyApi will have a +// pure virtual function generated, so that MyApi would look like: +// +// class MyApi { +// private: +// MyApi() { } +// ~MyApi() { } +// virtual void method1() = 0; +// virtual void method2( +// int param1, +// const String& param2, +// const Value& param3) = 0; +// virtual void method3(int param1) = 0; +// }; +// +// 2. MyApiStub will implement MyApi interface and would serialize all calls +// into the string-based calls of the underlying transport: +// +// DevToolsRPC::Delegate* transport; +// myApi = new MyApiStub(transport); +// myApi->method1(); +// myApi->method3(2); +// +// 3. MyApiDelegate is capable of dispatching the calls and convert them to the +// calls to the underlying MyApi methods: +// +// MyApi* realObject; +// MyApiDispatch::dispatch(realObject, rawStringCallGeneratedByStub); +// +// will make corresponding calls to the real object. + +#ifndef DevToolsRPC_h +#define DevToolsRPC_h + +#include "PlatformString.h" +#include "Vector.h" +#include "WebDevToolsMessageData.h" + +#include + +namespace WebCore { +class String; +} + +using WebCore::String; +using WTF::Vector; + +namespace WebKit { + +/////////////////////////////////////////////////////// +// RPC dispatch macro + +template +struct RpcTypeTrait { + typedef T ApiType; +}; + +template<> +struct RpcTypeTrait { + typedef bool ApiType; + static bool parse(const WebCore::String& t) + { + return t == "true"; + } + static WebCore::String toString(bool b) + { + return b ? "true" : "false"; + } +}; + +template<> +struct RpcTypeTrait { + typedef int ApiType; + static int parse(const WebCore::String& t) + { + bool success; + int i = t.toIntStrict(&success); + ASSERT(success); + return i; + } + static WebCore::String toString(int i) + { + return WebCore::String::number(i); + } +}; + +template<> +struct RpcTypeTrait { + typedef const String& ApiType; + static String parse(const WebCore::String& t) + { + return t; + } + static WebCore::String toString(const String& t) + { + return t; + } +}; + +/////////////////////////////////////////////////////// +// RPC Api method declarations + +#define TOOLS_RPC_API_METHOD0(Method) \ + virtual void Method() = 0; + +#define TOOLS_RPC_API_METHOD1(Method, T1) \ + virtual void Method(RpcTypeTrait::ApiType t1) = 0; + +#define TOOLS_RPC_API_METHOD2(Method, T1, T2) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2) = 0; + +#define TOOLS_RPC_API_METHOD3(Method, T1, T2, T3) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3) = 0; + +#define TOOLS_RPC_API_METHOD4(Method, T1, T2, T3, T4) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3, \ + RpcTypeTrait::ApiType t4) = 0; + +#define TOOLS_RPC_API_METHOD5(Method, T1, T2, T3, T4, T5) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3, \ + RpcTypeTrait::ApiType t4, \ + RpcTypeTrait::ApiType t5) = 0; + +/////////////////////////////////////////////////////// +// RPC stub method implementations + +#define TOOLS_RPC_STUB_METHOD0(Method) \ + virtual void Method() { \ + Vector args; \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +#define TOOLS_RPC_STUB_METHOD1(Method, T1) \ + virtual void Method(RpcTypeTrait::ApiType t1) { \ + Vector args(1); \ + args[0] = RpcTypeTrait::toString(t1); \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +#define TOOLS_RPC_STUB_METHOD2(Method, T1, T2) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2) { \ + Vector args(2); \ + args[0] = RpcTypeTrait::toString(t1); \ + args[1] = RpcTypeTrait::toString(t2); \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +#define TOOLS_RPC_STUB_METHOD3(Method, T1, T2, T3) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3) { \ + Vector args(3); \ + args[0] = RpcTypeTrait::toString(t1); \ + args[1] = RpcTypeTrait::toString(t2); \ + args[2] = RpcTypeTrait::toString(t3); \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +#define TOOLS_RPC_STUB_METHOD4(Method, T1, T2, T3, T4) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3, \ + RpcTypeTrait::ApiType t4) { \ + Vector args(4); \ + args[0] = RpcTypeTrait::toString(t1); \ + args[1] = RpcTypeTrait::toString(t2); \ + args[2] = RpcTypeTrait::toString(t3); \ + args[3] = RpcTypeTrait::toString(t4); \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +#define TOOLS_RPC_STUB_METHOD5(Method, T1, T2, T3, T4, T5) \ + virtual void Method(RpcTypeTrait::ApiType t1, \ + RpcTypeTrait::ApiType t2, \ + RpcTypeTrait::ApiType t3, \ + RpcTypeTrait::ApiType t4, \ + RpcTypeTrait::ApiType t5) { \ + Vector args(5); \ + args[0] = RpcTypeTrait::toString(t1); \ + args[1] = RpcTypeTrait::toString(t2); \ + args[2] = RpcTypeTrait::toString(t3); \ + args[3] = RpcTypeTrait::toString(t4); \ + args[4] = RpcTypeTrait::toString(t5); \ + this->sendRpcMessage(m_className, #Method, args); \ + } + +/////////////////////////////////////////////////////// +// RPC dispatch method implementations + +#define TOOLS_RPC_DISPATCH0(Method) \ +if (methodName == #Method) { \ + delegate->Method(); \ + return true; \ +} + +#define TOOLS_RPC_DISPATCH1(Method, T1) \ +if (methodName == #Method) { \ + delegate->Method(RpcTypeTrait::parse(args[0])); \ + return true; \ +} + +#define TOOLS_RPC_DISPATCH2(Method, T1, T2) \ +if (methodName == #Method) { \ + delegate->Method( \ + RpcTypeTrait::parse(args[0]), \ + RpcTypeTrait::parse(args[1]) \ + ); \ + return true; \ +} + +#define TOOLS_RPC_DISPATCH3(Method, T1, T2, T3) \ +if (methodName == #Method) { \ + delegate->Method( \ + RpcTypeTrait::parse(args[0]), \ + RpcTypeTrait::parse(args[1]), \ + RpcTypeTrait::parse(args[2]) \ + ); \ + return true; \ +} + +#define TOOLS_RPC_DISPATCH4(Method, T1, T2, T3, T4) \ +if (methodName == #Method) { \ + delegate->Method( \ + RpcTypeTrait::parse(args[0]), \ + RpcTypeTrait::parse(args[1]), \ + RpcTypeTrait::parse(args[2]), \ + RpcTypeTrait::parse(args[3]) \ + ); \ + return true; \ +} + +#define TOOLS_RPC_DISPATCH5(Method, T1, T2, T3, T4, T5) \ +if (methodName == #Method) { \ + delegate->Method( \ + RpcTypeTrait::parse(args[0]), \ + RpcTypeTrait::parse(args[1]), \ + RpcTypeTrait::parse(args[2]), \ + RpcTypeTrait::parse(args[3]), \ + RpcTypeTrait::parse(args[4]) \ + ); \ + return true; \ +} + +#define TOOLS_END_RPC_DISPATCH() \ +} + +// This macro defines three classes: Class with the Api, ClassStub that is +// serializing method calls and ClassDispatch that is capable of dispatching +// the serialized message into its delegate. +#define DEFINE_RPC_CLASS(Class, STRUCT) \ +class Class : public Noncopyable {\ +public: \ + Class() \ + { \ + m_className = #Class; \ + } \ + virtual ~Class() { } \ + \ + STRUCT( \ + TOOLS_RPC_API_METHOD0, \ + TOOLS_RPC_API_METHOD1, \ + TOOLS_RPC_API_METHOD2, \ + TOOLS_RPC_API_METHOD3, \ + TOOLS_RPC_API_METHOD4, \ + TOOLS_RPC_API_METHOD5) \ + WebCore::String m_className; \ +}; \ +\ +class Class##Stub \ + : public Class \ + , public DevToolsRPC { \ +public: \ + explicit Class##Stub(Delegate* delegate) : DevToolsRPC(delegate) { } \ + 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_METHOD4, \ + TOOLS_RPC_STUB_METHOD5) \ +}; \ +\ +class Class##Dispatch : public Noncopyable { \ +public: \ + Class##Dispatch() { } \ + virtual ~Class##Dispatch() { } \ + \ + static bool dispatch(Class* delegate, \ + const WebKit::WebDevToolsMessageData& data) { \ + String className = data.className; \ + if (className != #Class) \ + return false; \ + String methodName = data.methodName; \ + Vector args; \ + for (size_t i = 0; i < data.arguments.size(); i++) \ + args.append(data.arguments[i]); \ + typedef Class CLASS; \ + STRUCT( \ + TOOLS_RPC_DISPATCH0, \ + TOOLS_RPC_DISPATCH1, \ + TOOLS_RPC_DISPATCH2, \ + TOOLS_RPC_DISPATCH3, \ + TOOLS_RPC_DISPATCH4, \ + TOOLS_RPC_DISPATCH5) \ + return false; \ + } \ +}; + +/////////////////////////////////////////////////////// +// RPC base class +class DevToolsRPC { +public: + class Delegate { + public: + Delegate() { } + virtual ~Delegate() { } + virtual void sendRpcMessage(const WebKit::WebDevToolsMessageData& data) = 0; + }; + + explicit DevToolsRPC(Delegate* delegate) : m_delegate(delegate) { } + virtual ~DevToolsRPC() { }; + +protected: + void sendRpcMessage(const String& className, + const String& methodName, + const Vector& args) { + WebKit::WebVector webArgs(args.size()); + for (size_t i = 0; i < args.size(); i++) + webArgs[i] = args[i]; + WebKit::WebDevToolsMessageData data; + data.className = className; + data.methodName = methodName; + data.arguments.swap(webArgs); + this->m_delegate->sendRpcMessage(data); + } + + Delegate* m_delegate; +}; + +} // namespace WebKit + +#endif