1 // Copyright 2007, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef GEARS_BASE_COMMON_JS_TYPES_H__
27 #define GEARS_BASE_COMMON_JS_TYPES_H__
30 #include "gears/base/common/common.h" // for DISALLOW_EVIL_CONSTRUCTORS
31 #include "gears/base/common/string16.h" // for string16
35 #include <gecko_sdk/include/nsCOMPtr.h> // for JsParamFetcher
36 #include <gecko_internal/jsapi.h>
37 #include <gecko_internal/nsIXPConnect.h> // for JsParamFetcher
39 // Abstracted types for values used with JavaScript engines.
40 typedef jsval JsToken
;
41 typedef jsval JsScopedToken
; // unneeded in FF, see comment on JsArray
42 typedef JSContext
* JsContextPtr
;
43 typedef nsresult JsNativeMethodRetval
;
45 // interface required for COM objects exposed in JS
46 typedef nsISupports IScriptable
;
51 // no "base_interface_ie.h" because IE doesn't require a COM base interface
53 // Abstracted types for values used with JavaScript engines.
54 typedef VARIANT JsToken
;
55 typedef CComVariant JsScopedToken
;
56 typedef void* JsContextPtr
; // unused in IE
57 typedef HRESULT JsNativeMethodRetval
;
59 // interface required for COM objects exposed in JS
60 typedef IDispatch IScriptable
;
64 #include <WebKit/npapi.h>
65 #include <WebKit/npfunctions.h>
66 #include <WebKit/npruntime.h>
70 #include "gecko_sdk/include/npapi.h"
71 #include "gecko_sdk/include/npupp.h"
75 #if BROWSER_NPAPI || BROWSER_WEBKIT
76 // Abstracted types for values used with JavaScript engines.
77 typedef NPVariant JsToken
;
78 typedef NPP JsContextPtr
;
79 typedef NPError JsNativeMethodRetval
;
81 // Not used in NPAPI or WEBKIT at the moment
82 typedef void* IScriptable
;
84 #endif // BROWSER_NPAPI || BROWSER_WEBKIT
87 typedef JsRootedToken JsRootedCallback
;
89 // Utility functions to convert JsToken to various primitives.
90 // TODO(aa): Add coercion to these functions (since they include the word "to")
91 // and add new functions to determine what the token really is.
92 bool JsTokenToBool(JsToken t
, JsContextPtr cx
, bool *out
);
93 bool JsTokenToInt(JsToken t
, JsContextPtr cx
, int *out
);
94 bool JsTokenToString(JsToken t
, JsContextPtr cx
, std::string16
*out
);
95 bool JsTokenToDouble(JsToken t
, JsContextPtr cx
, double *out
);
96 bool JsTokenToNewCallback(JsToken t
, JsContextPtr cx
, JsRootedCallback
**out
);
98 // Utility function to check for the JavaScript values null and undefined. We
99 // usually treat these two identically to prevent confusion.
100 bool JsTokenIsNullOrUndefined(JsToken t
);
102 // Utility function to tell if a given token is a JavaScript object. This
103 // function returns true for all JavaScript objects, including things like
104 // functions and Date objects. It returns false for all primitive values
105 // including null and undefined.
106 bool JsTokenIsObject(JsToken t
);
110 // A JsToken that won't get GC'd out from under you.
111 class JsRootedToken
{
113 JsRootedToken(JsContextPtr context
, JsToken token
)
114 : context_(context
), token_(token
) {
115 if (JSVAL_IS_GCTHING(token_
)) {
116 JS_AddRoot(context_
, &token_
);
121 if (JSVAL_IS_GCTHING(token_
)) {
122 JS_RemoveRoot(context_
, &token_
);
126 JsToken
token() const { return token_
; }
127 JsContextPtr
context() const { return context_
; }
129 bool GetAsBool(bool *out
) const {
130 return JsTokenToBool(token_
, context_
, out
);
133 // TODO(aa): GetAsString(), etc. But needs restructuring first. See note below
134 // above IE implementation.
137 JsContextPtr context_
;
139 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
144 // A JsToken that won't get GC'd out from under you.
145 // TODO(aa): This leaks for things like strings and arrays. We need to correctly
146 // handle lifetime. Also need to think of different requirements for when token
147 // is an input parameter vs a return value.
148 class JsRootedToken
{
150 JsRootedToken(JsContextPtr context
, JsToken token
)
151 : token_(token
) { // IE doesn't use JsContextPtr
152 if (token_
.vt
== VT_DISPATCH
) {
153 token_
.pdispVal
->AddRef();
158 if (token_
.vt
== VT_DISPATCH
) {
159 token_
.pdispVal
->Release();
163 JsToken
token() const { return token_
; }
164 JsContextPtr
context() const { return NULL
; }
166 bool GetAsBool(bool *out
) const {
167 return JsTokenToBool(token_
, NULL
, out
);
172 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
175 // Implementations of boilerplate code.
176 // - We don't currently need GetNativeBaseClass on IE.
180 // An NPVariant that takes ownership of its value and releases it when it goes
182 class ScopedNPVariant
: public NPVariant
{
184 ScopedNPVariant() { VOID_TO_NPVARIANT(*this); }
186 explicit ScopedNPVariant(T value
) { VOID_TO_NPVARIANT(*this); Reset(value
); }
188 ~ScopedNPVariant() { Reset(); }
190 // This is necessary for API transparency.
191 ScopedNPVariant
& operator=(const NPVariant
&value
) {
196 // Frees the old value and replaces it with the new value. Strings are
197 // copied, and objects are retained.
199 void Reset(int value
);
200 void Reset(double value
);
201 void Reset(const char *value
);
202 void Reset(const char16
*value
);
203 void Reset(NPObject
*value
);
204 void Reset(const NPVariant
&value
);
206 // Gives up ownership of this variant, without freeing or releasing the
207 // underyling object. The variant will be VOID after this call.
211 typedef ScopedNPVariant JsScopedToken
;
213 // A JsToken that won't get GC'd out from under you.
214 class JsRootedToken
{
216 JsRootedToken(JsContextPtr context
, JsToken token
)
217 : context_(context
), token_(token
) { }
219 const JsToken
& token() const { return token_
; }
220 JsContextPtr
context() const { return context_
; }
222 bool GetAsBool(bool *out
) const {
223 return JsTokenToBool(token_
, context_
, out
);
227 JsContextPtr context_
; // TODO(mpcomplete): figure out if this is necessary
228 JsScopedToken token_
;
229 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
234 // Just placeholder values for Safari since the created workers use a separate
235 // process for JS execution.
236 typedef void JsToken
;
237 typedef void JsScopedToken
;
238 typedef void* JsContextPtr
;
239 typedef void JsNativeMethodRetval
;
241 #endif // BROWSER_xyz
243 // JsArray and JsObject make use of a JsScopedToken, which is a token that
244 // releases any references it has when it goes out of scope. This is necessary
245 // in IE and NPAPI, because getting an array element or object property
246 // increases the reference count, and we need a way to release that reference
247 // *after* we're done using the object. In Firefox, JsToken == JsScopedToken
248 // because Firefox only gives us a weak pointer to the value.
251 struct JsParamToSend
;
252 class ModuleImplBaseClass
;
259 bool SetArray(JsToken value
, JsContextPtr context
);
261 bool GetLength(int *length
) const;
263 // use the same syntax as JsRootedToken
264 const JsScopedToken
& token() const;
266 bool GetElement(int index
, JsScopedToken
*out
) const;
267 bool GetElementAsBool(int index
, bool *out
) const;
268 bool GetElementAsInt(int index
, int *out
) const;
269 bool GetElementAsDouble(int index
, double *out
) const;
270 bool GetElementAsString(int index
, std::string16
*out
) const;
271 bool GetElementAsArray(int index
, JsArray
*out
) const;
272 bool GetElementAsObject(int index
, JsObject
*out
) const;
273 bool GetElementAsFunction(int index
, JsRootedCallback
**out
) const;
275 bool SetElement(int index
, const JsScopedToken
& value
);
276 bool SetElementBool(int index
, bool value
);
277 bool SetElementInt(int index
, int value
);
278 bool SetElementDouble(int index
, double value
);
279 bool SetElementString(int index
, const std::string16
& value
);
280 bool SetElementArray(int index
, JsArray
* value
);
281 bool SetElementObject(int index
, JsObject
* value
);
282 bool SetElementFunction(int index
, JsRootedCallback
* value
);
283 bool SetElementModule(int index
, IScriptable
* value
);
286 // Needs access to the raw JsToken.
287 friend void ConvertJsParamToToken(const JsParamToSend
¶m
,
288 JsContextPtr context
,
289 JsScopedToken
*token
);
290 JsContextPtr js_context_
;
291 JsScopedToken array_
;
298 bool GetProperty(const std::string16
&name
, JsScopedToken
*value
) const;
299 bool SetObject(JsToken value
, JsContextPtr context
);
300 bool GetPropertyAsBool(const std::string16
&name
, bool *out
) const;
301 bool GetPropertyAsInt(const std::string16
&name
, int *out
) const;
302 bool GetPropertyAsDouble(const std::string16
&name
, double *out
) const;
303 bool GetPropertyAsString(const std::string16
&name
, std::string16
*out
) const;
304 bool GetPropertyAsArray(const std::string16
&name
, JsArray
*out
) const;
305 bool GetPropertyAsObject(const std::string16
&name
, JsObject
*out
) const;
306 bool GetPropertyAsFunction(const std::string16
&name
,
307 JsRootedCallback
**out
) const;
309 // SetProperty*() overwrites the existing named property or adds a new one if
311 bool SetPropertyBool(const std::string16
& name
, bool value
);
312 bool SetPropertyInt(const std::string16
&name
, int value
);
313 bool SetPropertyDouble(const std::string16
& name
, double value
);
314 bool SetPropertyString(const std::string16
&name
, const std::string16
&value
);
315 bool SetPropertyArray(const std::string16
& name
, JsArray
* value
);
316 bool SetPropertyObject(const std::string16
& name
, JsObject
* value
);
317 bool SetPropertyFunction(const std::string16
& name
, JsRootedCallback
* value
);
318 bool SetPropertyModule(const std::string16
& name
, IScriptable
* value
);
321 // Need access to the raw JsToken.
322 friend class JsRunnerBase
;
323 friend class JsArray
;
324 friend void ConvertJsParamToToken(const JsParamToSend
¶m
,
325 JsContextPtr context
,
326 JsScopedToken
*token
);
327 friend JsNativeMethodRetval
JsSetException(const ModuleImplBaseClass
*obj
,
328 const char16
*message
);
330 bool SetProperty(const std::string16
&name
, const JsToken
&value
);
332 JsContextPtr js_context_
;
333 JsScopedToken js_object_
;
336 // The JsParam* types define values for sending and receiving JS parameters.
339 JSPARAM_INT
, // TODO(mpcomplete): deprecate in favor of double?
349 enum JsParamRequirement
{
354 struct JsParamToSend
{
356 const void *value_ptr
;
359 struct JsParamToRecv
{
365 JsParamRequirement requirement
;
371 class ModuleImplBaseClass
;
373 // This class provides an interface for a property or method access on a native
374 // object from JavaScript. It allows consumers to retrieve what arguments were
375 // passed in, and return a value or exception back to the caller. Any native
376 // property or method handler should take an instance of this object as a
378 class JsCallContext
{
380 // Only browser-specific wrapper code should need to instantiate this object.
382 JsCallContext(JsContextPtr js_context
, NPObject
*object
,
383 int argc
, const JsToken
*argv
, JsToken
*retval
)
384 : js_context_(js_context
), object_(object
),
385 argc_(argc
), argv_(argv
), retval_(retval
),
386 is_exception_set_(false) {}
388 JsCallContext(DISPPARAMS FAR
*disp_params
, VARIANT FAR
*retval
,
389 EXCEPINFO FAR
*excep_info
)
390 : disp_params_(disp_params
), retval_(retval
), exception_info_(excep_info
),
391 is_exception_set_(false) {}
393 explicit JsCallContext(ModuleImplBaseClass
* obj
);
398 // Get the arguments a JavaScript caller has passed into a scriptable method
399 // of a native object. Returns the number of arguments successfully read
400 // (will bail at the first invalid argument).
401 int GetArguments(int argc
, JsArgument
*argv
);
403 // Sets the value to be returned to the calling JavaScript.
405 // The ModuleImplBaseClass* version should only be used when returning a
406 // JSPARAM_MODULE. It exists because passing a derived class through a void*
407 // and then casting to the base class is not safe - the compiler won't be able
408 // to correctly adjust the pointer offset.
410 // The int version is for use with JSPARAM_NULL, to avoid conflicting with the
411 // ModuleImplBaseClass version (works because NULL is defined as 0).
412 void SetReturnValue(JsParamType type
, const void *value_ptr
);
413 void SetReturnValue(JsParamType type
, const ModuleImplBaseClass
*value_ptr
) {
414 assert(type
== JSPARAM_MODULE
);
415 SetReturnValue(type
, reinterpret_cast<const void*>(value_ptr
));
417 void SetReturnValue(JsParamType type
, int) {
418 assert(type
== JSPARAM_NULL
);
419 SetReturnValue(type
, reinterpret_cast<const void*>(NULL
));
422 // Sets an exception to be thrown to the calling JavaScript. Setting an
423 // exception overrides any previous exception and any return values.
424 void SetException(const std::string16
&message
);
426 JsContextPtr
js_context() { return js_context_
; }
427 bool is_exception_set() { return is_exception_set_
; }
430 JsContextPtr js_context_
;
431 bool is_exception_set_
;
435 const JsToken
*argv_
;
438 DISPPARAMS FAR
*disp_params_
;
439 VARIANT FAR
*retval_
;
440 EXCEPINFO FAR
*exception_info_
;
444 nsCOMPtr
<nsIXPConnect
> xpc_
;
445 nsCOMPtr
<nsIXPCNativeCallContext
> ncc_
;
446 ModuleImplBaseClass
* obj_
;
453 // Given a JsParamToSend, extract it into a JsScopedToken. Resulting token
454 // increases the reference count for objects.
455 void ConvertJsParamToToken(const JsParamToSend
¶m
,
456 JsContextPtr context
, JsScopedToken
*token
);
458 //-----------------------------------------------------------------------------
459 #if BROWSER_FF // the rest of this file only applies to Firefox, for now
461 // Helper class to extract JavaScript parameters (including optional params
462 // and varargs), in a way that hides differences between main-thread and
463 // worker-thread environments.
464 class JsParamFetcher
{
466 explicit JsParamFetcher(ModuleImplBaseClass
*obj
);
468 JsContextPtr
GetContextPtr() { return js_context_
; }
469 int GetCount(bool has_mysterious_retval
) {
470 return has_mysterious_retval
? js_argc_
- 1 : js_argc_
;
472 // In Firefox, set has_string_retval iff method has a string return value.
473 bool IsOptionalParamPresent(int i
, bool has_string_retval
);
475 // All functions check the type of the requested value, and they will return
476 // false on a mismatch.
477 bool GetAsInt(int i
, int *out
);
478 bool GetAsString(int i
, std::string16
*out
);
479 bool GetAsArray(int i
, JsArray
*out
);
480 bool GetAsObject(int i
, JsObject
*out
);
481 bool GetAsNewRootedCallback(int i
, JsRootedCallback
**out
);
484 JsContextPtr js_context_
;
489 nsCOMPtr
<nsIXPConnect
> xpc_
;
490 nsCOMPtr
<nsIXPCNativeCallContext
> ncc_
;
496 // Sets JavaScript exceptions, in a way that hides differences
497 // between main-thread and worker-thread environments.
498 // Returns the value the caller should return to the JavaScript host engine.
499 JsNativeMethodRetval
JsSetException(const ModuleImplBaseClass
*obj
,
500 const char16
*message
);
502 // Garbage collection helper functions
503 bool RootJsToken(JsContextPtr cx
, JsToken t
);
507 //-----------------------------------------------------------------------------
510 #endif // GEARS_BASE_COMMON_JS_TYPES_H__