[seed] Dbus: implement service side DBus stuff, still needs some work...
- From: Robert Carr <racarr src gnome org>
- To: svn-commits-list gnome org
- Subject: [seed] Dbus: implement service side DBus stuff, still needs some work...
- Date: Sun, 17 May 2009 20:03:21 -0400 (EDT)
commit 6818afd36a0f290467c3c75c052cdb0730333850
Author: Robert Carr <racarr svn gnome org>
Date: Sun May 17 20:02:49 2009 -0400
Dbus: implement service side DBus stuff, still needs some work...
---
libseed/seed-api.c | 17 ++
libseed/seed.h | 1 +
modules/dbus/dbus-exports.c | 343 ++++++++++++++++++++++++++++++++++++++++++-
modules/dbus/dbus-values.h | 2 +
modules/dbus/module.c | 5 +-
modules/dbus/util/dbus.c | 8 +-
6 files changed, 371 insertions(+), 5 deletions(-)
diff --git a/libseed/seed-api.c b/libseed/seed-api.c
index 14bb768..328735c 100644
--- a/libseed/seed-api.c
+++ b/libseed/seed-api.c
@@ -704,3 +704,20 @@ seed_object_is_of_class (JSContextRef ctx, JSObjectRef obj, JSClassRef class)
{
return JSValueIsObjectOfClass (ctx, obj, class);
}
+
+JSObjectRef
+seed_make_function (JSContextRef ctx,
+ gpointer func,
+ gchar *name)
+{
+ JSObjectRef oref;
+ JSStringRef jsname = NULL;
+ if (name)
+ jsname = JSStringCreateWithUTF8CString (name);
+ oref = JSObjectMakeFunctionWithCallback (ctx, NULL, func);
+
+ if (jsname)
+ JSStringRelease (jsname);
+
+ return oref;
+}
diff --git a/libseed/seed.h b/libseed/seed.h
index d57c2b6..9efad7d 100644
--- a/libseed/seed.h
+++ b/libseed/seed.h
@@ -243,6 +243,7 @@ typedef SeedValue (*SeedFunctionCallback) (SeedContext ctx,
void seed_create_function (SeedContext ctx,
gchar * name, SeedFunctionCallback callback,
SeedObject object);
+SeedObject seed_make_function (SeedContext ctx, SeedFunctionCallback callback, const gchar *name);
/* Inconsistent naming? */
SeedObject seed_make_array (SeedContext ctx, const SeedValue elements,
gsize num_elements, SeedException *exception);
diff --git a/modules/dbus/dbus-exports.c b/modules/dbus/dbus-exports.c
index 91ab398..fb15d1a 100644
--- a/modules/dbus/dbus-exports.c
+++ b/modules/dbus/dbus-exports.c
@@ -15,7 +15,7 @@ typedef struct _Exports {
gboolean filter_was_registered;
} Exports;
-SeedClass seed_js_exports_class;
+SeedClass seed_js_exports_class = NULL;
static void on_bus_opened (DBusConnection *connection,
void *data);
@@ -401,3 +401,344 @@ out:
return retval;
}
+
+/* returns an error message or NULL */
+static DBusMessage *
+invoke_js_async_from_dbus(SeedContext ctx,
+ DBusBusType bus_type,
+ DBusMessage *method_call,
+ SeedObject this_obj,
+ SeedObject method_obj,
+ SeedException *exception)
+{
+ DBusMessage *reply;
+ int argc;
+ SeedValue *argv;
+ DBusMessageIter arg_iter;
+ GArray *values;
+ SeedObject callback_object;
+ SeedValue sender_string, signature_string;
+ gboolean thrown;
+ SeedValue ignored;
+ const char *signature;
+
+ reply = NULL;
+ thrown = FALSE;
+ argc = 0;
+ argv = NULL;
+
+ if (!seed_js_values_from_dbus(ctx, &arg_iter, &values, exception))
+ {
+ if (!dbus_reply_from_exception(ctx, method_call, &reply, exception))
+ g_warning ("conversion of dbus method arg failed but no exception was set?");
+ return reply;
+ }
+
+ /* we will add an argument, the callback */
+ callback_object = seed_make_function(ctx, async_call_callback,
+ "" /* anonymous */);
+
+ g_assert(callback_object);
+
+ g_array_append_val(values, callback_object);
+
+ /* We attach the DBus sender and serial as properties to
+ * callback, so we don't need to bother with memory managing them
+ * if the callback is never called and just discarded.*/
+ sender_string = seed_value_from_string (ctx, dbus_message_get_sender (method_call), exception);
+ if (!sender_string)
+ {
+ thrown = TRUE;
+ goto out;
+ }
+
+ seed_object_set_property (ctx, callback_object, "_dbusSender", sender_string);
+ seed_object_set_property (ctx, callback_object, "_dbusSerial",
+ seed_value_from_int (ctx, dbus_message_get_serial (method_call),
+ exception));
+ seed_object_set_property (ctx, callback_object, "_dbusBusType",
+ seed_value_from_int (ctx, bus_type, exception));
+
+ if (!signature_from_method(ctx,
+ method_obj,
+ &signature,
+ exception))
+ {
+ thrown = TRUE;
+ goto out;
+ }
+
+ signature_string = seed_value_from_string (ctx, signature, exception);
+ if (!signature_string)
+ {
+ thrown = TRUE;
+ goto out;
+ }
+ seed_object_set_property (ctx, callback_object, "_dbusOutSignature",
+ signature_string);
+ argc = values->len;
+ argv = (SeedValue *)values->data;
+
+ seed_object_call (ctx, method_obj, this_obj, argc,
+ argv, &ignored);
+out:
+ if (thrown)
+ {
+ if (!dbus_reply_from_exception(ctx, method_call, &reply, exception))
+ g_warning("conversion of dbus method arg failed but no exception was set?");
+ }
+
+ g_array_free (values, TRUE);
+
+ return reply;
+}
+
+static SeedObject
+find_js_property_by_path(SeedContext ctx,
+ SeedObject root_obj,
+ const gchar *path)
+{
+ gchar **elements;
+ gint i;
+ SeedObject obj;
+
+ elements = g_strsplit(path, "/", -1);
+ obj = root_obj;
+
+ /* g_strsplit returns empty string for the first
+ * '/' so we start with elements[1]
+ */
+ for (i = 1; elements[i] != NULL; ++i)
+ {
+ obj = seed_object_get_property(ctx, obj, elements[i]);
+
+ if (seed_value_is_undefined (ctx, obj) ||
+ !seed_value_is_object (ctx, obj))
+ {
+ obj = NULL;
+ break;
+ }
+ }
+
+ g_strfreev(elements);
+
+ return obj;
+}
+
+static gboolean
+find_method(SeedContext ctx,
+ SeedObject obj,
+ const gchar *method_name,
+ SeedValue *method_value)
+{
+ *method_value = seed_object_get_property (ctx, obj, method_name);
+ if (seed_value_is_undefined (ctx, *method_value) ||
+ !seed_value_is_object (ctx, *method_value))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static DBusHandlerResult
+on_message(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ SeedContext ctx;
+ const char *path;
+ DBusHandlerResult result;
+ SeedObject obj;
+ const char *method_name;
+ char *async_method_name;
+ SeedValue method_value;
+ DBusMessage *reply;
+ Exports *priv;
+
+ priv = user_data;
+ async_method_name = NULL;
+ reply = NULL;
+
+ ctx = seed_context_create (group, NULL);
+ seed_prepare_global_context (ctx);
+
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ method_value = seed_make_undefined (ctx);
+
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ path = dbus_message_get_path(message);
+
+ obj = find_js_property_by_path(ctx,
+ priv->object,
+ path);
+ if (obj == NULL)
+ {
+ g_warning("There is no JS object at %s",
+ path);
+ goto out;
+ }
+
+ method_name = dbus_message_get_member(message);
+
+ async_method_name = g_strdup_printf("%sAsync", method_name);
+
+ /* try first if an async version exists */
+ if (find_method(ctx,
+ obj,
+ async_method_name,
+ &method_value)) {
+
+ g_warning ("Invoking async method %s on JS obj at dbus path %s",
+ async_method_name, path);
+
+ reply = invoke_js_async_from_dbus(ctx,
+ priv->which_bus,
+ message,
+ obj,
+ method_value,
+ NULL); // Need exception here.
+
+ result = DBUS_HANDLER_RESULT_HANDLED;
+
+ /* otherwise try the sync version */
+ } else if (find_method(ctx,
+ obj,
+ method_name,
+ &method_value)) {
+
+ g_warning("Invoking method %s on JS obj at dbus path %s",
+ method_name, path);
+
+ reply = invoke_js_from_dbus(ctx,
+ message,
+ obj,
+ method_value,
+ NULL); // Need exception here
+
+ result = DBUS_HANDLER_RESULT_HANDLED;
+ /* otherwise FAIL */
+ } else {
+ g_warning("There is a JS object at %s but it has no method %s",
+ path, method_name);
+ }
+
+ if (reply != NULL) {
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+
+out:
+ seed_context_unref (ctx);
+ if (async_method_name)
+ g_free(async_method_name);
+ return result;
+}
+
+static void
+exports_constructor(SeedContext ctx,
+ SeedObject obj)
+{
+ Exports *priv;
+
+ priv = g_slice_new0(Exports);
+
+ seed_object_set_private (obj, priv);
+ priv->object = obj;
+}
+
+static gboolean
+add_connect_funcs(SeedContext ctx,
+ SeedObject obj,
+ DBusBusType which_bus)
+{
+ Exports *priv;
+ BigDBusConnectFuncs const *connect_funcs;
+
+ priv = seed_object_get_private (obj);
+ if (priv == NULL)
+ return FALSE;
+
+ if (which_bus == DBUS_BUS_SESSION) {
+ connect_funcs = &session_connect_funcs;
+ } else if (which_bus == DBUS_BUS_SYSTEM) {
+ connect_funcs = &system_connect_funcs;
+ } else
+ g_assert_not_reached();
+
+ priv->which_bus = which_bus;
+ big_dbus_add_connect_funcs_sync_notify(connect_funcs, priv);
+
+ return TRUE;
+}
+
+static void
+exports_finalize (SeedObject obj)
+{
+ Exports *priv;
+ BigDBusConnectFuncs const *connect_funcs;
+
+ priv = seed_object_get_private (obj);
+ if (priv == NULL)
+ return; /* we are the prototype, not a real instance, so constructor never called */
+
+ if (priv->which_bus == DBUS_BUS_SESSION) {
+ connect_funcs = &session_connect_funcs;
+ } else if (priv->which_bus == DBUS_BUS_SYSTEM) {
+ connect_funcs = &system_connect_funcs;
+ } else
+ g_assert_not_reached();
+
+ big_dbus_remove_connect_funcs(connect_funcs, priv);
+
+ if (priv->connection_weak_ref != NULL) {
+ on_bus_closed(priv->connection_weak_ref, priv);
+ }
+
+ g_slice_free(Exports, priv);
+}
+
+
+static SeedObject
+exports_new (SeedContext ctx,
+ DBusBusType which_bus)
+{
+ SeedObject exports;
+ SeedObject global;
+
+ global = seed_context_get_global_object (ctx);
+ if (!seed_js_exports_class)
+ {
+ seed_class_definition def = seed_empty_class;
+ def.initialize = exports_constructor;
+ def.finalize = exports_finalize;
+
+ seed_js_exports_class = seed_create_class (&def);
+ }
+ exports = seed_make_object (ctx, seed_js_exports_class, NULL);
+
+ return exports;
+}
+
+gboolean
+seed_js_define_dbus_exports(SeedContext ctx,
+ SeedObject on_object,
+ DBusBusType which_bus)
+{
+ SeedObject exports;
+
+
+ exports = exports_new(ctx, which_bus);
+ if (!exports)
+ return FALSE;
+
+ if (!add_connect_funcs(ctx, exports, which_bus))
+ return FALSE;
+
+ seed_object_set_property (ctx, on_object, "exports",
+ exports);
+
+ return TRUE;
+}
diff --git a/modules/dbus/dbus-values.h b/modules/dbus/dbus-values.h
index f12325b..2aa948f 100644
--- a/modules/dbus/dbus-values.h
+++ b/modules/dbus/dbus-values.h
@@ -10,6 +10,8 @@
G_BEGIN_DECLS
+extern SeedContextGroup group;
+
gboolean seed_js_values_from_dbus (SeedContext ctx,
DBusMessageIter *iter,
GArray **aray_p,
diff --git a/modules/dbus/module.c b/modules/dbus/module.c
index 4d18ae0..0d02b50 100644
--- a/modules/dbus/module.c
+++ b/modules/dbus/module.c
@@ -2,6 +2,7 @@
#include "util/dbus.h"
#include "dbus-values.h"
+#include "dbus-exports.h"
#define DBUS_CONNECTION_FROM_TYPE(type) ((type) == DBUS_BUS_SESSION ? session_bus : system_bus)
@@ -1009,7 +1010,7 @@ seed_js_dbus_acquire_name(SeedContext ctx,
return seed_make_null (ctx);
}
- lost_func = arguments[4];
+ lost_func = arguments[3];
owner = g_slice_new0(BigJSDBusNameOwner);
@@ -1383,6 +1384,8 @@ define_bus_object (SeedContext ctx,
seed_object_set_property (ctx, bus_obj, "_dbusBusType",
seed_value_from_int (ctx, which_bus, NULL));
//TODO: Define exports
+ seed_js_define_dbus_exports (ctx, bus_obj, which_bus);
+
seed_object_set_property (ctx, namespace_ref, bus_name, bus_obj);
}
diff --git a/modules/dbus/util/dbus.c b/modules/dbus/util/dbus.c
index c461352..d5ba711 100644
--- a/modules/dbus/util/dbus.c
+++ b/modules/dbus/util/dbus.c
@@ -624,14 +624,16 @@ info_free(BigDBusInfo *info)
info->name_ownership_monitors->data);
}
- while (big_g_hash_table_steal_one(info->name_watches, &key, &value)) {
+ while (value = g_hash_table_lookup(info->name_watches, &key))
+ {
BigNameWatch *watch = value;
-
+
while (watch->watchers) {
name_watch_remove_watcher(watch, watch->watchers->data);
}
-
+
name_watch_free(watch);
+ g_hash_table_steal (info->name_watches, &key);
}
if (info->signal_watchers_by_unique_sender) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]