[xpcom] Implement DBus.emitSignal() in the D-Bus XPCOM service
[browser-dbus-bridge.git] / xpcom-dbusservice / DBusService.cpp
index 3191e1a..cfc4e8f 100644 (file)
@@ -177,6 +177,106 @@ DBusService::GetMethod(PRUint32 aBusType,
     return NS_OK;
 }
 
+NS_IMETHODIMP DBusService::EmitSignal(PRUint32 busType,
+                                      const nsACString & objectPath,
+                                      const nsACString & interfaceName,
+                                      const nsACString & signalName,
+                                      const nsACString & aSignature,
+                                      nsIVariant **args,
+                                      PRUint32 count,
+                                      PRBool *_retval)
+{
+    DBusMessage *msg;
+    DBusMessageIter msg_iter;
+    DBusConnection *conn;
+    nsCAutoString signature;
+
+    conn = GetConnection(busType);
+
+    if (!conn)
+    {
+        BDBLOG(("DBusService::EmitSignal()): invalid bus type %d\n",
+               busType));
+        return NS_ERROR_ILLEGAL_VALUE;
+    }
+
+    if (objectPath.IsEmpty()
+     || interfaceName.IsEmpty()
+     || signalName.IsEmpty())
+    {
+        BDBLOG(("DBusService::EmitSignal()): invalid signal arguments\n"));
+        return NS_ERROR_ILLEGAL_VALUE;
+    }
+
+    msg = dbus_message_new_signal(PromiseFlatCString(objectPath).get(),
+                                  PromiseFlatCString(interfaceName).get(),
+                                  PromiseFlatCString(signalName).get());
+    dbus_message_iter_init_append(msg, &msg_iter);
+
+    if (count > 0)
+    {
+        JSContext *cx = GetCurrentJSContext();
+
+        if (aSignature.Equals(""))
+        {
+            for (PRUint32 i = 0; i < count; i++)
+            {
+                // no method signature specified, guess argument types
+                nsCOMPtr<nsIVariant> data = args[i];
+                nsCAutoString tmpsig;
+
+                getSignatureFromVariant(cx, data, tmpsig);
+                BDBLOG(("  aArgs[%02d]       : signature \"%s\"\n",
+                       i,
+                       PromiseFlatCString(tmpsig).get()));
+                signature.Append(tmpsig);
+
+            }
+        } else {
+            signature.Assign(aSignature);
+        }
+
+        if (dbus_signature_validate(PromiseFlatCString(signature).get(), nsnull))
+        {
+            DBusSignatureIter sig_iter;
+            int current_type;
+            int i = 0;
+
+            BDBLOG(("  signature \"%s\"\n", PromiseFlatCString(signature).get()));
+
+            dbus_signature_iter_init(&sig_iter, PromiseFlatCString(signature).get());
+            while ((current_type = dbus_signature_iter_get_current_type(&sig_iter)) != DBUS_TYPE_INVALID)
+            {
+                char *element_signature = dbus_signature_iter_get_signature(&sig_iter);
+                BDBLOG(("  element \"%s\" from signature\n", element_signature));
+                BDBLOG(("  type %c from signature\n", current_type));
+
+                addVariantToIter(cx, args[i], &msg_iter, &sig_iter);
+
+                i++;
+                dbus_free(element_signature);
+                dbus_signature_iter_next(&sig_iter);
+            }
+        }
+        else
+        {
+            BDBLOG(("  invalid signature \"%s\"\n", PromiseFlatCString(signature).get()));
+            dbus_message_unref(msg);
+            return NS_ERROR_ILLEGAL_VALUE;
+        }
+    }
+
+    if (dbus_connection_send(conn, msg, NULL))
+    {
+        dbus_message_unref(msg);
+        return NS_OK;
+    }
+        
+    dbus_message_unref(msg);
+    return NS_ERROR_UNEXPECTED;
+}
+
 DBusPendingCall *DBusService::SendWithReply(PRUint32 aConnType,
                                             DBusMessage *aMessage,
                                             PRUint32 aTimeout)