[xpcom] Fix string handling in getJSValueFromIter()
[browser-dbus-bridge.git] / xpcom-dbusservice / DBusMarshaling.cpp
index 74ded6b1f56f18704fd4db0d96ed04b2d5ed1e4a..cfb66453a837333ca693323cbea3008269d21791 100644 (file)
@@ -30,6 +30,7 @@
 #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)
@@ -132,7 +105,6 @@ 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));
@@ -193,7 +165,7 @@ getSignatureFromJSValue(JSContext *cx, jsval *aValue, nsCString &aResult)
                 if (variant)
                 {
                     BDBLOG(("    found wrapped variant\n"));
-                    getSignatureFromVariant(variant, aResult);
+                    getSignatureFromVariant(cx, variant, aResult);
                     return;
                 }
             }
@@ -251,7 +223,7 @@ getSignatureFromVariantType(PRUint16 aType, nsCString &aResult)
 }
 
 void
-getSignatureFromVariant(nsIVariant *aVariant, nsCString &aResult)
+getSignatureFromVariant(JSContext* cx, nsIVariant *aVariant, nsCString &aResult)
 {
     aResult.Assign(DBUS_TYPE_INVALID_AS_STRING);
 
@@ -302,7 +274,7 @@ getSignatureFromVariant(nsIVariant *aVariant, nsCString &aResult)
             {
                 // 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)
             {
@@ -326,7 +298,7 @@ getSignatureFromVariant(nsIVariant *aVariant, nsCString &aResult)
             nsCOMPtr<nsISupports> is;
             nsIID *iid;
             aVariant->GetAsInterface(&iid, getter_AddRefs(is));
-            getSignatureFromISupports(is, aResult);
+            getSignatureFromISupports(cx, is, aResult);
             break;
         }
         default:
@@ -338,7 +310,7 @@ getSignatureFromVariant(nsIVariant *aVariant, nsCString &aResult)
 }
 
 void
-getSignatureFromISupports(nsISupports *aISupports, nsCString &aResult)
+getSignatureFromISupports(JSContext* cx, nsISupports *aISupports, nsCString &aResult)
 {
     aResult.Assign(DBUS_TYPE_INVALID_AS_STRING);
 
@@ -347,7 +319,7 @@ getSignatureFromISupports(nsISupports *aISupports, nsCString &aResult)
     if (variant)
     {
         BDBLOG(("  getSignatureFromISupports: nsIVariant\n"));
-        getSignatureFromVariant(variant, aResult);
+        getSignatureFromVariant(cx, variant, aResult);
         return;
     }
 
@@ -359,36 +331,48 @@ getSignatureFromISupports(nsISupports *aISupports, nsCString &aResult)
         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);
@@ -412,11 +396,12 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
         {
             /* 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
@@ -427,30 +412,6 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                 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)
@@ -470,9 +431,15 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                         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);
@@ -499,7 +466,11 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                                                     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
@@ -532,18 +503,63 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                                  &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)
@@ -702,7 +718,7 @@ void addBasicTypeToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusT
     }
 }
 
-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));
@@ -710,7 +726,7 @@ void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessa
     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:
@@ -749,7 +765,7 @@ void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessa
         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]);
@@ -767,11 +783,11 @@ void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessa
         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"));
             }
@@ -792,8 +808,9 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
 
     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)
@@ -826,11 +843,12 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
             
             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;
@@ -849,46 +867,19 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
         {
             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;
@@ -902,6 +893,9 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
 void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, jsval *v)
 {
 
+    BDBLOG(("%s(%c)\n", __FUNCTION__, aDBusType));
+
+
     switch (aDBusType)
     {
         case DBUS_TYPE_STRING:
@@ -912,7 +906,8 @@ void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, js
             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;
@@ -924,7 +919,6 @@ void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, js
         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);
@@ -935,24 +929,44 @@ void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, js
             }
             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:
@@ -965,7 +979,7 @@ void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, js
     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;
@@ -1040,32 +1054,6 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter,
             {
                 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);
                 
@@ -1089,9 +1077,18 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter,
                     
                 } 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);
@@ -1107,12 +1104,12 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter,
 
                 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;
@@ -1122,7 +1119,7 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter,
                                     &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;
             }
@@ -1139,7 +1136,7 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter,
     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");
@@ -1149,7 +1146,7 @@ already_AddRefed<nsIMutableArray> getArrayFromIter(DBusMessageIter *aIter)
 
     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