diff options
Diffstat (limited to 'content/shell/renderer/test_runner/CppBoundClass.h')
-rw-r--r-- | content/shell/renderer/test_runner/CppBoundClass.h | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/content/shell/renderer/test_runner/CppBoundClass.h b/content/shell/renderer/test_runner/CppBoundClass.h new file mode 100644 index 0000000..f3870fd --- /dev/null +++ b/content/shell/renderer/test_runner/CppBoundClass.h @@ -0,0 +1,251 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* + * 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 <map> +#include <vector> + +#include "content/shell/renderer/test_runner/CppVariant.h" +#include "content/shell/renderer/test_runner/WebScopedPtr.h" +#include "third_party/WebKit/public/platform/WebNonCopyable.h" + +namespace blink { +class WebFrame; +class WebString; +} + +namespace WebTestRunner { + +typedef std::vector<CppVariant> CppArgumentList; + +// CppBoundClass lets you map Javascript method calls and property accesses +// directly to C++ method calls and CppVariant* variable access. +class CppBoundClass : public blink::WebNonCopyable { +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(blink::WebFrame*, const blink::WebString& classname); + + // Used by a test. Returns true if a method with the specified 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, the method parameter + // 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&, WebScopedPtr<GetterCallback>); + + // A wrapper for BindGetterCallback, to simplify the common case of binding a + // property on the current object. Though not verified here, the method parameter + // must be a method of this CppBoundClass subclass. + template<class T> + void bindProperty(const std::string& name, void (T::*method)(CppVariant*)) + { + WebScopedPtr<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(WebScopedPtr<Callback> fallbackCallback) + { + m_fallbackCallback = 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) + bindFallbackCallback(WebScopedPtr<Callback>(new MemberCallback<T>(static_cast<T*>(this), method))); + else + bindFallbackCallback(WebScopedPtr<Callback>()); + } + + // Some fields are protected because some tests depend on accessing them, + // but otherwise they should be considered private. + + typedef std::map<NPIdentifier, PropertyCallback*> PropertyList; + typedef std::map<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. + WebScopedPtr<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 |