OLD | NEW |
| (Empty) |
1 // Copyright 2010 The Ginsu Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 #ifndef C_SALT_SCRIPTING_BRIDGE_H_ | |
6 #define C_SALT_SCRIPTING_BRIDGE_H_ | |
7 | |
8 // TODO(dspringer, dmichael): Remove this: | |
9 #include <nacl/npruntime.h> | |
10 | |
11 #include <map> | |
12 #include <string> | |
13 #include <vector> | |
14 | |
15 #include "boost/noncopyable.hpp" | |
16 #include "boost/shared_ptr.hpp" | |
17 #include "c_salt/callback.h" | |
18 #include "c_salt/property.h" | |
19 #include "c_salt/scriptable_native_object_ptrs.h" | |
20 #include "c_salt/variant.h" | |
21 | |
22 namespace c_salt { | |
23 | |
24 class Instance; | |
25 class Module; | |
26 | |
27 namespace npapi { | |
28 class BrowserBinding; | |
29 } // namespace npapi | |
30 | |
31 // This class handles all the calls across the bridge to the browser via its | |
32 // browser binding object, |browser_binding_|. Note that NPObjects cannot have | |
33 // a vtable, hence the PIMPL pattern used here. Use AddMethodNamed() and | |
34 // AddProperty() to publish methods and static properties that can be accessed | |
35 // from the browser code. | |
36 // | |
37 // TODO(dspringer): |browser_binding_| gets replaced by pp::ScriptableObject | |
38 // when Pepper v2 becomes available. | |
39 | |
40 class ScriptingBridge : public c_salt::ScriptingInterface, | |
41 public boost::noncopyable { | |
42 public: | |
43 virtual ~ScriptingBridge(); | |
44 | |
45 // Causes |method_name| to be published as a method that can be called by | |
46 // JavaScript. Associated this method with |method|. | |
47 // | |
48 // Usage: | |
49 // AddMethodNamed("myFunc", /* This is the JavaScript name for the method | |
50 // you want to expose. */ | |
51 // &handler, /* This is a pointer to an instance of the | |
52 // handler object. */ | |
53 // &Handler::MyFunc /* This is the class method that will | |
54 // get called when "myFunc" is invoked | |
55 // from JavaScript. */ | |
56 // ); | |
57 // | |
58 // Example: | |
59 // class MyClass { | |
60 // void InitializeMethods(ScriptingBridge*); | |
61 // bool MyFunc(int32_t, double, std::string); | |
62 // }; | |
63 // | |
64 // MyClass::InitializeMethods(ScriptingBridge* bridge) { | |
65 // bridge->AddMethodNamed("myFunc", this, MyClass::MyFunc); | |
66 // } | |
67 // | |
68 // Caveats: | |
69 // - Currently, only up to 6 arguments are supported. | |
70 // - void return types are currently not supported. | |
71 // - Supported parameter types are currently limited to: | |
72 // std::string, int32_t, bool, double, and shared_ptr<ScriptingBridge> | |
73 template <class T, class Signature> | |
74 bool AddMethodNamed(const std::string& method_name, | |
75 T* handler, | |
76 Signature method) { | |
77 if (method_name.empty() || method == NULL) | |
78 return false; | |
79 SharedMethodCallbackExecutor method_ptr( | |
80 new MethodCallbackExecutorImpl<Signature>(handler, method)); | |
81 method_dictionary_.insert(MethodDictionary::value_type(method_name, | |
82 method_ptr)); | |
83 return true; | |
84 } | |
85 | |
86 // Adds |property| to the property dictionary. These properties should all | |
87 // be declared as static, mutable properties (the default). See | |
88 // c_salt/property.h for details. Example usage: | |
89 // SharedVariant value(new c_salt::Variant(42)); | |
90 // PropertyAttributes prop_attrib("myProp", value); | |
91 // bridge->AddProperty(Property(prop_attribs)); | |
92 bool AddProperty(const Property& property); | |
93 // Return a Property by ref counting so this can be made thread-safe. Note | |
94 // that this method bumps the ref count of the underlying instance to a Value, | |
95 // the caller is responsible for freeing it. Sets |value| to point to a NULL | |
96 // Value and returns |false| if no such property exists. | |
97 bool GetValueForPropertyNamed(const std::string& name, | |
98 SharedVariant* value) const; | |
99 // Sets the value of the property associated with |name|. Returns |false| | |
100 // if no such property exists. | |
101 bool SetValueForPropertyNamed(const std::string& name, const Variant& value); | |
102 | |
103 | |
104 // Make a copy of the browser binding object by asking the browser to retain | |
105 // it. Use this for the return value of functions that expect the retain | |
106 // count to increment, such as NPP_GetScriptableInstance(). | |
107 NPObject* CopyBrowserBinding(); | |
108 | |
109 // Release the browser binding object. Note that this *might* cause |this| | |
110 // to get deleted, if the ref count of the browser binding object falls to 0. | |
111 void ReleaseBrowserBinding(); | |
112 | |
113 // Log a message to the browser's console window. You can usually see this | |
114 // message when using a JavaScript debugger, such as Chrome Developer Tools. | |
115 bool LogToConsole(const std::string& msg) const; | |
116 | |
117 // Return the browser instance associated with this ScriptingBridge. | |
118 const NPP& GetBrowserInstance() const; | |
119 | |
120 void set_native_object(SharedScriptableNativeObject native_object) { | |
121 native_object_ = native_object; | |
122 } | |
123 | |
124 // Accessors. | |
125 const npapi::BrowserBinding* browser_binding() const { | |
126 return browser_binding_; | |
127 } | |
128 SharedScriptableNativeObject native_object() { | |
129 return native_object_; | |
130 } | |
131 | |
132 // This does not return a const NPObject* because none of the NPAPI that uses | |
133 // this value accepts a const NPObject*. This will go away with Pepper V2 | |
134 // so I don't think it's worth thinking about too hard. | |
135 NPObject* window_object() const; | |
136 | |
137 // A hidden class that wraps the NPObject, preserving its memory layout | |
138 // for the browser. | |
139 friend class npapi::BrowserBinding; | |
140 | |
141 private: | |
142 typedef std::map<std::string, | |
143 SharedMethodCallbackExecutor> MethodDictionary; | |
144 typedef std::map<std::string, Property> PropertyDictionary; | |
145 | |
146 ScriptingBridge(); // Not implemented, do not use. | |
147 explicit ScriptingBridge(npapi::BrowserBinding* browser_binding); | |
148 | |
149 // Support for browser-exposed methods. The browser proxy (a private, | |
150 // platform-specific implementation) invokes a method by first calling | |
151 // HasScriptMethod(), and if that returns |true|, calls InvokeScriptMethod(). | |
152 // The browser proxy is responsible for all the variant marshaling from | |
153 // platform-specific types (for example NPVariant or pp::Var) into c_salt | |
154 // Types. | |
155 virtual bool HasScriptMethod(const std::string& name); | |
156 virtual bool InvokeScriptMethod(const std::string& method_name, | |
157 const ::c_salt::SharedVariant* params_begin, | |
158 const ::c_salt::SharedVariant* params_end, | |
159 ::c_salt::SharedVariant* return_value_var); | |
160 | |
161 // Support for browser-exposed properties. The browser proxy (which is | |
162 // platform-specific) first calls HasProperty() before getting or setting; | |
163 // the Get or Set is performed only if HasProperty() returns |true|. The | |
164 // brwoser proxy is responsible for all the variant marshaling. | |
165 virtual bool HasScriptProperty(const std::string& name); | |
166 // Set |return_value| to the value associated with property |name|. If | |
167 // property |name| doesn't exist, then set |return_value| to the null type | |
168 // and return |false|. | |
169 virtual bool GetScriptProperty(const std::string& name, | |
170 SharedVariant* return_value) const; | |
171 // If |name| is associated with a static property, return that value. Else, | |
172 // if there is no property associated with |name|, add it as a dynamic | |
173 // property. See property.h for definitions and more details. | |
174 virtual bool SetScriptProperty(const std::string& name, | |
175 const SharedVariant& value); | |
176 // This succeeds only if |name| is associated with a dynamic property. | |
177 virtual bool RemoveScriptProperty(const std::string& name); | |
178 | |
179 // Return the names of all enumerable properties in to the provided vector. | |
180 virtual void GetAllPropertyNames(std::vector<std::string>* prop_names) const; | |
181 | |
182 // This is called by some browser proxies when all references to a proxy | |
183 // object have been deallocated, but the proxy's ref count has not gone to 0. | |
184 // It's kind of an anti-leak clean-up mechanism. | |
185 virtual void Invalidate(); | |
186 | |
187 virtual bool IsNative() const { return true; } | |
188 | |
189 // This is a weak reference. Some kind of smart_ptr would be useful here, | |
190 // but the |browser_binding_| instance is actually a proxy object that is | |
191 // managed by the browser. In addition, this pointer is actually a circular | |
192 // reference to the BrowserBinding object that owns this ScriptingBridge | |
193 // instance. | |
194 npapi::BrowserBinding* browser_binding_; | |
195 // |window_object_| is mutable so that the const accessor can create it | |
196 // lazily. | |
197 // TODO(dspringer): move this into BrowserBinding. | |
198 mutable NPObject* window_object_; | |
199 | |
200 MethodDictionary method_dictionary_; | |
201 PropertyDictionary property_dictionary_; | |
202 // ScriptingBridge owns the native object to ensure it stays alive as long as | |
203 // the browser needs it, and it goes away as soon as all clients are done with | |
204 // it. I.e., ScriptingBridge is ref-counted using the appropriate browser | |
205 // mechanism, and makes sure the target object has the same lifespan. | |
206 SharedScriptableNativeObject native_object_; | |
207 }; | |
208 | |
209 } // namespace c_salt | |
210 | |
211 #endif // C_SALT_SCRIPTING_BRIDGE_H_ | |
OLD | NEW |