summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog36
-rw-r--r--dbus/dbus-glib.h7
-rw-r--r--glib/dbus-glib.c45
-rw-r--r--glib/dbus-gmain.c3
-rw-r--r--glib/dbus-gobject.c127
-rw-r--r--glib/dbus-gparser.c3
-rw-r--r--glib/dbus-gproxy.c6
-rw-r--r--test/glib/Makefile.am2
-rw-r--r--test/glib/test-dbus-glib.c16
-rw-r--r--test/glib/test-service-glib.c99
-rw-r--r--test/glib/test-service-glib.xml10
11 files changed, 293 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog
index bce59c68..0476f339 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2005-06-30 Colin Walters <walters@verbum.org>
+
+ * test/glib/test-dbus-glib.c:
+ * test/glib/test-service-glib.c:
+ * test/glib/test-service-glib.xml: Update tests for new error
+ setting bits, also add async tests (patch from Ross Burton).
+
+ * test/glib/Makefile.am (test_service_glib_LDADD): Add
+ DBUS_GLIB_THREADS_LIBS.
+
+ * glib/dbus-gproxy.c (get_name_owner)
+ (dbus_g_pending_call_end_valist): Ditto.
+
+ * glib/dbus-gobject.c (error_metadata): New mapping from GError
+ domain (GQuark) to DBusGErrorInfo.
+ (gerror_domaincode_to_dbus_error_name): Attempt to look up error
+ quark in error_metadata. Take message interface as default
+ error message interface.
+ (gerror_to_dbus_error_message): Pass message interface.
+ (dbus_set_g_error): Resurrected.
+ (dbus_g_error_info_free): New function.
+ (dbus_g_object_type_install_info): Use g_type_class_ref instead
+ of _peek to actually create the object class if it hasn't been
+ created yet.
+ (dbus_g_error_domain_register): New function.
+
+ * glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error.
+
+ * glib/dbus-gparser.c (validate_signature): Ditto.
+
+ * dbus/dbus-glib.h (dbus_g_error_set): Delete.
+ (dbus_g_error_domain_register): Prototype.
+
+ * glib/dbus-glib.c (dbus_g_error_set): Delete.
+ Update tests.
+
2005-06-29 Colin Walters <walters@verbum.org>
* dbus/dbus-glib.h: Delete DBUS_TYPE_G_PROXY_ARRAY. Add
diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h
index 5e791e01..41b3d9c1 100644
--- a/dbus/dbus-glib.h
+++ b/dbus/dbus-glib.h
@@ -81,9 +81,6 @@ typedef enum
#include <dbus/dbus-glib-error-enum.h>
} DBusGError;
-void dbus_g_error_set (GError **error,
- const char *name,
- const char *msg);
gboolean dbus_g_error_has_name (GError *error,
const char *name);
const char * dbus_g_error_get_name (GError *error);
@@ -126,6 +123,10 @@ struct _DBusGObjectInfo
void dbus_g_object_type_install_info (GType object_type,
const DBusGObjectInfo *info);
+void dbus_g_error_domain_register (GQuark domain,
+ const char * default_iface,
+ GType code_enum);
+
void dbus_g_connection_register_g_object (DBusGConnection *connection,
const char *at_path,
GObject *object);
diff --git a/glib/dbus-glib.c b/glib/dbus-glib.c
index 3153deef..5b30ce7a 100644
--- a/glib/dbus-glib.c
+++ b/glib/dbus-glib.c
@@ -26,6 +26,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include "dbus-gtest.h"
#include "dbus-gutils.h"
+#include "dbus-gobject.h"
#include <string.h>
#include <libintl.h>
@@ -149,41 +150,6 @@ dbus_g_error_quark (void)
return quark;
}
-#include "dbus-glib-error-switch.h"
-
-/**
- * Set a GError return location from a D-BUS error name and message.
- * This function should only be used in the implementation of service
- * methods.
- *
- * @param gerror location to store a GError, or #NULL
- * @param name the D-BUS error name
- * @param msg the D-BUS error detailed message
- */
-void
-dbus_g_error_set (GError **gerror,
- const char *name,
- const char *msg)
-{
- int code;
- g_return_if_fail (name != NULL);
- g_return_if_fail (msg != NULL);
-
- code = dbus_error_to_gerror_code (name);
- if (code == DBUS_GERROR_REMOTE_EXCEPTION)
- g_set_error (gerror, DBUS_GERROR,
- code,
- "%s%c%s",
- msg,
- '\0',
- name);
- else
- g_set_error (gerror, DBUS_GERROR,
- code,
- "%s",
- msg);
-}
-
/**
* Determine whether D-BUS error name for a remote exception matches
* the given name. This function is intended to be invoked on a
@@ -463,7 +429,7 @@ _dbus_glib_test (const char *test_data_dir)
dbus_error_init (&err);
dbus_set_error_const (&err, DBUS_ERROR_NO_MEMORY, "Out of memory!");
- dbus_g_error_set (&gerror, err.name, err.message);
+ dbus_set_g_error (&gerror, &err);
g_assert (gerror != NULL);
g_assert (gerror->domain == DBUS_GERROR);
g_assert (gerror->code == DBUS_GERROR_NO_MEMORY);
@@ -472,13 +438,6 @@ _dbus_glib_test (const char *test_data_dir)
dbus_error_init (&err);
g_clear_error (&gerror);
- dbus_g_error_set (&gerror, "com.example.Foo.BlahFailed", "blah failed");
- g_assert (gerror != NULL);
- g_assert (gerror->domain == DBUS_GERROR);
- g_assert (gerror->code == DBUS_GERROR_REMOTE_EXCEPTION);
- g_assert (dbus_g_error_has_name (gerror, "com.example.Foo.BlahFailed"));
- g_assert (!strcmp (gerror->message, "blah failed"));
-
return TRUE;
}
diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c
index 6d3b56c8..9d45ca0e 100644
--- a/glib/dbus-gmain.c
+++ b/glib/dbus-gmain.c
@@ -28,6 +28,7 @@
#include "dbus-gtest.h"
#include "dbus-gutils.h"
#include "dbus-gvalue.h"
+#include "dbus-gobject.h"
#include "dbus-gvalue-utils.h"
#include <string.h>
@@ -720,7 +721,7 @@ dbus_g_bus_get (DBusBusType type,
connection = dbus_bus_get (type, &derror);
if (connection == NULL)
{
- dbus_g_error_set (error, derror.name, derror.message);
+ dbus_set_g_error (error, &derror);
dbus_error_free (&derror);
return NULL;
}
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
diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c
index 90798b19..daf9bc8e 100644
--- a/glib/dbus-gparser.c
+++ b/glib/dbus-gparser.c
@@ -23,6 +23,7 @@
#include "dbus-gparser.h"
#include "dbus/dbus-glib-lowlevel.h"
#include "dbus-gidl.h"
+#include "dbus-gobject.h"
#include "dbus/dbus-signature.h"
#include <string.h>
@@ -474,7 +475,7 @@ validate_signature (const char *str,
if (!dbus_signature_validate (str, &derror))
{
- dbus_g_error_set (error, derror.name, derror.message);
+ dbus_set_g_error (&derror, error);
return FALSE;
}
return TRUE;
diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c
index 9ea4c16c..91cda82f 100644
--- a/glib/dbus-gproxy.c
+++ b/glib/dbus-gproxy.c
@@ -818,7 +818,7 @@ get_name_owner (DBusConnection *connection,
error:
g_assert (dbus_error_is_set (&derror));
- dbus_g_error_set (error, derror.name, derror.message);
+ dbus_set_g_error (error, &derror);
dbus_error_free (&derror);
out:
@@ -2009,14 +2009,14 @@ dbus_g_pending_call_end_valist (DBusGConnection *connection,
break;
case DBUS_MESSAGE_TYPE_ERROR:
dbus_set_error_from_message (&derror, reply);
- dbus_g_error_set (error, derror.name, derror.message);
+ dbus_set_g_error (error, &derror);
dbus_error_free (&derror);
goto out;
break;
default:
dbus_set_error (&derror, DBUS_ERROR_FAILED,
"Reply was neither a method return nor an exception");
- dbus_g_error_set (error, derror.name, derror.message);
+ dbus_set_g_error (error, &derror);
dbus_error_free (&derror);
goto out;
break;
diff --git a/test/glib/Makefile.am b/test/glib/Makefile.am
index 77ee1906..04d9c644 100644
--- a/test/glib/Makefile.am
+++ b/test/glib/Makefile.am
@@ -61,7 +61,7 @@ my-object-marshal.h: Makefile my-object-marshal.list
CLEANFILES = $(BUILT_SOURCES)
-test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
+test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la $(DBUS_GLIB_THREADS_LIBS)
else
### not building tests
diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c
index e8cb74af..fd71d743 100644
--- a/test/glib/test-dbus-glib.c
+++ b/test/glib/test-dbus-glib.c
@@ -441,7 +441,8 @@ main (int argc, char **argv)
if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID) != FALSE)
lose ("ThrowError call unexpectedly succeeded!");
if (!dbus_g_error_has_name (error, "org.freedesktop.DBus.Tests.MyObject.Foo"))
- lose ("ThrowError call returned unexpected error %s", dbus_g_error_get_name (error));
+ lose ("ThrowError call returned unexpected error \"%s\": %s", dbus_g_error_get_name (error),
+ error->message);
g_print ("ThrowError failed (as expected) returned error: %s\n", error->message);
g_clear_error (&error);
@@ -490,6 +491,13 @@ main (int argc, char **argv)
if (v_UINT32_2 != 43)
lose ("(wrapped) increment call returned %d, should be 43", v_UINT32_2);
+ v_UINT32_2 = 0;
+ if (!org_freedesktop_DBus_Tests_MyObject_async_increment (proxy, 42, &v_UINT32_2, &error))
+ lose_gerror ("Failed to complete (wrapped) AsyncIncrement call", error);
+
+ if (v_UINT32_2 != 43)
+ lose ("(wrapped) async increment call returned %d, should be 43", v_UINT32_2);
+
g_print ("Calling (wrapped) throw_error\n");
if (org_freedesktop_DBus_Tests_MyObject_throw_error (proxy, &error) != FALSE)
lose ("(wrapped) ThrowError call unexpectedly succeeded!");
@@ -497,6 +505,12 @@ main (int argc, char **argv)
g_print ("(wrapped) ThrowError failed (as expected) returned error: %s\n", error->message);
g_clear_error (&error);
+ if (org_freedesktop_DBus_Tests_MyObject_async_throw_error (proxy, &error) != FALSE)
+ lose ("(wrapped) AsyncThrowError call unexpectedly succeeded!");
+
+ g_print ("(wrapped) AsyncThrowError failed (as expected) returned error: %s\n", error->message);
+ g_clear_error (&error);
+
g_print ("Calling (wrapped) uppercase\n");
if (!org_freedesktop_DBus_Tests_MyObject_uppercase (proxy, "foobar", &v_STRING_2, &error))
lose_gerror ("Failed to complete (wrapped) Uppercase call", error);
diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c
index 9d5dfcc8..84b57c68 100644
--- a/test/glib/test-service-glib.c
+++ b/test/glib/test-service-glib.c
@@ -44,7 +44,9 @@ typedef enum
MY_OBJECT_ERROR_BAR
} MyObjectError;
-#define MY_OBJECT_ERROR my_object_error_quark ()
+#define MY_OBJECT_ERROR (my_object_error_quark ())
+
+#define MY_TYPE_ERROR (my_object_error_get_type ())
gboolean my_object_do_nothing (MyObject *obj, GError **error);
@@ -85,10 +87,16 @@ gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
gboolean my_object_terminate (MyObject *obj, GError **error);
+gboolean my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
+
+gboolean my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context);
+
#include "test-service-glib-glue.h"
GQuark my_object_error_quark (void);
+GType my_object_error_get_type (void);
+
/* Properties */
enum
{
@@ -231,6 +239,30 @@ my_object_error_quark (void)
return quark;
}
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+my_object_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+
+ ENUM_ENTRY (MY_OBJECT_ERROR_FOO, "Foo"),
+ ENUM_ENTRY (MY_OBJECT_ERROR_BAR, "Bar"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static ("MyObjectError", values);
+ }
+
+ return etype;
+}
+
static GObject *obj;
static GObject *obj2;
@@ -250,9 +282,11 @@ my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
gboolean
my_object_throw_error (MyObject *obj, GError **error)
{
- dbus_g_error_set (error,
- "org.freedesktop.DBus.Tests.MyObject.Foo",
- "this method always loses");
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "%s",
+ "this method always loses");
return FALSE;
}
@@ -464,6 +498,53 @@ my_object_emit_signal2 (MyObject *obj, GError **error)
return TRUE;
}
+typedef struct {
+ gint32 x;
+ DBusGMethodInvocation *context;
+} IncrementData;
+
+static gboolean
+do_async_increment (IncrementData *data)
+{
+ gint32 newx = data->x + 1;
+ dbus_g_method_return (data->context, newx);
+ g_free (data);
+ return FALSE;
+}
+
+gboolean
+my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context)
+{
+ IncrementData *data = g_new0 (IncrementData, 1);
+ data->x = x;
+ data->context = context;
+ g_idle_add ((GSourceFunc)do_async_increment, data);
+ return TRUE;
+}
+
+static gboolean
+do_async_error (IncrementData *data)
+{
+ GError *error;
+ error = g_error_new (MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "%s",
+ "this method always loses");
+ dbus_g_method_return_error (data->context, error);
+ g_free (data);
+ return FALSE;
+}
+
+gboolean
+my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context)
+{
+ IncrementData *data = g_new0(IncrementData, 1);
+ data->context = context;
+ g_idle_add ((GSourceFunc)do_async_error, data);
+ return TRUE;
+}
+
+
static GMainLoop *loop;
gboolean
@@ -484,6 +565,14 @@ main (int argc, char **argv)
guint32 request_name_ret;
g_type_init ();
+ g_thread_init (NULL); dbus_g_thread_init ();
+
+ dbus_g_object_type_install_info (MY_TYPE_OBJECT,
+ &dbus_glib_my_object_object_info);
+
+ dbus_g_error_domain_register (MY_OBJECT_ERROR,
+ NULL,
+ MY_TYPE_ERROR);
g_printerr ("Launching test-service-glib\n");
@@ -506,8 +595,6 @@ main (int argc, char **argv)
obj = g_object_new (MY_TYPE_OBJECT, NULL);
obj2 = g_object_new (MY_TYPE_OBJECT, NULL);
- dbus_g_object_type_install_info (MY_TYPE_OBJECT,
- &dbus_glib_my_object_object_info);
dbus_g_connection_register_g_object (connection,
"/org/freedesktop/DBus/Tests/MyTestObject",
obj);
diff --git a/test/glib/test-service-glib.xml b/test/glib/test-service-glib.xml
index 83240b47..58058626 100644
--- a/test/glib/test-service-glib.xml
+++ b/test/glib/test-service-glib.xml
@@ -77,6 +77,16 @@
<method name="IncrementVal">
</method>
+ <method name="AsyncIncrement">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="x" />
+ <arg type="u" direction="out" />
+ </method>
+
+ <method name="AsyncThrowError">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+
<method name="GetVal">
<arg type="u" direction="out" />
</method>