1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CppBoundClass class: 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch This base class serves as a parent for C++ classes designed to be bound to 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch JavaScript objects. 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Subclasses should define the constructor to build the property and method 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lists needed to bind this class to a JS object. They should also declare 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch and define member variables and methods to be exposed to JS through 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch that object. 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch See cpp_binding_example.{h|cc} for an example. 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*/ 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WEBKIT_GLUE_CPP_BOUNDCLASS_H__ 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WEBKIT_GLUE_CPP_BOUNDCLASS_H__ 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map> 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/cpp_variant.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace WebKit { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebFrame; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::vector<CppVariant> CppArgumentList; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CppBoundClass lets you map Javascript method calls and property accesses 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// directly to C++ method calls and CppVariant* variable access. 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBoundClass { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class PropertyCallback { 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~PropertyCallback() { } 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets |value| to the value of the property. Returns false in case of 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // failure. |value| is always non-NULL. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual bool GetValue(CppVariant* value) = 0; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sets the property value to |value|. Returns false in case of failure. 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual bool SetValue(const CppVariant& value) = 0; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The constructor should call BindMethod, BindProperty, and 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SetFallbackMethod as needed to set up the methods, properties, and 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fallback method. 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CppBoundClass(); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~CppBoundClass(); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return a CppVariant representing this class, for use with BindProperty(). 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The variant type is guaranteed to be NPVariantType_Object. 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CppVariant* GetAsCppVariant(); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Given a WebFrame, BindToJavascript builds the NPObject that will represent 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the class and binds it to the frame's window under the given name. This 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should generally be called from the WebView delegate's 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WindowObjectCleared(). A class so bound will be accessible to JavaScript 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as window.<classname>. The owner of the CppBoundObject is responsible for 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // keeping the object around while the frame is alive, and for destroying it 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // afterwards. 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void BindToJavascript(WebKit::WebFrame* frame, const std::string& classname); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The type of callbacks. 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef Callback2<const CppArgumentList&, CppVariant*>::Type Callback; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef Callback1<CppVariant*>::Type GetterCallback; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used by a test. Returns true if a method with name |name| exists, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // regardless of whether a fallback is registered. 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool IsMethodRegistered(const std::string& name) const; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bind the Javascript method called |name| to the C++ callback |callback|. 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindCallback(const std::string& name, Callback* callback); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A wrapper for BindCallback, to simplify the common case of binding a 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // method on the current object. Though not verified here, |method| 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // must be a method of this CppBoundClass subclass. 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch template<typename T> 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindMethod(const std::string& name, 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void (T::*method)(const CppArgumentList&, CppVariant*)) { 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Callback* callback = 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback<T, const CppArgumentList&, CppVariant*>( 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<T*>(this), method); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BindCallback(name, callback); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bind Javascript property |name| to the C++ getter callback |callback|. 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This can be used to create read-only properties. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindGetterCallback(const std::string& name, GetterCallback* callback); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A wrapper for BindGetterCallback, to simplify the common case of binding a 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // property on the current object. Though not verified here, |method| 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // must be a method of this CppBoundClass subclass. 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch template<typename T> 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindProperty(const std::string& name, void (T::*method)(CppVariant*)) { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetterCallback* callback = 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback<T, CppVariant*>(static_cast<T*>(this), method); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BindGetterCallback(name, callback); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bind the Javascript property called |name| to a CppVariant |prop|. 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindProperty(const std::string& name, CppVariant* prop); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bind Javascript property called |name| to a PropertyCallback |callback|. 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CppBoundClass assumes control over the life time of the |callback|. 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindProperty(const std::string& name, PropertyCallback* callback); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the fallback callback, which is called when when a callback is 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // invoked that isn't bound. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If it is NULL (its default value), a JavaScript exception is thrown in 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that case (as normally expected). If non NULL, the fallback method is 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // invoked and the script continues its execution. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Passing NULL for |callback| clears out any existing binding. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It is used for tests and should probably only be used in such cases 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as it may cause unexpected behaviors (a JavaScript object with a 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fallback always returns true when checked for a method's 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // existence). 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindFallbackCallback(Callback* fallback_callback) { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fallback_callback_.reset(fallback_callback); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A wrapper for BindFallbackCallback, to simplify the common case of 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // binding a method on the current object. Though not verified here, 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |method| must be a method of this CppBoundClass subclass. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Passing NULL for |method| clears out any existing binding. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch template<typename T> 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BindFallbackMethod( 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void (T::*method)(const CppArgumentList&, CppVariant*)) { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (method) { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Callback* callback = 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback<T, const CppArgumentList&, CppVariant*>( 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<T*>(this), method); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BindFallbackCallback(callback); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BindFallbackCallback(NULL); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Some fields are protected because some tests depend on accessing them, 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but otherwise they should be considered private. 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<NPIdentifier, PropertyCallback*> PropertyList; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<NPIdentifier, Callback*> MethodList; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These maps associate names with property and method pointers to be 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // exposed to JavaScript. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PropertyList properties_; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MethodList methods_; 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The callback gets invoked when a call is made to an nonexistent method. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Callback> fallback_callback_; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NPObject callbacks. 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend struct CppNPObject; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool HasMethod(NPIdentifier ident) const; 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Invoke(NPIdentifier ident, const NPVariant* args, size_t arg_count, 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NPVariant* result); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool HasProperty(NPIdentifier ident) const; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool GetProperty(NPIdentifier ident, NPVariant* result) const; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool SetProperty(NPIdentifier ident, const NPVariant* value); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A lazily-initialized CppVariant representing this class. We retain 1 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reference to this object, and it is released on deletion. 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CppVariant self_variant_; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // True if our np_object has been bound to a WebFrame, in which case it must 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be unregistered with V8 when we delete it. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool bound_to_frame_; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(CppBoundClass); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CPP_BOUNDCLASS_H__ 181