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 |
|