X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=blobdiff_plain;f=droute%2Fdroute.c;h=0a0bfd6bfc34d45cdba5dac409ea68150cebaa97;hp=55020a7e8c6dda49d5bf63596b9ee363fab338f9;hb=a9691925d9a5e2eb32009de2cc6bfa4b9f168945;hpb=9919d5a9ca422a958bf346f84b40e5315aad6fe2 diff --git a/droute/droute.c b/droute/droute.c index 55020a7..0a0bfd6 100644 --- a/droute/droute.c +++ b/droute/droute.c @@ -23,6 +23,7 @@ #include #include +#include #include "droute.h" #include "droute-pairhash.h" @@ -39,20 +40,24 @@ struct _DRouteContext { - DBusConnection *bus; GPtrArray *registered_paths; - gchar *introspect_dir; + gchar *introspect_string; }; struct _DRoutePath { DRouteContext *cnx; + gchar *path; + gboolean prefix; GStringChunk *chunks; GPtrArray *interfaces; + GPtrArray *introspection; GHashTable *methods; GHashTable *properties; + DRouteIntrospectChildrenFunction introspect_children_cb; + void *introspect_children_data; void *user_data; DRouteGetDatumFunction get_datum; }; @@ -70,19 +75,29 @@ typedef struct PropertyPair static DBusHandlerResult handle_message (DBusConnection *bus, DBusMessage *message, void *user_data); +static DBusMessage * +droute_object_does_not_exist_error (DBusMessage *message); + /*---------------------------------------------------------------------------*/ static DRoutePath * path_new (DRouteContext *cnx, + const char *path, + gboolean prefix, void *user_data, + DRouteIntrospectChildrenFunction introspect_children_cb, + void *introspect_children_data, DRouteGetDatumFunction get_datum) { DRoutePath *new_path; new_path = g_new0 (DRoutePath, 1); new_path->cnx = cnx; + new_path->path = g_strdup (path); + new_path->prefix = prefix; new_path->chunks = g_string_chunk_new (CHUNKS_DEFAULT); new_path->interfaces = g_ptr_array_new (); + new_path->introspection = g_ptr_array_new (); new_path->methods = g_hash_table_new_full ((GHashFunc)str_pair_hash, str_pair_equal, @@ -92,8 +107,10 @@ path_new (DRouteContext *cnx, new_path->properties = g_hash_table_new_full ((GHashFunc)str_pair_hash, str_pair_equal, g_free, - NULL); + g_free); + new_path->introspect_children_cb = introspect_children_cb; + new_path->introspect_children_data = introspect_children_data; new_path->user_data = user_data; new_path->get_datum = get_datum; @@ -103,8 +120,10 @@ path_new (DRouteContext *cnx, static void path_free (DRoutePath *path, gpointer user_data) { + g_free (path->path); g_string_chunk_free (path->chunks); g_ptr_array_free (path->interfaces, TRUE); + g_free(g_ptr_array_free (path->introspection, FALSE)); g_hash_table_destroy (path->methods); g_hash_table_destroy (path->properties); } @@ -121,14 +140,12 @@ path_get_datum (DRoutePath *path, const gchar *pathstr) /*---------------------------------------------------------------------------*/ DRouteContext * -droute_new (DBusConnection *bus, const char *introspect_dir) +droute_new () { DRouteContext *cnx; cnx = g_new0 (DRouteContext, 1); - cnx->bus = bus; cnx->registered_paths = g_ptr_array_new (); - cnx->introspect_dir = g_strdup(introspect_dir); return cnx; } @@ -137,18 +154,11 @@ void droute_free (DRouteContext *cnx) { g_ptr_array_foreach (cnx->registered_paths, (GFunc) path_free, NULL); - g_free (cnx->introspect_dir); g_free (cnx); } /*---------------------------------------------------------------------------*/ -DBusConnection * -droute_get_bus (DRouteContext *cnx) -{ - return cnx->bus; -} - /*---------------------------------------------------------------------------*/ static DBusObjectPathVTable droute_vtable = @@ -164,13 +174,8 @@ droute_add_one (DRouteContext *cnx, const void *data) { DRoutePath *new_path; - gboolean registered; - - new_path = path_new (cnx, (void *) data, NULL); - registered = dbus_connection_register_object_path (cnx->bus, path, &droute_vtable, new_path); - if (!registered) - oom(); + new_path = path_new (cnx, path, FALSE, (void *)data, NULL, NULL, NULL); g_ptr_array_add (cnx->registered_paths, new_path); return new_path; @@ -180,14 +185,15 @@ DRoutePath * droute_add_many (DRouteContext *cnx, const char *path, const void *data, + DRouteIntrospectChildrenFunction introspect_children_cb, + void *introspect_children_data, const DRouteGetDatumFunction get_datum) { DRoutePath *new_path; - new_path = path_new (cnx, (void *) data, get_datum); - - if (!dbus_connection_register_fallback (cnx->bus, path, &droute_vtable, new_path)) - oom(); + new_path = path_new (cnx, path, TRUE, (void *) data, + introspect_children_cb, introspect_children_data, + get_datum); g_ptr_array_add (cnx->registered_paths, new_path); return new_path; @@ -198,6 +204,7 @@ droute_add_many (DRouteContext *cnx, void droute_path_add_interface(DRoutePath *path, const char *name, + const char *introspect, const DRouteMethod *methods, const DRouteProperty *properties) { @@ -207,6 +214,7 @@ droute_path_add_interface(DRoutePath *path, itf = g_string_chunk_insert (path->chunks, name); g_ptr_array_add (path->interfaces, itf); + g_ptr_array_add (path->introspection, (gpointer) introspect); for (; methods != NULL && methods->name != NULL; methods++) { @@ -249,6 +257,8 @@ impl_prop_GetAll (DBusMessage *message, gchar *iface; void *datum = path_get_datum (path, pathstr); + if (!datum) + return droute_object_does_not_exist_error (message); dbus_error_init (&error); if (!dbus_message_get_args @@ -275,7 +285,7 @@ impl_prop_GetAll (DBusMessage *message, (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry)) oom (); dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, - key->two); + &key->two); (value->get) (&iter_dict_entry, datum); if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry)) oom (); @@ -299,6 +309,7 @@ impl_prop_GetSet (DBusMessage *message, StrPair pair; PropertyPair *prop_funcs = NULL; + void *datum; dbus_error_init (&error); if (!dbus_message_get_args (message, @@ -314,11 +325,19 @@ impl_prop_GetSet (DBusMessage *message, prop_funcs = (PropertyPair *) g_hash_table_lookup (path->properties, &pair); if (!prop_funcs) +#ifdef DBUS_ERROR_UNKNOWN_PROPERTY + return dbus_message_new_error (message, DBUS_ERROR_UNKNOWN_PROPERTY, "Property unavailable"); +#else return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable"); +#endif + + datum = path_get_datum (path, pathstr); + if (!datum) + return droute_object_does_not_exist_error (message); if (get && prop_funcs->get) { - void *datum = path_get_datum (path, pathstr); + DBusMessageIter iter; _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr); @@ -333,7 +352,6 @@ impl_prop_GetSet (DBusMessage *message, } else if (!get && prop_funcs->set) { - void *datum = path_get_datum (path, pathstr); DBusMessageIter iter; _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr); @@ -346,6 +364,12 @@ impl_prop_GetSet (DBusMessage *message, reply = dbus_message_new_method_return (message); } +#ifdef DBUS_ERROR_PROPERTY_READ_ONLY + else if (!get) + { + reply = dbus_message_new_error (message, DBUS_ERROR_PROPERTY_READ_ONLY, "Property is read-only"); + } +#endif else { reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Getter or setter unavailable"); @@ -355,6 +379,35 @@ impl_prop_GetSet (DBusMessage *message, } static DBusHandlerResult +handle_dbus (DBusConnection *bus, + DBusMessage *message, + const gchar *iface, + const gchar *member, + const gchar *pathstr) +{ + static int id = 1; + char *id_str = (char *) g_malloc(40); + DBusMessage *reply; + + if (strcmp (iface, DBUS_INTERFACE_DBUS) != 0 || + strcmp (member, "Hello") != 0) + { + g_free (id_str); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + /* TODO: Fix this hack (we don't handle wrap-around, for instance) */ + sprintf (id_str, ":1.%d", id++); + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &id_str, DBUS_TYPE_INVALID); + dbus_connection_send (bus, reply, NULL); + dbus_connection_flush (bus); + dbus_message_unref (reply); + g_free (id_str); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult handle_properties (DBusConnection *bus, DBusMessage *message, DRoutePath *path, @@ -362,7 +415,7 @@ handle_properties (DBusConnection *bus, const gchar *member, const gchar *pathstr) { - DBusMessage *reply; + DBusMessage *reply = NULL; DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED; if (!g_strcmp0(member, "GetAll")) @@ -394,35 +447,6 @@ static const char *introspection_node_element = static const char *introspection_footer = ""; -static void -append_interface (GString *str, - const gchar *interface, - const gchar *directory) -{ - gchar *filename; - gchar *contents; - gsize len; - - GError *err = NULL; - - filename = g_build_filename (directory, interface, NULL); - - if (g_file_get_contents (filename, &contents, &len, &err)) - { - g_string_append_len (str, contents, len); - } - else - { - g_warning ("AT-SPI: Cannot find introspection XML file %s - %s", - filename, err->message); - g_error_free (err); - } - - g_string_append (str, "\n"); - g_free (filename); - g_free (contents); -} - static DBusHandlerResult handle_introspection (DBusConnection *bus, DBusMessage *message, @@ -446,11 +470,23 @@ handle_introspection (DBusConnection *bus, g_string_append_printf(output, introspection_node_element, pathstr); - for (i=0; i < path->interfaces->len; i++) + if (!path->get_datum || path_get_datum (path, pathstr)) { - gchar *interface = (gchar *) g_ptr_array_index (path->interfaces, i); - _DROUTE_DEBUG ("DRoute (appending interface): %s\n", interface); - append_interface(output, interface, path->cnx->introspect_dir); + for (i=0; i < path->introspection->len; i++) + { + gchar *introspect = (gchar *) g_ptr_array_index (path->introspection, i); + g_string_append (output, introspect); + } + } + + if (path->introspect_children_cb) + { + gchar *children = (*path->introspect_children_cb) (pathstr, path->introspect_children_data); + if (children) + { + g_string_append (output, children); + g_free (children); + } } g_string_append(output, introspection_footer); @@ -484,6 +520,8 @@ handle_other (DBusConnection *bus, DRouteFunction func; DBusMessage *reply = NULL; + void *datum; + pair.one = iface; pair.two = member; @@ -492,20 +530,21 @@ handle_other (DBusConnection *bus, func = (DRouteFunction) g_hash_table_lookup (path->methods, &pair); if (func != NULL) { - void *datum = path_get_datum (path, pathstr); - - reply = (func) (bus, message, datum); - - if (!reply) + datum = path_get_datum (path, pathstr); + if (!datum) + reply = droute_object_does_not_exist_error (message); + else + reply = (func) (bus, message, datum); + + /* All D-Bus method calls must have a reply. + * If one is not provided presume that the caller has already + * sent one. + */ + if (reply) { - /* All D-Bus method calls must have a reply. - * If one is not provided presume that the call has a void - * return and no error has occured. - */ - reply = dbus_message_new_method_return (message); + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); } - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); result = DBUS_HANDLER_RESULT_HANDLED; } @@ -525,19 +564,57 @@ handle_message (DBusConnection *bus, DBusMessage *message, void *user_data) const gint type = dbus_message_get_type (message); const gchar *pathstr = dbus_message_get_path (message); + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + _DROUTE_DEBUG ("DRoute (handle message): %s|%s of type %d on %s\n", member, iface, type, pathstr); + /* Check for basic reasons not to handle */ if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || member == NULL || iface == NULL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return result; + + if (!strcmp (pathstr, DBUS_PATH_DBUS)) + result = handle_dbus (bus, message, iface, member, pathstr); + else if (!strcmp (iface, "org.freedesktop.DBus.Properties")) + result = handle_properties (bus, message, path, iface, member, pathstr); + else if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) + result = handle_introspection (bus, message, path, iface, member, pathstr); + else + result = handle_other (bus, message, path, iface, member, pathstr); +#if 0 + if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED) + g_print ("DRoute | Unhandled message: %s|%s of type %d on %s\n", member, iface, type, pathstr); +#endif + + return result; +} - if (!strcmp (iface, "org.freedesktop.DBus.Properties")) - return handle_properties (bus, message, path, iface, member, pathstr); +/*---------------------------------------------------------------------------*/ - if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) - return handle_introspection (bus, message, path, iface, member, pathstr); +static DBusMessage * +droute_object_does_not_exist_error (DBusMessage *message) +{ + DBusMessage *reply; + gchar *errmsg; - return handle_other (bus, message, path, iface, member, pathstr); + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" could not be processed as object %s does not exist\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message), + dbus_message_get_path (message)); +#ifdef DBUS_ERROR_UNKNOWN_OBJECT + reply = dbus_message_new_error (message, + DBUS_ERROR_UNKNOWN_OBJECT, + errmsg); +#else + reply = dbus_message_new_error (message, + DBUS_ERROR_FAILED, + errmsg); +#endif + g_free (errmsg); + return reply; } /*---------------------------------------------------------------------------*/ @@ -596,4 +673,54 @@ droute_invalid_arguments_error (DBusMessage *message) return reply; } +void +droute_path_register (DRoutePath *path, DBusConnection *bus) +{ + if (path->prefix) + dbus_connection_register_fallback (bus, path->path, &droute_vtable, path); + else + dbus_connection_register_object_path (bus, path->path, + &droute_vtable, path); +} + +void +droute_path_unregister (DRoutePath *path, DBusConnection *bus) +{ + dbus_connection_unregister_object_path (bus, path->path); +} + +void +droute_context_register (DRouteContext *cnx, DBusConnection *bus) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_register, + bus); +} + +void +droute_context_unregister (DRouteContext *cnx, DBusConnection *bus) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister, + bus); +} + +void +droute_context_deregister (DRouteContext *cnx, DBusConnection *bus) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister, + bus); +} + +void +droute_intercept_dbus (DBusConnection *bus) +{ + dbus_connection_register_object_path (bus, DBUS_PATH_DBUS, + &droute_vtable, NULL); +} + +void +droute_unintercept_dbus (DBusConnection *bus) +{ + dbus_connection_unregister_object_path (bus, DBUS_PATH_DBUS); +} + /*END------------------------------------------------------------------------*/