1 | /* This file is part of the KDE project |
2 | Copyright (C) 2010 Maksim Orlovich <maksim@kde.org> |
3 | Copyright (C) 2002 Koos Vriezen <koos.vriezen@gmail.com> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #ifndef kparts_scriptableextension_h |
22 | #define kparts_scriptableextension_h |
23 | |
24 | #include <QtGlobal> |
25 | #include <QObject> |
26 | #include <QVariant> |
27 | #include <kparts/part.h> |
28 | |
29 | namespace KParts { |
30 | |
31 | class ScriptableExtension; |
32 | struct ScriptableExtensionPrivate; |
33 | class LiveConnectExtension; |
34 | |
35 | /** |
36 | * An extension class that permits KParts to be scripted (such as when embedded |
37 | * inside a KHTMLPart) and to access the host's scriptable objects as well. |
38 | * |
39 | * See @ref ScriptValueTypes for how values are passed to/from various methods here. |
40 | * |
41 | * @since 4.5 |
42 | * \nosubgrouping |
43 | */ |
44 | class KPARTS_EXPORT ScriptableExtension: public QObject |
45 | { |
46 | Q_OBJECT |
47 | public: |
48 | /** @defgroup ScriptValueTypes Script Value Types |
49 | * @{ |
50 | * Values are passed to and from scriptable methods or properties as QVariants. |
51 | * Valid values may be bools, strings, and numbers (doubles), as well as the |
52 | * following custom types: |
53 | * \li @ref Null |
54 | * \li @ref Undefined |
55 | * \li @ref Exception |
56 | * \li @ref Object |
57 | * \li @ref FunctionRef |
58 | */ |
59 | |
60 | /// Corresponds to 'null' in JavaScript |
61 | struct Null {}; |
62 | |
63 | /// Corresponds to 'undefined' in JavaScript |
64 | struct Undefined {}; |
65 | |
66 | /// Returned from operations to denote a failure. May not be passed in as |
67 | /// a parameter, only returned |
68 | struct Exception { |
69 | /// Error message returned from the callee. This should be assumed to be |
70 | /// low-level (in particular, it might not be translated) and should |
71 | /// only be displayed in low-level debugging tools and the like. |
72 | QString message; |
73 | |
74 | Exception() {} |
75 | Exception(const QString& msg): message(msg) {} |
76 | }; |
77 | |
78 | /// Objects are abstracted away as a pair of the ScriptableExtension |
79 | /// the performs operations on it, and an implementation-specific Id, |
80 | /// which gets passed to the extension's methods. |
81 | /// |
82 | /// Objects are reference-counted, with the following protocol: |
83 | /// 1) Return values from methods, rootObject(), enclosingObject(), |
84 | /// and get() are already acquired by the producer, so the consumer |
85 | /// should release them when done. |
86 | /// 2) During a call, the caller guarantees that all the arguments |
87 | /// will be live for the calls duration, but the callee must |
88 | /// acquire them if it stores it for longer than that. |
89 | /// |
90 | /// @see acquire, acquireValue, release, releaseValue |
91 | struct Object { |
92 | ScriptableExtension* owner; |
93 | quint64 objId; |
94 | |
95 | Object(): owner(0), objId(0) {} |
96 | Object(ScriptableExtension* o, quint64 id): owner(o), objId(id) {} |
97 | bool operator==(const Object& other) const { return owner == other.owner && objId == other.objId; } |
98 | }; |
99 | |
100 | /// Function references are a pair of an object and a field in it. |
101 | /// Essentially, if you have a base.field(something) call, the |
102 | /// 'base' needs to be passed as the 'this' to the function, and |
103 | /// these references can be used to resolve that. |
104 | struct FunctionRef { |
105 | Object base; |
106 | QString field; |
107 | |
108 | FunctionRef() {} |
109 | FunctionRef(const Object& b, const QString&f): base(b), field(f) {} |
110 | bool operator==(const FunctionRef& other) const { return base == other.base && field == other.field; } |
111 | }; |
112 | |
113 | //@} |
114 | |
115 | |
116 | ///@name lifetime |
117 | //@{ |
118 | protected: |
119 | ScriptableExtension(QObject* parent); |
120 | public: |
121 | virtual ~ScriptableExtension(); |
122 | |
123 | /** |
124 | * Queries @p obj for a child object which inherits from this |
125 | * ScriptableExtension class. Convenience method. |
126 | */ |
127 | static ScriptableExtension* childObject(QObject* obj); |
128 | |
129 | /** |
130 | * This returns a bridge object that permits KParts implementing the older |
131 | * LiveConnectExtension to be used via the ScriptableExtension API. |
132 | * The bridge's parent will be the @p parentObj. |
133 | */ |
134 | static ScriptableExtension* adapterFromLiveConnect(QObject* parentObj, |
135 | LiveConnectExtension* oldApi); |
136 | |
137 | //@} |
138 | |
139 | |
140 | ///@name Object Hierarchy |
141 | //@{ |
142 | |
143 | /** |
144 | * Reports the hosting ScriptableExtension to a child. It's the responsibility |
145 | * of a parent part to call this method on all of its kids' ScriptableExtensions |
146 | * as soon as possible. |
147 | */ |
148 | void setHost(ScriptableExtension* host); |
149 | |
150 | /** |
151 | * Returns any registered parent scripting context. May be 0 if setHost |
152 | * was not called (or not call yet). |
153 | */ |
154 | ScriptableExtension* host() const; |
155 | |
156 | /** |
157 | * Return the root scriptable object of this KPart. |
158 | * For example for an HTML part, it would represent a Window object. |
159 | * May be undefined or null |
160 | */ |
161 | virtual QVariant rootObject(); |
162 | |
163 | /** |
164 | * Returns an object that represents the host()'s view of us. |
165 | * For example, if the host is an HTML part, it would return |
166 | * a DOM node of an <object> handled by this part. |
167 | * May be undefined or null |
168 | * |
169 | * Implemented in terms of objectForKid |
170 | * |
171 | */ |
172 | QVariant enclosingObject(); |
173 | //@} |
174 | |
175 | ///@name Object Operations |
176 | /// All these methods share the following conventions: |
177 | /// \li Values are passed and returned encoded as defined in |
178 | /// @ref ScriptValueTypes |
179 | /// \li All methods may return an exception if unsupported |
180 | /// \li All callers \b must provide an accurate callerPrincipal |
181 | /// argument describing which ScriptableExtension (and hence which KPart) |
182 | /// they're acting as. This is used to implement <b>security checks</b>. This |
183 | /// is \b not the same as the owner of an object. For example, if a plugin is |
184 | /// calling an operation on a KHTMLPart object, |
185 | /// then the 'this' parameter would be the object owner, a ScriptableExtension |
186 | /// provided by the KHTMLPart, while the callerPrincipal would be the |
187 | /// ScriptableExtension of the \em plugin. The extension is expected |
188 | /// to do appropriate cross-site scripting checks on this argument |
189 | /// if it is acting as a host. |
190 | //@{ |
191 | |
192 | typedef QList<QVariant> ArgList; |
193 | |
194 | /** |
195 | Try to use the object @p objId associated with 'this' as a function. |
196 | */ |
197 | virtual QVariant callAsFunction(ScriptableExtension* callerPrincipal, quint64 objId, const ArgList& args); |
198 | |
199 | /** |
200 | Try to use a function reference to field @p f of object @objId as a function |
201 | */ |
202 | virtual QVariant callFunctionReference(ScriptableExtension* callerPrincipal, quint64 objId, |
203 | const QString& f, const ArgList& args); |
204 | |
205 | /** |
206 | Try to use the object @p objId associated with 'this' as a constructor |
207 | (corresponding to ECMAScript's new foo(bar, baz, glarch) expression). |
208 | */ |
209 | virtual QVariant callAsConstructor(ScriptableExtension* callerPrincipal, quint64 objId, const ArgList& args); |
210 | |
211 | /** |
212 | Returns true if the object @p objId associated with 'this' has the property |
213 | @p propName. |
214 | */ |
215 | virtual bool hasProperty(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName); |
216 | |
217 | /** |
218 | Tries to get field @p propName from object @p objId associated with 'this'. |
219 | */ |
220 | virtual QVariant get(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName); |
221 | |
222 | /** |
223 | Tries to set the field @p propName from object @p objId associated with 'this' |
224 | to @p value. Returns true on success |
225 | */ |
226 | virtual bool put(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value); |
227 | |
228 | /** |
229 | Tries to remove the field d @p propName from object @p objId associated with 'this'. |
230 | Returns true on success |
231 | */ |
232 | virtual bool removeProperty(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName); |
233 | |
234 | /** |
235 | Tries to enumerate all fields of object @p objId associated with this to |
236 | @p result. Returns true on success |
237 | */ |
238 | virtual bool enumerateProperties(ScriptableExtension* callerPrincipal, quint64 objId, QStringList* result); |
239 | |
240 | /** |
241 | Tries to raise an exception with given message in this extension's scripting |
242 | context. Returns true on success |
243 | */ |
244 | virtual bool setException(ScriptableExtension* callerPrincipal, const QString& message); |
245 | |
246 | |
247 | enum ScriptLanguage { |
248 | ECMAScript, /// < also known as JavaScript |
249 | EnumLimit = 0xFFFF |
250 | }; |
251 | |
252 | /** |
253 | Tries to evaluate a script @p code with the given object as its context. |
254 | The parameter @p language specifies the language to execute it as. |
255 | Use isScriptLanguageSupported to check for support. |
256 | */ |
257 | virtual QVariant evaluateScript(ScriptableExtension* callerPrincipal, |
258 | quint64 contextObjectId, |
259 | const QString& code, |
260 | ScriptLanguage language = ECMAScript); |
261 | |
262 | /** returns true if this extension can execute scripts in the given |
263 | language */ |
264 | virtual bool isScriptLanguageSupported(ScriptLanguage lang) const; |
265 | |
266 | /** |
267 | increases reference count of object @p objId |
268 | */ |
269 | virtual void acquire(quint64 objid); |
270 | |
271 | /** |
272 | Helper that calls @ref acquire on any object or function reference base |
273 | stored in @p v. |
274 | |
275 | @return a copy of the passed in value |
276 | */ |
277 | static QVariant acquireValue(const QVariant& v); |
278 | |
279 | /** |
280 | decreases reference count of object @p objId |
281 | */ |
282 | virtual void release(quint64 objid); |
283 | |
284 | /** |
285 | Helper that calls @ref release on any object or function reference base |
286 | stored in @p v. |
287 | |
288 | @return a copy of the passed in value |
289 | */ |
290 | static QVariant releaseValue(const QVariant& v); |
291 | |
292 | //@} |
293 | private: |
294 | /** |
295 | * If this extension is a host that provides an object corresponding |
296 | * to each kid, override this method to provide it. |
297 | * @see enclosingObject |
298 | */ |
299 | virtual QVariant encloserForKid(KParts::ScriptableExtension* kid); |
300 | |
301 | ScriptableExtensionPrivate* const d; |
302 | }; |
303 | |
304 | KPARTS_EXPORT unsigned int qHash(const KParts::ScriptableExtension::Object& o); |
305 | |
306 | KPARTS_EXPORT unsigned int qHash(const KParts::ScriptableExtension::FunctionRef& f); |
307 | |
308 | } // namespace KParts |
309 | |
310 | Q_DECLARE_METATYPE(KParts::ScriptableExtension::Null) |
311 | Q_DECLARE_METATYPE(KParts::ScriptableExtension::Undefined) |
312 | Q_DECLARE_METATYPE(KParts::ScriptableExtension::Exception) |
313 | Q_DECLARE_METATYPE(KParts::ScriptableExtension::Object) |
314 | Q_DECLARE_METATYPE(KParts::ScriptableExtension::FunctionRef) |
315 | |
316 | #endif |
317 | |
318 | // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; |
319 | |