diff options
Diffstat (limited to 'glib/dbus-gobject.c')
-rw-r--r-- | glib/dbus-gobject.c | 127 |
1 files changed, 125 insertions, 2 deletions
diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index 8e399796..c91f1851 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -39,9 +39,16 @@ * @{ */ +typedef struct +{ + char *default_iface; + GType code_enum; +} DBusGErrorInfo; + static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT; static GHashTable *info_hash = NULL; static GHashTable *marshal_table = NULL; +static GData *error_metadata = NULL; static char* uscore_to_wincaps (const char *uscore) @@ -696,6 +703,7 @@ lookup_object_and_method (GObject *object, static char * gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info, + const char *msg_interface, GQuark domain, gint code) { const char *domain_str; @@ -707,6 +715,36 @@ gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info, if (!domain_str || !code_str) { + DBusGErrorInfo *info; + + g_static_rw_lock_reader_lock (&globals_lock); + + if (error_metadata != NULL) + info = g_datalist_id_get_data (&error_metadata, domain); + else + info = NULL; + + g_static_rw_lock_reader_unlock (&globals_lock); + + if (info) + { + GEnumValue *value; + GEnumClass *klass; + + klass = g_type_class_ref (info->code_enum); + value = g_enum_get_value (klass, code); + g_type_class_unref (klass); + + domain_str = info->default_iface; + code_str = value->value_nick; + } + } + + if (!domain_str) + domain_str = msg_interface; + + if (!domain_str || !code_str) + { /* If we can't map it sensibly, make up an error name */ char *domain_from_quark; @@ -752,7 +790,9 @@ gerror_to_dbus_error_message (const DBusGObjectInfo *object_info, else { char *error_name; - error_name = gerror_domaincode_to_dbus_error_name (object_info, error->domain, error->code); + error_name = gerror_domaincode_to_dbus_error_name (object_info, + dbus_message_get_interface (message), + error->domain, error->code); reply = dbus_message_new_error (message, error_name, error->message); g_free (error_name); } @@ -1256,6 +1296,40 @@ export_signals (DBusGConnection *connection, const DBusGObjectInfo *info, GObjec } } +#include "dbus-glib-error-switch.h" + +void +dbus_set_g_error (GError **gerror, + DBusError *error) +{ + int code; + + code = dbus_error_to_gerror_code (error->name); + if (code != DBUS_GERROR_REMOTE_EXCEPTION) + g_set_error (gerror, DBUS_GERROR, + code, + "%s", + error->message); + else + g_set_error (gerror, DBUS_GERROR, + code, + "%s%c%s", + error->message, + '\0', + error->name); +} + +static void +dbus_g_error_info_free (gpointer p) +{ + DBusGErrorInfo *info; + + info = p; + + g_free (info->default_iface); + g_free (info); +} + /** @} */ /* end of internals */ /** @@ -1287,7 +1361,7 @@ dbus_g_object_type_install_info (GType object_type, dbus_g_value_types_init (); - object_class = g_type_class_peek (object_type); + object_class = g_type_class_ref (object_type); g_return_if_fail (G_IS_OBJECT_CLASS (object_class)); @@ -1301,6 +1375,55 @@ dbus_g_object_type_install_info (GType object_type, g_hash_table_replace (info_hash, object_class, (void*) info); g_static_rw_lock_writer_unlock (&globals_lock); + + g_type_class_unref (object_class); +} + +/** + * Register a GError domain and set of codes with D-BUS. You must + * have created a GEnum for the error codes. This function will not + * be needed with an introspection-capable GLib. + * + * @param domain the GError domain + * @param default_iface the D-BUS interface used for error values by default, or #NULL + * @param code_enum a GType for a GEnum of the error codes + */ +void +dbus_g_error_domain_register (GQuark domain, + const char *default_iface, + GType code_enum) +{ + DBusGErrorInfo *info; + + g_return_if_fail (g_quark_to_string (domain) != NULL); + g_return_if_fail (code_enum != G_TYPE_INVALID); + g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM); + + g_static_rw_lock_writer_lock (&globals_lock); + + if (error_metadata == NULL) + g_datalist_init (&error_metadata); + + info = g_datalist_id_get_data (&error_metadata, domain); + + if (info != NULL) + { + g_warning ("Metadata for error domain \"%s\" already registered\n", + g_quark_to_string (domain)); + } + else + { + info = g_new0 (DBusGErrorInfo, 1); + info->default_iface = g_strdup (default_iface); + info->code_enum = code_enum; + + g_datalist_id_set_data_full (&error_metadata, + domain, + info, + dbus_g_error_info_free); + } + + g_static_rw_lock_writer_unlock (&globals_lock); } static void |