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 class JsContextWrapper
;
41 // Abstracted types for values used with JavaScript engines.
42 typedef jsval JsToken
;
43 typedef jsval JsScopedToken
; // unneeded in FF, see comment on JsArray
44 typedef JSContext
* JsContextPtr
;
45 typedef JsContextWrapper
* JsContextWrapperPtr
;
46 typedef nsresult JsNativeMethodRetval
;
48 // interface required for COM objects exposed in JS
49 typedef nsISupports IScriptable
;
54 // no "base_interface_ie.h" because IE doesn't require a COM base interface
56 // Abstracted types for values used with JavaScript engines.
57 typedef VARIANT JsToken
;
58 typedef CComVariant JsScopedToken
;
59 typedef void* JsContextPtr
; // unused in IE
60 typedef void* JsContextWrapperPtr
; // unused in IE
61 typedef HRESULT JsNativeMethodRetval
;
63 // interface required for COM objects exposed in JS
64 typedef IDispatch IScriptable
;
68 #include <WebKit/npapi.h>
69 #include <WebKit/npfunctions.h>
70 #include <WebKit/npruntime.h>
74 #include "gecko_sdk/include/npapi.h"
75 #include "gecko_sdk/include/npupp.h"
79 #if BROWSER_NPAPI || BROWSER_WEBKIT
80 // Abstracted types for values used with JavaScript engines.
81 typedef NPVariant JsToken
;
82 typedef NPP JsContextPtr
;
83 typedef void* JsContextWrapperPtr
; // unused in NPAPI
84 typedef NPError JsNativeMethodRetval
;
86 // Not used in NPAPI or WEBKIT at the moment
87 typedef void* IScriptable
;
89 #endif // BROWSER_NPAPI || BROWSER_WEBKIT
92 typedef JsRootedToken JsRootedCallback
;
94 // The JsParam* types define values for sending and receiving JS parameters.
109 enum JsParamRequirement
{
114 struct JsParamToSend
{
116 const void *value_ptr
;
119 struct JsParamToRecv
{
125 JsParamRequirement requirement
;
130 // Utility functions to convert JsToken to various primitives. These
131 // functions will try to coerce the JsToken to the required type. null or
132 // undefined are never coerced and these functions will return false in
134 // TODO(oshlack): implement coercion for NPAPI.
135 bool JsTokenToBool(JsToken t
, JsContextPtr cx
, bool *out
);
136 bool JsTokenToInt(JsToken t
, JsContextPtr cx
, int *out
);
137 bool JsTokenToString(JsToken t
, JsContextPtr cx
, std::string16
*out
);
138 bool JsTokenToDouble(JsToken t
, JsContextPtr cx
, double *out
);
139 bool JsTokenToNewCallback(JsToken t
, JsContextPtr cx
, JsRootedCallback
**out
);
141 // Utility function to determine the type of a JsToken.
142 JsParamType
JsTokenGetType(JsToken t
, JsContextPtr cx
);
144 // Utility function to tell if a given token is a JavaScript function.
145 bool JsTokenIsCallback(JsToken t
, JsContextPtr cx
);
147 // Utility function to tell if a given token is a JavaScript array.
148 bool JsTokenIsArray(JsToken t
, JsContextPtr cx
);
150 // Utility function to tell if a given token is a JavaScript object. This
151 // function returns true for all JavaScript objects, including things like
152 // functions and Date objects. It returns false for all primitive values
153 // including null and undefined.
154 bool JsTokenIsObject(JsToken t
);
156 // Utility function to check for the JavaScript values null and undefined. We
157 // usually treat these two identically to prevent confusion.
158 bool JsTokenIsNullOrUndefined(JsToken t
);
162 // A JsToken that won't get GC'd out from under you.
163 class JsRootedToken
{
165 JsRootedToken(JsContextPtr context
, JsToken token
)
166 : context_(context
), token_(token
) {
167 if (JSVAL_IS_GCTHING(token_
)) {
168 JS_AddRoot(context_
, &token_
);
173 if (JSVAL_IS_GCTHING(token_
)) {
174 JS_RemoveRoot(context_
, &token_
);
178 JsToken
token() const { return token_
; }
179 JsContextPtr
context() const { return context_
; }
181 bool GetAsBool(bool *out
) const {
182 return JsTokenToBool(token_
, context_
, out
);
185 // TODO(aa): GetAsString(), etc. But needs restructuring first. See note below
186 // above IE implementation.
189 JsContextPtr context_
;
191 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
196 // A JsToken that won't get GC'd out from under you.
197 // TODO(aa): This leaks for things like strings and arrays. We need to correctly
198 // handle lifetime. Also need to think of different requirements for when token
199 // is an input parameter vs a return value.
200 class JsRootedToken
{
202 JsRootedToken(JsContextPtr context
, JsToken token
)
203 : token_(token
) { // IE doesn't use JsContextPtr
204 if (token_
.vt
== VT_DISPATCH
) {
205 token_
.pdispVal
->AddRef();
210 if (token_
.vt
== VT_DISPATCH
) {
211 token_
.pdispVal
->Release();
215 JsToken
token() const { return token_
; }
216 JsContextPtr
context() const { return NULL
; }
218 bool GetAsBool(bool *out
) const {
219 return JsTokenToBool(token_
, NULL
, out
);
224 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
227 // Implementations of boilerplate code.
228 // - We don't currently need GetNativeBaseClass on IE.
232 // An NPVariant that takes ownership of its value and releases it when it goes
234 class ScopedNPVariant
: public NPVariant
{
236 ScopedNPVariant() { VOID_TO_NPVARIANT(*this); }
238 explicit ScopedNPVariant(T value
) { VOID_TO_NPVARIANT(*this); Reset(value
); }
240 ~ScopedNPVariant() { Reset(); }
242 // This is necessary for API transparency.
243 ScopedNPVariant
& operator=(const NPVariant
&value
) {
248 // Frees the old value and replaces it with the new value. Strings are
249 // copied, and objects are retained.
251 void Reset(int value
);
252 void Reset(double value
);
253 void Reset(const char *value
);
254 void Reset(const char16
*value
);
255 void Reset(NPObject
*value
);
256 void Reset(const NPVariant
&value
);
258 // Gives up ownership of this variant, without freeing or releasing the
259 // underyling object. The variant will be VOID after this call.
263 typedef ScopedNPVariant JsScopedToken
;
265 // A JsToken that won't get GC'd out from under you.
266 class JsRootedToken
{
268 JsRootedToken(JsContextPtr context
, JsToken token
)
269 : context_(context
), token_(token
) { }
271 const JsToken
& token() const { return token_
; }
272 JsContextPtr
context() const { return context_
; }
274 bool GetAsBool(bool *out
) const {
275 return JsTokenToBool(token_
, context_
, out
);
279 JsContextPtr context_
; // TODO(mpcomplete): figure out if this is necessary
280 JsScopedToken token_
;
281 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken
);
286 // Just placeholder values for Safari since the created workers use a separate
287 // process for JS execution.
288 typedef void JsToken
;
289 typedef void JsScopedToken
;
290 typedef void* JsContextPtr
;
291 typedef void JsNativeMethodRetval
;
293 #endif // BROWSER_xyz
295 // JsArray and JsObject make use of a JsScopedToken, which is a token that
296 // releases any references it has when it goes out of scope. This is necessary
297 // in IE and NPAPI, because getting an array element or object property
298 // increases the reference count, and we need a way to release that reference
299 // *after* we're done using the object. In Firefox, JsToken == JsScopedToken
300 // because Firefox only gives us a weak pointer to the value.
303 struct JsParamToSend
;
304 class JsRunnerInterface
;
305 class ModuleImplBaseClass
;
312 bool SetArray(JsToken value
, JsContextPtr context
);
314 bool GetLength(int *length
) const;
316 // use the same syntax as JsRootedToken
317 const JsScopedToken
&token() const { return array_
; }
318 const JsContextPtr
&context() const { return js_context_
; }
321 bool GetElement(int index
, JsScopedToken
*out
) const;
323 // These functions coerce values using the JsTokenTo*() functions.
324 bool GetElementAsBool(int index
, bool *out
) const;
325 bool GetElementAsInt(int index
, int *out
) const;
326 bool GetElementAsDouble(int index
, double *out
) const;
327 bool GetElementAsString(int index
, std::string16
*out
) const;
328 bool GetElementAsArray(int index
, JsArray
*out
) const;
329 bool GetElementAsObject(int index
, JsObject
*out
) const;
330 bool GetElementAsFunction(int index
, JsRootedCallback
**out
) const;
332 // Method to get the type of an element
333 JsParamType
GetElementType(int index
) const;
335 bool SetElement(int index
, const JsScopedToken
& value
);
336 bool SetElementBool(int index
, bool value
);
337 bool SetElementInt(int index
, int value
);
338 bool SetElementDouble(int index
, double value
);
339 bool SetElementString(int index
, const std::string16
& value
);
340 bool SetElementArray(int index
, JsArray
* value
);
341 bool SetElementObject(int index
, JsObject
* value
);
342 bool SetElementFunction(int index
, JsRootedCallback
* value
);
343 bool SetElementModule(int index
, IScriptable
* value
);
346 JsContextPtr js_context_
;
347 JsScopedToken array_
;
354 bool GetProperty(const std::string16
&name
, JsScopedToken
*value
) const;
355 bool SetObject(JsToken value
, JsContextPtr context
);
357 // These functions coerce values using the JsTokenTo*() functions.
358 bool GetPropertyAsBool(const std::string16
&name
, bool *out
) const;
359 bool GetPropertyAsInt(const std::string16
&name
, int *out
) const;
360 bool GetPropertyAsDouble(const std::string16
&name
, double *out
) const;
361 bool GetPropertyAsString(const std::string16
&name
, std::string16
*out
) const;
362 bool GetPropertyAsArray(const std::string16
&name
, JsArray
*out
) const;
363 bool GetPropertyAsObject(const std::string16
&name
, JsObject
*out
) const;
364 bool GetPropertyAsFunction(const std::string16
&name
,
365 JsRootedCallback
**out
) const;
367 // Method to get the type of a property
368 JsParamType
GetPropertyType(const std::string16
&name
) const;
370 // SetProperty*() overwrites the existing named property or adds a new one if
372 bool SetPropertyBool(const std::string16
& name
, bool value
);
373 bool SetPropertyInt(const std::string16
&name
, int value
);
374 bool SetPropertyDouble(const std::string16
& name
, double value
);
375 bool SetPropertyString(const std::string16
&name
, const std::string16
&value
);
376 bool SetPropertyArray(const std::string16
& name
, JsArray
* value
);
377 bool SetPropertyObject(const std::string16
& name
, JsObject
* value
);
378 bool SetPropertyFunction(const std::string16
& name
, JsRootedCallback
* value
);
379 bool SetPropertyModule(const std::string16
& name
, IScriptable
* value
);
381 const JsScopedToken
&token() const { return js_object_
; }
382 const JsContextPtr
&context() const { return js_context_
; }
385 bool SetProperty(const std::string16
&name
, const JsToken
&value
);
387 JsContextPtr js_context_
;
388 JsScopedToken js_object_
;
391 class ModuleImplBaseClass
;
392 class JsRunnerInterface
;
394 // This class provides an interface for a property or method access on a native
395 // object from JavaScript. It allows consumers to retrieve what arguments were
396 // passed in, and return a value or exception back to the caller. Any native
397 // property or method handler should take an instance of this object as a
399 class JsCallContext
{
401 // Only browser-specific wrapper code should need to instantiate this object.
403 JsCallContext(JsContextPtr js_context
, NPObject
*object
,
404 int argc
, const JsToken
*argv
, JsToken
*retval
)
405 : js_context_(js_context
), object_(object
),
406 argc_(argc
), argv_(argv
), retval_(retval
),
407 is_exception_set_(false) {}
409 JsCallContext(DISPPARAMS FAR
*disp_params
, VARIANT FAR
*retval
,
410 EXCEPINFO FAR
*excep_info
)
411 : disp_params_(disp_params
), retval_(retval
), exception_info_(excep_info
),
412 is_exception_set_(false) {}
414 JsCallContext(JsContextPtr cx
, JsRunnerInterface
*js_runner
,
415 int argc
, JsToken
*argv
, JsToken
*retval
);
420 // Get the arguments a JavaScript caller has passed into a scriptable method
421 // of a native object. Returns the number of arguments successfully read
422 // (will bail at the first invalid argument).
423 int GetArguments(int argc
, JsArgument
*argv
);
425 // Get the type of an argument that was passed in.
426 JsParamType
GetArgumentType(int i
);
428 // Sets the value to be returned to the calling JavaScript.
430 // The ModuleImplBaseClass* version should only be used when returning a
431 // JSPARAM_MODULE. It exists because passing a derived class through a void*
432 // and then casting to the base class is not safe - the compiler won't be able
433 // to correctly adjust the pointer offset.
435 // The int version is for use with JSPARAM_NULL, to avoid conflicting with the
436 // ModuleImplBaseClass version (works because NULL is defined as 0).
437 void SetReturnValue(JsParamType type
, const void *value_ptr
);
438 void SetReturnValue(JsParamType type
, const ModuleImplBaseClass
*value_ptr
) {
439 assert(type
== JSPARAM_MODULE
);
440 SetReturnValue(type
, reinterpret_cast<const void*>(value_ptr
));
442 void SetReturnValue(JsParamType type
, int) {
443 assert(type
== JSPARAM_NULL
);
444 SetReturnValue(type
, reinterpret_cast<const void*>(NULL
));
447 // Sets an exception to be thrown to the calling JavaScript. Setting an
448 // exception overrides any previous exception and any return values.
449 void SetException(const std::string16
&message
);
451 JsContextPtr
js_context() { return js_context_
; }
452 bool is_exception_set() { return is_exception_set_
; }
455 JsContextPtr js_context_
;
456 bool is_exception_set_
;
460 const JsToken
*argv_
;
463 DISPPARAMS FAR
*disp_params_
;
464 VARIANT FAR
*retval_
;
465 EXCEPINFO FAR
*exception_info_
;
470 JsRunnerInterface
*js_runner_
;
471 nsCOMPtr
<nsIXPConnect
> xpc_
;
472 nsCOMPtr
<nsIXPCNativeCallContext
> ncc_
;
479 // Given a JsParamToSend, extract it into a JsScopedToken. Resulting token
480 // increases the reference count for objects.
481 void ConvertJsParamToToken(const JsParamToSend
¶m
,
482 JsContextPtr context
, JsScopedToken
*token
);
484 //-----------------------------------------------------------------------------
485 #if BROWSER_FF // the rest of this file only applies to Firefox, for now
487 // Helper class to extract JavaScript parameters (including optional params
488 // and varargs), in a way that hides differences between main-thread and
489 // worker-thread environments.
490 class JsParamFetcher
{
492 explicit JsParamFetcher(ModuleImplBaseClass
*obj
);
494 JsContextPtr
GetContextPtr() { return js_context_
; }
495 int GetCount(bool has_mysterious_retval
) {
496 return has_mysterious_retval
? js_argc_
- 1 : js_argc_
;
498 // In Firefox, set has_string_retval iff method has a string return value.
499 bool IsOptionalParamPresent(int i
, bool has_string_retval
);
501 // These functions coerce values using the JsTokenTo*() functions.
502 bool GetAsInt(int i
, int *out
);
503 bool GetAsString(int i
, std::string16
*out
);
504 bool GetAsBool(int i
, bool *out
);
505 bool GetAsDouble(int i
, double *out
);
506 bool GetAsArray(int i
, JsArray
*out
);
507 bool GetAsObject(int i
, JsObject
*out
);
509 // TODO(kevinww): Currently doesn't work in a worker thread because it uses
511 bool GetAsModule(int i
, nsISupports
**out
);
513 bool GetAsNewRootedCallback(int i
, JsRootedCallback
**out
);
515 // Method to get the type of a parameter
516 JsParamType
GetType(int i
);
518 void SetReturnValue(JsToken retval
);
521 JsContextPtr js_context_
;
526 nsCOMPtr
<nsIXPConnect
> xpc_
;
527 nsCOMPtr
<nsIXPCNativeCallContext
> ncc_
;
531 // Sets JavaScript exceptions, in a way that hides differences
532 // between main-thread and worker-thread environments.
533 // Returns the value the caller should return to the JavaScript host engine.
534 JsNativeMethodRetval
JsSetException(JsContextPtr cx
,
535 JsRunnerInterface
*js_runner
,
536 const char16
*message
,
537 bool notify_native_call_context
);
539 // Garbage collection helper functions
540 bool RootJsToken(JsContextPtr cx
, JsToken t
);
544 //-----------------------------------------------------------------------------
547 #endif // GEARS_BASE_COMMON_JS_TYPES_H__