WebKitTools/DumpRenderTree/chromium/CppBoundClass.h
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org)
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions are
       
     7  * met:
       
     8  *
       
     9  *     * Redistributions of source code must retain the above copyright
       
    10  * notice, this list of conditions and the following disclaimer.
       
    11  *     * Redistributions in binary form must reproduce the above
       
    12  * copyright notice, this list of conditions and the following disclaimer
       
    13  * in the documentation and/or other materials provided with the
       
    14  * distribution.
       
    15  *     * Neither the name of Google Inc. nor the names of its
       
    16  * contributors may be used to endorse or promote products derived from
       
    17  * this software without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 /*
       
    33   CppBoundClass class:
       
    34   This base class serves as a parent for C++ classes designed to be bound to
       
    35   JavaScript objects.
       
    36 
       
    37   Subclasses should define the constructor to build the property and method
       
    38   lists needed to bind this class to a JS object.  They should also declare
       
    39   and define member variables and methods to be exposed to JS through
       
    40   that object.
       
    41 */
       
    42 
       
    43 #ifndef CppBoundClass_h
       
    44 #define CppBoundClass_h
       
    45 
       
    46 #include "CppVariant.h"
       
    47 #include <wtf/HashMap.h>
       
    48 #include <wtf/Noncopyable.h>
       
    49 #include <wtf/OwnPtr.h>
       
    50 #include <wtf/Vector.h>
       
    51 
       
    52 namespace WebKit {
       
    53 class WebFrame;
       
    54 class WebString;
       
    55 }
       
    56 
       
    57 typedef Vector<CppVariant> CppArgumentList;
       
    58 
       
    59 // CppBoundClass lets you map Javascript method calls and property accesses
       
    60 // directly to C++ method calls and CppVariant* variable access.
       
    61 class CppBoundClass : public Noncopyable {
       
    62 public:
       
    63     class PropertyCallback {
       
    64     public:
       
    65         virtual ~PropertyCallback() { }
       
    66 
       
    67         // Sets |value| to the value of the property. Returns false in case of
       
    68         // failure. |value| is always non-0.
       
    69         virtual bool getValue(CppVariant* result) = 0;
       
    70 
       
    71         // sets the property value to |value|. Returns false in case of failure.
       
    72         virtual bool setValue(const CppVariant&) = 0;
       
    73     };
       
    74 
       
    75     // Callback class for "void function(CppVariant*)"
       
    76     class GetterCallback {
       
    77     public:
       
    78         virtual ~GetterCallback() {}
       
    79         virtual void run(CppVariant*) = 0;
       
    80     };
       
    81 
       
    82     // The constructor should call BindMethod, BindProperty, and
       
    83     // SetFallbackMethod as needed to set up the methods, properties, and
       
    84     // fallback method.
       
    85     CppBoundClass() : m_boundToFrame(false) {}
       
    86     virtual ~CppBoundClass();
       
    87 
       
    88     // Return a CppVariant representing this class, for use with BindProperty().
       
    89     // The variant type is guaranteed to be NPVariantType_Object.
       
    90     CppVariant* getAsCppVariant();
       
    91 
       
    92     // Given a WebFrame, BindToJavascript builds the NPObject that will represent
       
    93     // the class and binds it to the frame's window under the given name.  This
       
    94     // should generally be called from the WebView delegate's
       
    95     // WindowObjectCleared(). A class so bound will be accessible to JavaScript
       
    96     // as window.<classname>. The owner of the CppBoundObject is responsible for
       
    97     // keeping the object around while the frame is alive, and for destroying it
       
    98     // afterwards.
       
    99     void bindToJavascript(WebKit::WebFrame*, const WebKit::WebString& classname);
       
   100 
       
   101     // Used by a test.  Returns true if a method with name |name| exists,
       
   102     // regardless of whether a fallback is registered.
       
   103     bool isMethodRegistered(const std::string&) const;
       
   104 
       
   105 protected:
       
   106     // Callback for "void function(const CppArguemntList&, CppVariant*)"
       
   107     class Callback {
       
   108     public:
       
   109         virtual ~Callback() {}
       
   110         virtual void run(const CppArgumentList&, CppVariant*) = 0;
       
   111     };
       
   112 
       
   113     // Callback for "void T::method(const CppArguemntList&, CppVariant*)"
       
   114     template <class T> class MemberCallback : public Callback {
       
   115     public:
       
   116         typedef void (T::*MethodType)(const CppArgumentList&, CppVariant*);
       
   117         MemberCallback(T* object, MethodType method)
       
   118             : m_object(object)
       
   119             , m_method(method) {}
       
   120         virtual ~MemberCallback() {}
       
   121 
       
   122         virtual void run(const CppArgumentList& arguments, CppVariant* result)
       
   123         {
       
   124             (m_object->*m_method)(arguments, result);
       
   125         }
       
   126     private:
       
   127         T* m_object;
       
   128         MethodType m_method;
       
   129     };
       
   130 
       
   131     // Callback class for "void T::method(CppVariant*)"
       
   132     template <class T> class MemberGetterCallback : public GetterCallback {
       
   133     public:
       
   134         typedef void (T::*MethodType)(CppVariant*);
       
   135         MemberGetterCallback(T* object, MethodType method)
       
   136             : m_object(object)
       
   137             , m_method(method) {}
       
   138         virtual ~MemberGetterCallback() {}
       
   139 
       
   140         virtual void run(CppVariant* result) { (m_object->*m_method)(result); }
       
   141     private:
       
   142         T* m_object;
       
   143         MethodType m_method;
       
   144     };
       
   145 
       
   146     // Bind the Javascript method called the string parameter to the C++ method.
       
   147     void bindCallback(const std::string&, Callback*);
       
   148 
       
   149     // A wrapper for bindCallback, to simplify the common case of binding a
       
   150     // method on the current object.  Though not verified here, |method|
       
   151     // must be a method of this CppBoundClass subclass.
       
   152     template<class T>
       
   153     void bindMethod(const std::string& name, void (T::*method)(const CppArgumentList&, CppVariant*))
       
   154     {
       
   155         Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method);
       
   156         bindCallback(name, callback);
       
   157     }
       
   158 
       
   159     // Bind Javascript property |name| to the C++ getter callback |callback|.
       
   160     // This can be used to create read-only properties.
       
   161     void bindGetterCallback(const std::string&, GetterCallback*);
       
   162 
       
   163     // A wrapper for BindGetterCallback, to simplify the common case of binding a
       
   164     // property on the current object.  Though not verified here, |method|
       
   165     // must be a method of this CppBoundClass subclass.
       
   166     template<class T>
       
   167     void bindProperty(const std::string& name, void (T::*method)(CppVariant*))
       
   168     {
       
   169         GetterCallback* callback = new MemberGetterCallback<T>(static_cast<T*>(this), method);
       
   170         bindGetterCallback(name, callback);
       
   171     }
       
   172 
       
   173     // Bind the Javascript property called |name| to a CppVariant.
       
   174     void bindProperty(const std::string&, CppVariant*);
       
   175 
       
   176     // Bind Javascript property called |name| to a PropertyCallback.
       
   177     // CppBoundClass assumes control over the life time of the callback.
       
   178     void bindProperty(const std::string&, PropertyCallback*);
       
   179 
       
   180     // Set the fallback callback, which is called when when a callback is
       
   181     // invoked that isn't bound.
       
   182     // If it is 0 (its default value), a JavaScript exception is thrown in
       
   183     // that case (as normally expected). If non 0, the fallback method is
       
   184     // invoked and the script continues its execution.
       
   185     // Passing 0 clears out any existing binding.
       
   186     // It is used for tests and should probably only be used in such cases
       
   187     // as it may cause unexpected behaviors (a JavaScript object with a
       
   188     // fallback always returns true when checked for a method's
       
   189     // existence).
       
   190     void bindFallbackCallback(Callback* fallbackCallback)
       
   191     {
       
   192         m_fallbackCallback.set(fallbackCallback);
       
   193     }
       
   194 
       
   195     // A wrapper for BindFallbackCallback, to simplify the common case of
       
   196     // binding a method on the current object.  Though not verified here,
       
   197     // |method| must be a method of this CppBoundClass subclass.
       
   198     // Passing 0 for |method| clears out any existing binding.
       
   199     template<class T>
       
   200     void bindFallbackMethod(void (T::*method)(const CppArgumentList&, CppVariant*))
       
   201     {
       
   202         if (method) {
       
   203             Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method);
       
   204             bindFallbackCallback(callback);
       
   205         } else
       
   206             bindFallbackCallback(0);
       
   207     }
       
   208 
       
   209     // Some fields are protected because some tests depend on accessing them,
       
   210     // but otherwise they should be considered private.
       
   211 
       
   212     typedef HashMap<NPIdentifier, PropertyCallback*> PropertyList;
       
   213     typedef HashMap<NPIdentifier, Callback*> MethodList;
       
   214     // These maps associate names with property and method pointers to be
       
   215     // exposed to JavaScript.
       
   216     PropertyList m_properties;
       
   217     MethodList m_methods;
       
   218 
       
   219     // The callback gets invoked when a call is made to an nonexistent method.
       
   220     OwnPtr<Callback> m_fallbackCallback;
       
   221 
       
   222 private:
       
   223     // NPObject callbacks.
       
   224     friend struct CppNPObject;
       
   225     bool hasMethod(NPIdentifier) const;
       
   226     bool invoke(NPIdentifier, const NPVariant* args, size_t argCount,
       
   227                 NPVariant* result);
       
   228     bool hasProperty(NPIdentifier) const;
       
   229     bool getProperty(NPIdentifier, NPVariant* result) const;
       
   230     bool setProperty(NPIdentifier, const NPVariant*);
       
   231 
       
   232     // A lazily-initialized CppVariant representing this class.  We retain 1
       
   233     // reference to this object, and it is released on deletion.
       
   234     CppVariant m_selfVariant;
       
   235 
       
   236     // True if our np_object has been bound to a WebFrame, in which case it must
       
   237     // be unregistered with V8 when we delete it.
       
   238     bool m_boundToFrame;
       
   239 };
       
   240 
       
   241 #endif // CppBoundClass_h