/* * 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 #include #include #include namespace WebKit { class WebFrame; class WebString; } typedef Vector 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.. 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 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 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 void bindMethod(const std::string& name, void (T::*method)(const CppArgumentList&, CppVariant*)) { Callback* callback = new MemberCallback(static_cast(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 void bindProperty(const std::string& name, void (T::*method)(CppVariant*)) { GetterCallback* callback = new MemberGetterCallback(static_cast(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 void bindFallbackMethod(void (T::*method)(const CppArgumentList&, CppVariant*)) { if (method) { Callback* callback = new MemberCallback(static_cast(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 PropertyList; typedef HashMap 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 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