WebKit/chromium/src/DevToolsRPC.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 // DevTools RPC subsystem is a simple string serialization-based rpc
       
    32 // implementation. The client is responsible for defining the Rpc-enabled
       
    33 // interface in terms of its macros:
       
    34 //
       
    35 // #define MYAPI_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3)
       
    36 //   METHOD0(Method1)
       
    37 //   METHOD1(Method3, int)
       
    38 // (snippet above should be multiline macro, add trailing backslashes)
       
    39 //
       
    40 // DEFINE_RPC_CLASS(MyApi, MYAPI_STRUCT)
       
    41 //
       
    42 // The snippet above will generate three classes: MyApi, MyApiStub and
       
    43 // MyApiDispatch.
       
    44 //
       
    45 // 1. For each method defined in the marco MyApi will have a
       
    46 // pure virtual function generated, so that MyApi would look like:
       
    47 //
       
    48 // class MyApi {
       
    49 // private:
       
    50 //     MyApi() { }
       
    51 //     ~MyApi() { }
       
    52 //     virtual void method1() = 0;
       
    53 //     virtual void method2(
       
    54 //         int param1,
       
    55 //         const String& param2,
       
    56 //         const Value& param3) = 0;
       
    57 //     virtual void method3(int param1) = 0;
       
    58 // };
       
    59 //
       
    60 // 2. MyApiStub will implement MyApi interface and would serialize all calls
       
    61 // into the string-based calls of the underlying transport:
       
    62 //
       
    63 // DevToolsRPC::Delegate* transport;
       
    64 // myApi = new MyApiStub(transport);
       
    65 // myApi->method1();
       
    66 // myApi->method3(2);
       
    67 //
       
    68 // 3. MyApiDelegate is capable of dispatching the calls and convert them to the
       
    69 // calls to the underlying MyApi methods:
       
    70 //
       
    71 // MyApi* realObject;
       
    72 // MyApiDispatch::dispatch(realObject, rawStringCallGeneratedByStub);
       
    73 //
       
    74 // will make corresponding calls to the real object.
       
    75 
       
    76 #ifndef DevToolsRPC_h
       
    77 #define DevToolsRPC_h
       
    78 
       
    79 #include "PlatformString.h"
       
    80 #include "Vector.h"
       
    81 #include "WebDevToolsMessageData.h"
       
    82 
       
    83 #include <wtf/Noncopyable.h>
       
    84 
       
    85 namespace WebCore {
       
    86 class String;
       
    87 }
       
    88 
       
    89 using WebCore::String;
       
    90 using WTF::Vector;
       
    91 
       
    92 namespace WebKit {
       
    93 
       
    94 ///////////////////////////////////////////////////////
       
    95 // RPC dispatch macro
       
    96 
       
    97 template<typename T>
       
    98 struct RpcTypeTrait {
       
    99     typedef T ApiType;
       
   100 };
       
   101 
       
   102 template<>
       
   103 struct RpcTypeTrait<bool> {
       
   104     typedef bool ApiType;
       
   105     static bool parse(const WebCore::String& t)
       
   106     {
       
   107         return t == "true";
       
   108     }
       
   109     static WebCore::String toString(bool b)
       
   110     {
       
   111         return b ? "true" : "false";
       
   112     }
       
   113 };
       
   114 
       
   115 template<>
       
   116 struct RpcTypeTrait<int> {
       
   117     typedef int ApiType;
       
   118     static int parse(const WebCore::String& t)
       
   119     {
       
   120         bool success;
       
   121         int i = t.toIntStrict(&success);
       
   122         ASSERT(success);
       
   123         return i;
       
   124     }
       
   125     static WebCore::String toString(int i)
       
   126     {
       
   127         return WebCore::String::number(i);
       
   128     }
       
   129 };
       
   130 
       
   131 template<>
       
   132 struct RpcTypeTrait<String> {
       
   133     typedef const String& ApiType;
       
   134     static String parse(const WebCore::String& t)
       
   135     {
       
   136         return t;
       
   137     }
       
   138     static WebCore::String toString(const String& t)
       
   139     {
       
   140         return t;
       
   141     }
       
   142 };
       
   143 
       
   144 ///////////////////////////////////////////////////////
       
   145 // RPC Api method declarations
       
   146 
       
   147 #define TOOLS_RPC_API_METHOD0(Method) \
       
   148     virtual void Method() = 0;
       
   149 
       
   150 #define TOOLS_RPC_API_METHOD1(Method, T1) \
       
   151     virtual void Method(RpcTypeTrait<T1>::ApiType t1) = 0;
       
   152 
       
   153 #define TOOLS_RPC_API_METHOD2(Method, T1, T2) \
       
   154     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   155                         RpcTypeTrait<T2>::ApiType t2) = 0;
       
   156 
       
   157 #define TOOLS_RPC_API_METHOD3(Method, T1, T2, T3) \
       
   158     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   159                         RpcTypeTrait<T2>::ApiType t2, \
       
   160                         RpcTypeTrait<T3>::ApiType t3) = 0;
       
   161 
       
   162 #define TOOLS_RPC_API_METHOD4(Method, T1, T2, T3, T4) \
       
   163     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   164                         RpcTypeTrait<T2>::ApiType t2, \
       
   165                         RpcTypeTrait<T3>::ApiType t3, \
       
   166                         RpcTypeTrait<T4>::ApiType t4) = 0;
       
   167 
       
   168 #define TOOLS_RPC_API_METHOD5(Method, T1, T2, T3, T4, T5) \
       
   169     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   170                         RpcTypeTrait<T2>::ApiType t2, \
       
   171                         RpcTypeTrait<T3>::ApiType t3, \
       
   172                         RpcTypeTrait<T4>::ApiType t4, \
       
   173                         RpcTypeTrait<T5>::ApiType t5) = 0;
       
   174 
       
   175 ///////////////////////////////////////////////////////
       
   176 // RPC stub method implementations
       
   177 
       
   178 #define TOOLS_RPC_STUB_METHOD0(Method) \
       
   179     virtual void Method() { \
       
   180         Vector<String> args; \
       
   181         this->sendRpcMessage(m_className, #Method, args); \
       
   182     }
       
   183 
       
   184 #define TOOLS_RPC_STUB_METHOD1(Method, T1) \
       
   185     virtual void Method(RpcTypeTrait<T1>::ApiType t1) { \
       
   186         Vector<String> args(1); \
       
   187         args[0] = RpcTypeTrait<T1>::toString(t1); \
       
   188         this->sendRpcMessage(m_className, #Method, args); \
       
   189     }
       
   190 
       
   191 #define TOOLS_RPC_STUB_METHOD2(Method, T1, T2) \
       
   192     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   193                         RpcTypeTrait<T2>::ApiType t2) { \
       
   194         Vector<String> args(2); \
       
   195         args[0] = RpcTypeTrait<T1>::toString(t1); \
       
   196         args[1] = RpcTypeTrait<T2>::toString(t2); \
       
   197         this->sendRpcMessage(m_className, #Method, args); \
       
   198     }
       
   199 
       
   200 #define TOOLS_RPC_STUB_METHOD3(Method, T1, T2, T3) \
       
   201     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   202                         RpcTypeTrait<T2>::ApiType t2, \
       
   203                         RpcTypeTrait<T3>::ApiType t3) { \
       
   204         Vector<String> args(3); \
       
   205         args[0] = RpcTypeTrait<T1>::toString(t1); \
       
   206         args[1] = RpcTypeTrait<T2>::toString(t2); \
       
   207         args[2] = RpcTypeTrait<T3>::toString(t3); \
       
   208         this->sendRpcMessage(m_className, #Method, args); \
       
   209     }
       
   210 
       
   211 #define TOOLS_RPC_STUB_METHOD4(Method, T1, T2, T3, T4) \
       
   212     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   213                         RpcTypeTrait<T2>::ApiType t2, \
       
   214                         RpcTypeTrait<T3>::ApiType t3, \
       
   215                         RpcTypeTrait<T4>::ApiType t4) { \
       
   216         Vector<String> args(4); \
       
   217         args[0] = RpcTypeTrait<T1>::toString(t1); \
       
   218         args[1] = RpcTypeTrait<T2>::toString(t2); \
       
   219         args[2] = RpcTypeTrait<T3>::toString(t3); \
       
   220         args[3] = RpcTypeTrait<T4>::toString(t4); \
       
   221         this->sendRpcMessage(m_className, #Method, args); \
       
   222     }
       
   223 
       
   224 #define TOOLS_RPC_STUB_METHOD5(Method, T1, T2, T3, T4, T5) \
       
   225     virtual void Method(RpcTypeTrait<T1>::ApiType t1, \
       
   226                         RpcTypeTrait<T2>::ApiType t2, \
       
   227                         RpcTypeTrait<T3>::ApiType t3, \
       
   228                         RpcTypeTrait<T4>::ApiType t4, \
       
   229                         RpcTypeTrait<T5>::ApiType t5) { \
       
   230         Vector<String> args(5); \
       
   231         args[0] = RpcTypeTrait<T1>::toString(t1); \
       
   232         args[1] = RpcTypeTrait<T2>::toString(t2); \
       
   233         args[2] = RpcTypeTrait<T3>::toString(t3); \
       
   234         args[3] = RpcTypeTrait<T4>::toString(t4); \
       
   235         args[4] = RpcTypeTrait<T5>::toString(t5); \
       
   236         this->sendRpcMessage(m_className, #Method, args); \
       
   237     }
       
   238 
       
   239 ///////////////////////////////////////////////////////
       
   240 // RPC dispatch method implementations
       
   241 
       
   242 #define TOOLS_RPC_DISPATCH0(Method) \
       
   243 if (methodName == #Method) { \
       
   244     delegate->Method(); \
       
   245     return true; \
       
   246 }
       
   247 
       
   248 #define TOOLS_RPC_DISPATCH1(Method, T1) \
       
   249 if (methodName == #Method) { \
       
   250     delegate->Method(RpcTypeTrait<T1>::parse(args[0])); \
       
   251     return true; \
       
   252 }
       
   253 
       
   254 #define TOOLS_RPC_DISPATCH2(Method, T1, T2) \
       
   255 if (methodName == #Method) { \
       
   256     delegate->Method( \
       
   257         RpcTypeTrait<T1>::parse(args[0]), \
       
   258         RpcTypeTrait<T2>::parse(args[1]) \
       
   259     ); \
       
   260     return true; \
       
   261 }
       
   262 
       
   263 #define TOOLS_RPC_DISPATCH3(Method, T1, T2, T3) \
       
   264 if (methodName == #Method) { \
       
   265     delegate->Method( \
       
   266         RpcTypeTrait<T1>::parse(args[0]), \
       
   267         RpcTypeTrait<T2>::parse(args[1]), \
       
   268         RpcTypeTrait<T3>::parse(args[2]) \
       
   269     ); \
       
   270     return true; \
       
   271 }
       
   272 
       
   273 #define TOOLS_RPC_DISPATCH4(Method, T1, T2, T3, T4) \
       
   274 if (methodName == #Method) { \
       
   275     delegate->Method( \
       
   276         RpcTypeTrait<T1>::parse(args[0]), \
       
   277         RpcTypeTrait<T2>::parse(args[1]), \
       
   278         RpcTypeTrait<T3>::parse(args[2]), \
       
   279         RpcTypeTrait<T4>::parse(args[3]) \
       
   280     ); \
       
   281     return true; \
       
   282 }
       
   283 
       
   284 #define TOOLS_RPC_DISPATCH5(Method, T1, T2, T3, T4, T5) \
       
   285 if (methodName == #Method) { \
       
   286     delegate->Method( \
       
   287         RpcTypeTrait<T1>::parse(args[0]), \
       
   288         RpcTypeTrait<T2>::parse(args[1]), \
       
   289         RpcTypeTrait<T3>::parse(args[2]), \
       
   290         RpcTypeTrait<T4>::parse(args[3]), \
       
   291         RpcTypeTrait<T5>::parse(args[4]) \
       
   292     ); \
       
   293     return true; \
       
   294 }
       
   295 
       
   296 #define TOOLS_END_RPC_DISPATCH() \
       
   297 }
       
   298 
       
   299 // This macro defines three classes: Class with the Api, ClassStub that is
       
   300 // serializing method calls and ClassDispatch that is capable of dispatching
       
   301 // the serialized message into its delegate.
       
   302 #define DEFINE_RPC_CLASS(Class, STRUCT) \
       
   303 class Class : public Noncopyable {\
       
   304 public: \
       
   305     Class() \
       
   306     { \
       
   307         m_className = #Class; \
       
   308     } \
       
   309     virtual ~Class() { } \
       
   310     \
       
   311     STRUCT( \
       
   312         TOOLS_RPC_API_METHOD0, \
       
   313         TOOLS_RPC_API_METHOD1, \
       
   314         TOOLS_RPC_API_METHOD2, \
       
   315         TOOLS_RPC_API_METHOD3, \
       
   316         TOOLS_RPC_API_METHOD4, \
       
   317         TOOLS_RPC_API_METHOD5) \
       
   318     WebCore::String m_className; \
       
   319 }; \
       
   320 \
       
   321 class Class##Stub \
       
   322     : public Class \
       
   323     , public DevToolsRPC { \
       
   324 public: \
       
   325     explicit Class##Stub(Delegate* delegate) : DevToolsRPC(delegate) { } \
       
   326     virtual ~Class##Stub() { } \
       
   327     typedef Class CLASS; \
       
   328     STRUCT( \
       
   329         TOOLS_RPC_STUB_METHOD0, \
       
   330         TOOLS_RPC_STUB_METHOD1, \
       
   331         TOOLS_RPC_STUB_METHOD2, \
       
   332         TOOLS_RPC_STUB_METHOD3, \
       
   333         TOOLS_RPC_STUB_METHOD4, \
       
   334         TOOLS_RPC_STUB_METHOD5) \
       
   335 }; \
       
   336 \
       
   337 class Class##Dispatch : public Noncopyable { \
       
   338 public: \
       
   339     Class##Dispatch() { } \
       
   340     virtual ~Class##Dispatch() { } \
       
   341     \
       
   342     static bool dispatch(Class* delegate, \
       
   343                          const WebKit::WebDevToolsMessageData& data) { \
       
   344         String className = data.className; \
       
   345         if (className != #Class) \
       
   346             return false; \
       
   347         String methodName = data.methodName; \
       
   348         Vector<String> args; \
       
   349         for (size_t i = 0; i < data.arguments.size(); i++) \
       
   350             args.append(data.arguments[i]); \
       
   351         typedef Class CLASS; \
       
   352         STRUCT( \
       
   353             TOOLS_RPC_DISPATCH0, \
       
   354             TOOLS_RPC_DISPATCH1, \
       
   355             TOOLS_RPC_DISPATCH2, \
       
   356             TOOLS_RPC_DISPATCH3, \
       
   357             TOOLS_RPC_DISPATCH4, \
       
   358             TOOLS_RPC_DISPATCH5) \
       
   359         return false; \
       
   360     } \
       
   361 };
       
   362 
       
   363 ///////////////////////////////////////////////////////
       
   364 // RPC base class
       
   365 class DevToolsRPC {
       
   366 public:
       
   367     class Delegate {
       
   368     public:
       
   369         Delegate() { }
       
   370         virtual ~Delegate() { }
       
   371         virtual void sendRpcMessage(const WebKit::WebDevToolsMessageData& data) = 0;
       
   372     };
       
   373 
       
   374     explicit DevToolsRPC(Delegate* delegate) : m_delegate(delegate) { }
       
   375     virtual ~DevToolsRPC() { };
       
   376 
       
   377 protected:
       
   378     void sendRpcMessage(const String& className,
       
   379                         const String& methodName,
       
   380                         const Vector<String>& args) {
       
   381       WebKit::WebVector<WebKit::WebString> webArgs(args.size());
       
   382       for (size_t i = 0; i < args.size(); i++)
       
   383           webArgs[i] = args[i];
       
   384       WebKit::WebDevToolsMessageData data;
       
   385       data.className = className;
       
   386       data.methodName = methodName;
       
   387       data.arguments.swap(webArgs);
       
   388       this->m_delegate->sendRpcMessage(data);
       
   389     }
       
   390 
       
   391     Delegate* m_delegate;
       
   392 };
       
   393 
       
   394 } // namespace WebKit
       
   395 
       
   396 #endif