[XPCOM] Keep the JS context with the Service/Method objects, we
[browser-dbus-bridge.git] / xpcom-dbusservice / DBusMarshaling.cpp
index b71f23c..71e8f3d 100644 (file)
 
 #include "bdb-debug.h"
 
-void addArrayDataToIter(void *data_ptr, PRUint32 start, 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)
@@ -194,7 +166,7 @@ getSignatureFromJSValue(JSContext *cx, jsval *aValue, nsCString &aResult)
                 if (variant)
                 {
                     BDBLOG(("    found wrapped variant\n"));
-                    getSignatureFromVariant(variant, aResult);
+                    getSignatureFromVariant(cx, variant, aResult);
                     return;
                 }
             }
@@ -252,7 +224,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);
 
@@ -303,7 +275,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)
             {
@@ -327,7 +299,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:
@@ -339,7 +311,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);
 
@@ -348,7 +320,7 @@ getSignatureFromISupports(nsISupports *aISupports, nsCString &aResult)
     if (variant)
     {
         BDBLOG(("  getSignatureFromISupports: nsIVariant\n"));
-        getSignatureFromVariant(variant, aResult);
+        getSignatureFromVariant(cx, variant, aResult);
         return;
     }
 
@@ -360,28 +332,6 @@ 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);
         }
@@ -423,7 +373,7 @@ PRBool typesMatch(PRUint16 vType, int 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);
@@ -463,30 +413,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)
@@ -506,6 +432,13 @@ 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++)
                         {
                             jsval propname;
@@ -538,7 +471,7 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                                 nsresult rs = xpc->JSToVariant(cx, propvalue, &var);
                                 NS_ENSURE_SUCCESS(rs, );
 
-                                addVariantToIter(var, &dictIter, &dictSigIter);
+                                addVariantToIter(cx, var, &dictIter, &dictSigIter);
                             }
                             
                             // Close the dict entry container
@@ -584,7 +517,7 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                 if (dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
                                                      array_signature, &arrayIter))
                 {
-                    addArrayDataToIter(data_ptr, 0, count, type,
+                    addArrayDataToIter(cx, data_ptr, 0, count, type,
                                        &arrayIter, &aChildSigIter);
                     dbus_message_iter_close_container(aIter, &arrayIter);
                 }
@@ -621,7 +554,7 @@ addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter
                             break;
                     }
 
-                    addVariantToIter(variant, &arrayIter, &aChildSigIter);
+                    addVariantToIter(cx, variant, &arrayIter, &aChildSigIter);
                 }
 
                 dbus_message_iter_close_container(aIter, &arrayIter);
@@ -786,7 +719,7 @@ void addBasicTypeToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusT
     }
 }
 
-void addArrayDataToIter(void *data_ptr, PRUint32 start, 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));
@@ -855,7 +788,7 @@ void addArrayDataToIter(void *data_ptr, PRUint32 start, PRUint32 count, PRUint16
             {
                 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"));
             }
@@ -947,7 +880,7 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
                 nsresult rs = xpc->JSToVariant(cx, *aValue, &var);
                 NS_ENSURE_SUCCESS(rs, );
 
-                addVariantToIter(var, aIter, aSigIter);
+                addVariantToIter(cx, var, aIter, aSigIter);
             }
             
             break;
@@ -1046,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;
@@ -1121,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);
                 
@@ -1170,6 +1077,13 @@ 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);
@@ -1188,7 +1102,7 @@ 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));
 
@@ -1220,7 +1134,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");
@@ -1230,7 +1144,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