#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsArrayUtils.h"
+#include "nsTArray.h"
#include "nsMemory.h"
#include "nsISupportsPrimitives.h"
#include "nsIProperties.h"
#include "bdb-debug.h"
-void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
-void addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
+void getSignatureFromJSValue(JSContext *cx, jsval *aValue, nsCString &aResult);
+void getSignatureFromVariantType(PRUint16 aType, nsCString &aResult);
+void getSignatureFromISupports(JSContext* cx, nsISupports *aISupports, nsCString &aResult);
-static void
-listJSObjectProperties(JSContext *cx, JSObject *js_obj)
-{
- JSIdArray *props = JS_Enumerate(cx, js_obj);
- if (props)
- {
- BDBLOG((" listJSObjectProperties: got JSIdArray with %i props\n", props->length));
+void addArrayToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusType);
+void addArrayDataToIter(JSContext* cx, void *data_ptr, PRUint32 start, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
- for (int i = 0; i < props->length; i++)
- {
- jsval v;
- const PRUnichar *name;
- JS_IdToValue( cx, props->vector[i], &v );
- JSString *prop_string = JS_ValueToString(cx, v);
- name = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(prop_string));
- nsDependentString name_s(name);
- const char *utf8prop = NS_ConvertUTF16toUTF8(name_s).get();
- BDBLOG((" property %s\n", utf8prop));
-
- jsval value;
- if (JS_LookupUCProperty(cx,
- js_obj,
- JS_GetStringChars(prop_string),
- JS_GetStringLength(prop_string),
- &value) == JS_TRUE)
- {
- JSString *val_string = JS_ValueToString(cx, value);
- const PRUnichar *valstr = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(val_string));
- nsDependentString val_s(valstr);
- const char *utf8val = NS_ConvertUTF16toUTF8(val_s).get();
- BDBLOG((" value %s\n", utf8val));
- }
- }
- JS_DestroyIdArray(cx, props);
- }
-}
+void addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
+already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter, int aDBusType);
+
+void addBasicTypeToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusType);
void
getSignatureFromJSValue(JSContext *cx, jsval *aValue, nsCString &aResult)
{
nsISupports* supports;
JSClass* clazz;
- JSObject* parent;
JSObject* glob = JSVAL_TO_OBJECT(*aValue);
clazz = JS_GET_CLASS(cx, JS_GetParent(cx, glob));
if (variant)
{
BDBLOG((" found wrapped variant\n"));
- getSignatureFromVariant(variant, aResult);
+ getSignatureFromVariant(cx, variant, aResult);
return;
}
}
}
void
-getSignatureFromVariant(nsIVariant *aVariant, nsCString &aResult)
+getSignatureFromVariant(JSContext* cx, nsIVariant *aVariant, nsCString &aResult)
{
aResult.Assign(DBUS_TYPE_INVALID_AS_STRING);
{
// get element signature from first element
nsISupports *element = ((nsISupports **)data_ptr)[0];
- getSignatureFromISupports(element, elementsig);
+ getSignatureFromISupports(cx, element, elementsig);
}
else if (type == nsIDataType::VTYPE_ARRAY)
{
nsCOMPtr<nsISupports> is;
nsIID *iid;
aVariant->GetAsInterface(&iid, getter_AddRefs(is));
- getSignatureFromISupports(is, aResult);
+ getSignatureFromISupports(cx, is, aResult);
break;
}
default:
}
void
-getSignatureFromISupports(nsISupports *aISupports, nsCString &aResult)
+getSignatureFromISupports(JSContext* cx, nsISupports *aISupports, nsCString &aResult)
{
aResult.Assign(DBUS_TYPE_INVALID_AS_STRING);
if (variant)
{
BDBLOG((" getSignatureFromISupports: nsIVariant\n"));
- getSignatureFromVariant(variant, aResult);
+ getSignatureFromVariant(cx, variant, aResult);
return;
}
JSObject *js_obj = nsnull;
if (NS_SUCCEEDED(wrapped->GetJSObject(&js_obj)))
{
- // try to get a JS context (code borrowed from xpcsample1.cpp)
-
- // get the xpconnect service
- nsresult rv;
- nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
- if(NS_FAILED(rv))
- return;
- BDBLOG((" got nsIXPConnect\n"));
-
- // get the xpconnect native call context
- nsAXPCNativeCallContext *callContext = nsnull;
- xpc->GetCurrentNativeCallContext(&callContext);
- if(!callContext)
- return;
-
- // Get JSContext of current call
- JSContext* cx;
- rv = callContext->GetJSContext(&cx);
- if(NS_FAILED(rv) || !cx)
- return;
- BDBLOG((" got JSContext\n"));
-
jsval obj_as_jsval = OBJECT_TO_JSVAL(js_obj);
getSignatureFromJSValue(cx, &obj_as_jsval, aResult);
}
}
}
+PRUint16 getVType(int dType)
+{
+ switch (dType)
+ {
+ case DBUS_TYPE_BOOLEAN:
+ return nsIDataType::VTYPE_BOOL;
+ case DBUS_TYPE_BYTE:
+ return nsIDataType::VTYPE_INT8;
+ case DBUS_TYPE_INT16:
+ return nsIDataType::VTYPE_INT16;
+ case DBUS_TYPE_UINT16:
+ return nsIDataType::VTYPE_UINT16;
+ case DBUS_TYPE_INT32:
+ return nsIDataType::VTYPE_INT32;
+ case DBUS_TYPE_UINT32:
+ return nsIDataType::VTYPE_UINT32;
+ case DBUS_TYPE_DOUBLE:
+ return nsIDataType::VTYPE_DOUBLE;
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ return nsIDataType::VTYPE_WCHAR_STR;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+PRBool typesMatch(PRUint16 vType, int dType)
+{
+ return (vType == getVType(dType));
+}
+
void
-addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
+addVariantToIter(JSContext* cx, nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
{
char *element_signature = dbus_signature_iter_get_signature(aSigIter);
int element_type = dbus_signature_iter_get_current_type(aSigIter);
{
/* TODO: Support for non-JS Dicts */
- BDBLOG((" add dict from variant\n"));
+ BDBLOG((" add dict from variant\n"));
nsCOMPtr<nsISupports> is;
nsIID *iid;
// Reported by a leak, dunno why?
+ // It's a comptr so it should go away with the end of context afaik
aVariant->GetAsInterface(&iid, getter_AddRefs(is));
// test argument for nsIXPConnectWrappedJS
JSObject *js_obj = nsnull;
if (NS_SUCCEEDED(wrapped->GetJSObject(&js_obj)))
{
- // try to get a JS context (code borrowed from xpcsample1.cpp)
-
- // get the xpconnect service
- nsresult rv;
- nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
- if(NS_FAILED(rv))
- return;
- BDBLOG((" got nsIXPConnect\n"));
-
- // get the xpconnect native call context
- nsAXPCNativeCallContext *callContext = nsnull;
- xpc->GetCurrentNativeCallContext(&callContext);
- if(!callContext)
- return;
-
- // Get JSContext of current call
- JSContext* cx;
- rv = callContext->GetJSContext(&cx);
- if(NS_FAILED(rv) || !cx)
- return;
- BDBLOG((" got JSContext\n"));
-
- jsval obj_as_jsval = OBJECT_TO_JSVAL(js_obj);
-
// try to enumerate object properties
JSIdArray *props = JS_Enumerate(cx, js_obj);
if (props)
dbus_signature_iter_recurse(&childSigIter, &dictSigIter);
dbus_signature_iter_next(&dictSigIter); // key type
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+ if(NS_FAILED(rv))
+ return;
+ BDBLOG((" got nsIXPConnect\n"));
+
+
for (int p = 0; p < props->length; p++)
{
- // get key signature from first property name
jsval propname;
nsCAutoString tmpsig;
JS_IdToValue(cx, props->vector[p], &propname);
JS_GetStringLength(prop_string),
&propvalue) == JS_TRUE)
{
- addJSValueToIter(cx, &propvalue, &dictIter, &dictSigIter);
+ nsIVariant *var = nsnull;
+ nsresult rs = xpc->JSToVariant(cx, propvalue, &var);
+ NS_ENSURE_SUCCESS(rs, );
+
+ addVariantToIter(cx, var, &dictIter, &dictSigIter);
}
// Close the dict entry container
&count,
&data_ptr);
- BDBLOG((" getSignatureFromVariant: got %d elements of type %d\n", count, type));
- BDBLOG((" getSignatureFromVariant: got array signature %s\n", array_signature));
+ BDBLOG((" %s: got %d elements of type %d\n", __FUNCTION__, count, type));
+ BDBLOG((" %s: got array signature %s\n", __FUNCTION__, array_signature));
- DBusMessageIter arrayIter;
- if (dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
- array_signature, &arrayIter))
+ int dbustype = dbus_signature_iter_get_current_type(&aChildSigIter);
+
+ if (typesMatch(type, dbustype))
{
- addArrayDataToIter(data_ptr, count, type, &arrayIter, &aChildSigIter);
+ BDBLOG(("*** Yay, types match!\n"));
+
+ DBusMessageIter arrayIter;
+ if (dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
+ array_signature, &arrayIter))
+ {
+ addArrayDataToIter(cx, data_ptr, 0, count, type,
+ &arrayIter, &aChildSigIter);
+ dbus_message_iter_close_container(aIter, &arrayIter);
+ }
+ nsMemory::Free(data_ptr);
+ } else {
+ BDBLOG(("*** Bummer, types don't match so we'll need to iterate\n"));
+
+ DBusMessageIter arrayIter;
+ dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
+ array_signature, &arrayIter);
+
+ /* Seems stupid not to be able to iterate over the values as
+ * nsIVariants directly, but no API to that effect seems to be
+ * available...
+ */
+ for (PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance("@mozilla.org/variant;1");
+
+ switch (type)
+ {
+#define SET_INT(bits) \
+ case nsIDataType::VTYPE_INT ## bits: \
+ variant->SetAsInt ## bits(*(((PRInt ## bits*)data_ptr)+i)); \
+ break; \
+ case nsIDataType::VTYPE_UINT ## bits: \
+ variant->SetAsUint ## bits(*(((PRUint ## bits*)data_ptr)+i)); \
+ break;
+ SET_INT(16)
+ SET_INT(32)
+ SET_INT(64)
+ default:
+ BDBLOG(("*** No conversion from %i to %c\n", type, dbustype));
+ break;
+ }
+
+ addVariantToIter(cx, variant, &arrayIter, &aChildSigIter);
+ }
+
dbus_message_iter_close_container(aIter, &arrayIter);
+ nsMemory::Free(data_ptr);
}
- nsMemory::Free(data_ptr);
}
}
else if (element_type == DBUS_TYPE_STRUCT)
}
}
-void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
+void addArrayDataToIter(JSContext* cx, void *data_ptr, PRUint32 start, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
{
int aDBusType = dbus_signature_iter_get_current_type(aSigIter);
BDBLOG(("addArrayDataToIter: appending %d elements of type %d '%c'\n", count, type, aDBusType));
switch (type)
{
#define ADD_DATA \
- for (int i = 0; i < count; i++) \
+ for (PRUint32 i = start; i < count; i++) \
dbus_message_iter_append_basic(aIter, aDBusType, data+i)
case nsIDataType::VTYPE_INT8:
case nsIDataType::VTYPE_UINT8:
case nsIDataType::VTYPE_WCHAR_STR:
{
PRUnichar **data = (PRUnichar **)data_ptr;
- for (int i = 0; i < count; i++)
+ for (PRUint32 i = start; i < count; i++)
{
const char *val_ptr;
nsCAutoString val = NS_ConvertUTF16toUTF8(data[i]);
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsISupports **data = (nsISupports **)data_ptr;
- for (int i = 0; i < count; i++)
+ for (PRUint32 i = start; i < count; i++)
{
nsCOMPtr<nsIVariant> data_variant = do_QueryInterface(data[i]);
if (data_variant)
- addVariantToIter(data_variant, aIter, aSigIter);
+ addVariantToIter(cx, data_variant, aIter, aSigIter);
else
BDBLOG((" interface not nsIVariant\n"));
}
int dbusType = dbus_signature_iter_get_current_type(aSigIter);
- BDBLOG(("%s(%c, %s)\n", __FUNCTION__, dbusType,
- dbus_signature_iter_get_signature(aSigIter)));
+ BDBLOG(("%s(%s, %c, %s)\n", __FUNCTION__,
+ JS_GetTypeName(cx, JS_TypeOfValue(cx, *aValue)),
+ dbusType, dbus_signature_iter_get_signature(aSigIter)));
// Using the expected type instead of the actual allows autoconversion
switch (dbusType)
if (JS_ValueToNumber(cx, *aValue, &d))
{
+ BDBLOG(("%s(%f)\n", __FUNCTION__, d));
dbus_message_iter_append_basic(aIter, dbusType, &d);
}
else
{
- BDBLOG(("%s(): Could not fetch boolean from jsvalue\n", __FUNCTION__));
+ BDBLOG(("%s(): Could not fetch number from jsvalue\n", __FUNCTION__));
}
break;
{
if (JSVAL_IS_OBJECT(*aValue) && JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*aValue)))
{
- JSIdArray *props = JS_Enumerate(cx, JSVAL_TO_OBJECT(*aValue));
- if (props)
- {
- BDBLOG((" got JSIdArray\n"));
+ // Arrays are simply converted to variants and pushed to the
+ // variant code path
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+ if(NS_FAILED(rv))
+ return;
+ BDBLOG((" got nsIXPConnect\n"));
- // Open container
- DBusSignatureIter arraySigIter;
- dbus_signature_iter_recurse(aSigIter, &arraySigIter);
- char *array_sig = dbus_signature_iter_get_signature(&arraySigIter);
-
- DBusMessageIter arrayIter;
- dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
- array_sig, &arrayIter);
- dbus_free(array_sig);
-
- for (int p = 0; p < props->length; p++)
- {
- int type = dbus_signature_iter_get_current_type(&arraySigIter);
- jsval propname;
- JS_IdToValue(cx, props->vector[p], &propname);
-
- jsval propvalue;
- JSString *prop_string = JS_ValueToString(cx, propname);
- if (JS_LookupUCProperty(cx,
- JSVAL_TO_OBJECT(*aValue),
- JS_GetStringChars(prop_string),
- JS_GetStringLength(prop_string),
- &propvalue) == JS_TRUE)
- {
- addJSValueToIter(cx, &propvalue, &arrayIter, &arraySigIter);
- } else {
- break;
- }
-
- dbus_signature_iter_next(&arraySigIter);
- }
-
- dbus_message_iter_close_container(aIter, &arrayIter);
- JS_DestroyIdArray(cx, props);
- }
+ nsIVariant *var = nsnull;
+ nsresult rs = xpc->JSToVariant(cx, *aValue, &var);
+ NS_ENSURE_SUCCESS(rs, );
+
+ addVariantToIter(cx, var, aIter, aSigIter);
}
break;
void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, jsval *v)
{
+ BDBLOG(("%s(%c)\n", __FUNCTION__, aDBusType));
+
+
switch (aDBusType)
{
case DBUS_TYPE_STRING:
dbus_message_iter_get_basic(aIter, &val);
if (val != nsnull)
{
- JSString *str = JS_NewStringCopyN(cx, val, strlen(val));
+ nsAutoString uval = NS_ConvertUTF8toUTF16(val);
+ JSString *str = JS_NewUCStringCopyN(cx, uval.get(), uval.Length());
*v = STRING_TO_JSVAL(str);
}
break;
case DBUS_TYPE_UINT32:
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
- case DBUS_TYPE_DOUBLE:
{
dbus_uint64_t val = 0;
dbus_message_iter_get_basic(aIter, &val);
}
break;
}
+ case DBUS_TYPE_DOUBLE:
+ {
+ jsdouble val = 0.0;
+ dbus_message_iter_get_basic(aIter, &val);
+ if (!JS_NewNumberValue(cx, val, v))
+ {
+ BDBLOG(("%s: Number conversion from %c failed\n", __FUNCTION__,
+ aDBusType));
+ }
+ break;
+ }
case DBUS_TYPE_ARRAY:
{
// FIXME: implement!
-/*
+ // FIXME: Dicts
+
nsTArray<jsval> elems;
// recurse to container
+ DBusMessageIter arrayIter;
+ dbus_message_iter_recurse(aIter, &arrayIter);
// iterate over array elements
do
{
- getJSValueFromIter
+ jsval cv;
+ BDBLOG(("arg type: %c\n", dbus_message_iter_get_arg_type(&arrayIter)));
+ getJSValueFromIter(cx,
+ &arrayIter,
+ dbus_message_iter_get_arg_type(&arrayIter),
+ &cv);
+ elems.AppendElement(cv);
- } while (iter_next);
+ } while (dbus_message_iter_next(&arrayIter));
// Create an Array object with the elements
- JSObject *array = JS_NewArrayObject(cx, 0, NULL);
-*/
+ JSObject *array = JS_NewArrayObject(cx, elems.Length(), elems.Elements());
+ *v = OBJECT_TO_JSVAL(array);
break;
}
case DBUS_TYPE_STRUCT:
return;
}
-already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter, int aDBusType)
+already_AddRefed<nsIWritableVariant> getVariantFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType)
{
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance("@mozilla.org/variant;1");
nsIWritableVariant *retval;
{
BDBLOG((" arg type ARRAY with DICT_ENTRY\n"));
- // try to get a JS context (code borrowed from xpcsample1.cpp)
-
- // get the xpconnect service
- nsresult rv;
- nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
- if(NS_FAILED(rv))
- return nsnull;
- BDBLOG((" got nsIXPConnect\n"));
-
- // get the xpconnect native call context
- // FIXME: this doesn't work for signals since there's no
- // active context there...
- nsAXPCNativeCallContext *callContext = nsnull;
- xpc->GetCurrentNativeCallContext(&callContext);
- if(!callContext)
- {
- BDBLOG((" callContext :(\n"));
- return nsnull;
- }
- // Get JSContext of current call
- JSContext* cx;
- rv = callContext->GetJSContext(&cx);
- if(NS_FAILED(rv) || !cx)
- return nsnull;
- BDBLOG((" got JSContext\n"));
-
// Construct a JS Object
JSObject *obj = JS_NewObject(cx, nsnull, nsnull, nsnull);
} while (dbus_message_iter_next(&array_iter));
+ // get the xpconnect service
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+ if(NS_FAILED(rv))
+ return nsnull;
+ BDBLOG((" got nsIXPConnect\n"));
+
// Convert to variant and return
nsIVariant *var = nsnull;
- nsresult rs = xpc->JSToVariant(cx, OBJECT_TO_JSVAL(obj), &var);
+ rv = xpc->JSToVariant(cx, OBJECT_TO_JSVAL(obj), &var);
+ if(NS_FAILED(rv))
+ return nsnull;
variant->SetFromVariant(var);
var = nsnull;
NS_ADDREF(retval = variant);
BDBLOG((" arg type ARRAY\n"));
dbus_message_iter_recurse(aIter, &array_iter);
- items = getArrayFromIter(&array_iter);
+ items = getArrayFromIter(cx, &array_iter);
items->GetLength(&item_count);
BDBLOG((" array: %d items\n", item_count));
nsIVariant **item_array = new nsIVariant*[item_count];
- for (int i = 0; i < item_count; i++)
+ for (PRUint32 i = 0; i < item_count; i++)
{
nsCOMPtr<nsIVariant> item = do_QueryElementAt(items, i);
item_array[i] = item;
&NS_GET_IID(nsIVariant),
item_count,
item_array);
- for (int i = 0; i < item_count; i++)
+ for (PRUint32 i = 0; i < item_count; i++)
NS_RELEASE(item_array[i]);
delete[] item_array;
}
return retval;
}
-already_AddRefed<nsIMutableArray> getArrayFromIter(DBusMessageIter *aIter)
+already_AddRefed<nsIMutableArray> getArrayFromIter(JSContext* cx, DBusMessageIter *aIter)
{
int current_type;
nsCOMPtr<nsIMutableArray> array = do_CreateInstance("@mozilla.org/array;1");
while ((current_type = dbus_message_iter_get_arg_type(aIter)) != DBUS_TYPE_INVALID)
{
- nsCOMPtr<nsIWritableVariant> variant = getVariantFromIter(aIter, current_type);
+ nsCOMPtr<nsIWritableVariant> variant = getVariantFromIter(cx, aIter, current_type);
if (variant)
array->AppendElement(variant, PR_FALSE);
else