| /* |
| * Copyright (C) 2010 Google Inc. All rights reserved. |
| * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org) |
| * |
| * 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. |
| */ |
| |
| /* |
| CppBoundClass class: |
| This base class serves as a parent for C++ classes designed to be bound to |
| JavaScript objects. |
| |
| Subclasses should define the constructor to build the property and method |
| lists needed to bind this class to a JS object. They should also declare |
| and define member variables and methods to be exposed to JS through |
| that object. |
| */ |
| |
| #ifndef CppBoundClass_h |
| #define CppBoundClass_h |
| |
| #include "CppVariant.h" |
| #include <wtf/HashMap.h> |
| #include <wtf/Noncopyable.h> |
| #include <wtf/OwnPtr.h> |
| #include <wtf/Vector.h> |
| |
| namespace WebKit { |
| class WebFrame; |
| class WebString; |
| } |
| |
| typedef Vector<CppVariant> CppArgumentList; |
| |
| // CppBoundClass lets you map Javascript method calls and property accesses |
| // directly to C++ method calls and CppVariant* variable access. |
| class CppBoundClass { |
| WTF_MAKE_NONCOPYABLE(CppBoundClass); |
| public: |
| class PropertyCallback { |
| public: |
| virtual ~PropertyCallback() { } |
| |
| // Sets |value| to the value of the property. Returns false in case of |
| // failure. |value| is always non-0. |
| virtual bool getValue(CppVariant* result) = 0; |
| |
| // sets the property value to |value|. Returns false in case of failure. |
| virtual bool setValue(const CppVariant&) = 0; |
| }; |
| |
| // Callback class for "void function(CppVariant*)" |
| class GetterCallback { |
| public: |
| virtual ~GetterCallback() {} |
| virtual void run(CppVariant*) = 0; |
| }; |
| |
| // The constructor should call BindMethod, BindProperty, and |
| // SetFallbackMethod as needed to set up the methods, properties, and |
| // fallback method. |
| CppBoundClass() : m_boundToFrame(false) {} |
| virtual ~CppBoundClass(); |
| |
| // Return a CppVariant representing this class, for use with BindProperty(). |
| // The variant type is guaranteed to be NPVariantType_Object. |
| CppVariant* getAsCppVariant(); |
| |
| // Given a WebFrame, BindToJavascript builds the NPObject that will represent |
| // the class and binds it to the frame's window under the given name. This |
| // should generally be called from the WebView delegate's |
| // WindowObjectCleared(). A class so bound will be accessible to JavaScript |
| // as window.<classname>. The owner of the CppBoundObject is responsible for |
| // keeping the object around while the frame is alive, and for destroying it |
| // afterwards. |
| void bindToJavascript(WebKit::WebFrame*, const WebKit::WebString& classname); |
| |
| // Used by a test. Returns true if a method with name |name| exists, |
| // regardless of whether a fallback is registered. |
| bool isMethodRegistered(const std::string&) const; |
| |
| protected: |
| // Callback for "void function(const CppArguemntList&, CppVariant*)" |
| class Callback { |
| public: |
| virtual ~Callback() {} |
| virtual void run(const CppArgumentList&, CppVariant*) = 0; |
| }; |
| |
| // Callback for "void T::method(const CppArguemntList&, CppVariant*)" |
| template <class T> class MemberCallback : public Callback { |
| public: |
| typedef void (T::*MethodType)(const CppArgumentList&, CppVariant*); |
| MemberCallback(T* object, MethodType method) |
| : m_object(object) |
| , m_method(method) {} |
| virtual ~MemberCallback() {} |
| |
| virtual void run(const CppArgumentList& arguments, CppVariant* result) |
| { |
| (m_object->*m_method)(arguments, result); |
| } |
| private: |
| T* m_object; |
| MethodType m_method; |
| }; |
| |
| // Callback class for "void T::method(CppVariant*)" |
| template <class T> class MemberGetterCallback : public GetterCallback { |
| public: |
| typedef void (T::*MethodType)(CppVariant*); |
| MemberGetterCallback(T* object, MethodType method) |
| : m_object(object) |
| , m_method(method) {} |
| virtual ~MemberGetterCallback() {} |
| |
| virtual void run(CppVariant* result) { (m_object->*m_method)(result); } |
| private: |
| T* m_object; |
| MethodType m_method; |
| }; |
| |
| // Bind the Javascript method called the string parameter to the C++ method. |
| void bindCallback(const std::string&, Callback*); |
| |
| // A wrapper for bindCallback, to simplify the common case of binding a |
| // method on the current object. Though not verified here, |method| |
| // must be a method of this CppBoundClass subclass. |
| template<class T> |
| void bindMethod(const std::string& name, void (T::*method)(const CppArgumentList&, CppVariant*)) |
| { |
| Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method); |
| bindCallback(name, callback); |
| } |
| |
| // Bind Javascript property |name| to the C++ getter callback |callback|. |
| // This can be used to create read-only properties. |
| void bindGetterCallback(const std::string&, GetterCallback*); |
| |
| // A wrapper for BindGetterCallback, to simplify the common case of binding a |
| // property on the current object. Though not verified here, |method| |
| // must be a method of this CppBoundClass subclass. |
| template<class T> |
| void bindProperty(const std::string& name, void (T::*method)(CppVariant*)) |
| { |
| GetterCallback* callback = new MemberGetterCallback<T>(static_cast<T*>(this), method); |
| bindGetterCallback(name, callback); |
| } |
| |
| // Bind the Javascript property called |name| to a CppVariant. |
| void bindProperty(const std::string&, CppVariant*); |
| |
| // Bind Javascript property called |name| to a PropertyCallback. |
| // CppBoundClass assumes control over the life time of the callback. |
| void bindProperty(const std::string&, PropertyCallback*); |
| |
| // Set the fallback callback, which is called when when a callback is |
| // invoked that isn't bound. |
| // If it is 0 (its default value), a JavaScript exception is thrown in |
| // that case (as normally expected). If non 0, the fallback method is |
| // invoked and the script continues its execution. |
| // Passing 0 clears out any existing binding. |
| // It is used for tests and should probably only be used in such cases |
| // as it may cause unexpected behaviors (a JavaScript object with a |
| // fallback always returns true when checked for a method's |
| // existence). |
| void bindFallbackCallback(Callback* fallbackCallback) |
| { |
| m_fallbackCallback.set(fallbackCallback); |
| } |
| |
| // A wrapper for BindFallbackCallback, to simplify the common case of |
| // binding a method on the current object. Though not verified here, |
| // |method| must be a method of this CppBoundClass subclass. |
| // Passing 0 for |method| clears out any existing binding. |
| template<class T> |
| void bindFallbackMethod(void (T::*method)(const CppArgumentList&, CppVariant*)) |
| { |
| if (method) { |
| Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method); |
| bindFallbackCallback(callback); |
| } else |
| bindFallbackCallback(0); |
| } |
| |
| // Some fields are protected because some tests depend on accessing them, |
| // but otherwise they should be considered private. |
| |
| typedef HashMap<NPIdentifier, PropertyCallback*> PropertyList; |
| typedef HashMap<NPIdentifier, Callback*> MethodList; |
| // These maps associate names with property and method pointers to be |
| // exposed to JavaScript. |
| PropertyList m_properties; |
| MethodList m_methods; |
| |
| // The callback gets invoked when a call is made to an nonexistent method. |
| OwnPtr<Callback> m_fallbackCallback; |
| |
| private: |
| // NPObject callbacks. |
| friend struct CppNPObject; |
| bool hasMethod(NPIdentifier) const; |
| bool invoke(NPIdentifier, const NPVariant* args, size_t argCount, |
| NPVariant* result); |
| bool hasProperty(NPIdentifier) const; |
| bool getProperty(NPIdentifier, NPVariant* result) const; |
| bool setProperty(NPIdentifier, const NPVariant*); |
| |
| // A lazily-initialized CppVariant representing this class. We retain 1 |
| // reference to this object, and it is released on deletion. |
| CppVariant m_selfVariant; |
| |
| // True if our np_object has been bound to a WebFrame, in which case it must |
| // be unregistered with V8 when we delete it. |
| bool m_boundToFrame; |
| }; |
| |
| #endif // CppBoundClass_h |