summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dbus/dbus-binding-tool-glib.c48
-rw-r--r--dbus/dbus-glib.h2
-rw-r--r--dbus/dbus-gobject.c412
-rw-r--r--test/core/Makefile.am4
-rw-r--r--test/core/my-object.c853
-rw-r--r--test/core/my-object.h118
-rw-r--r--test/core/test-dbus-glib.c286
-rw-r--r--test/core/test-service-glib.c832
-rw-r--r--test/core/test-service-glib.xml7
9 files changed, 1664 insertions, 898 deletions
diff --git a/dbus/dbus-binding-tool-glib.c b/dbus/dbus-binding-tool-glib.c
index adede27..7e280f6 100644
--- a/dbus/dbus-binding-tool-glib.c
+++ b/dbus/dbus-binding-tool-glib.c
@@ -40,2 +40,6 @@
+/* Remember to grep for ->format_version in the code if you change this,
+ * most changes should be in dbus-gobject.c. */
+#define FORMAT_VERSION 1
+
#define MARSHAL_PREFIX "dbus_glib_marshal_"
@@ -491,6 +495,5 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
- if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
- channel, error, data->prefix))
- goto io_lose;
- WRITE_OR_LOSE (" 0,\n");
+ if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = { %d,\n",
+ channel, error, data->prefix, FORMAT_VERSION))
+ goto io_lose;
if (!write_printf_to_iochannel (" dbus_glib_%s_methods,\n", channel, error, data->prefix))
@@ -738,9 +741,32 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
PropertyInfo *prop;
-
- prop = tmp->data;
-
- g_string_append (data->property_blob, interface_info_get_name (interface));
- g_string_append_c (data->property_blob, '\0');
- g_string_append (data->property_blob, property_info_get_name (prop));
- g_string_append_c (data->property_blob, '\0');
+ PropertyAccessFlags access_flags;
+ const char *access_string;
+ char *uscored;
+
+ prop = tmp->data;
+
+ access_flags = property_info_get_access (prop);
+ if ((access_flags & PROPERTY_READ) && (access_flags & PROPERTY_WRITE))
+ access_string = "readwrite";
+ else if (access_flags & PROPERTY_READ)
+ access_string = "read";
+ else if (access_flags & PROPERTY_WRITE)
+ access_string = "write";
+ else
+ continue;
+
+ /* We append both in the blob so we have to malloc() less when processing
+ * properties */
+ uscored = _dbus_gutils_wincaps_to_uscore (property_info_get_name (prop));
+
+ g_string_append (data->property_blob, interface_info_get_name (interface));
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, property_info_get_name (prop));
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, uscored);
+ g_string_append_c (data->property_blob, '\0');
+ g_string_append (data->property_blob, access_string);
+ g_string_append_c (data->property_blob, '\0');
+
+ g_free (uscored);
}
diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h
index 664e89f..a3a3597 100644
--- a/dbus/dbus-glib.h
+++ b/dbus/dbus-glib.h
@@ -152,2 +152,4 @@ struct _DBusGObjectInfo
+void dbus_glib_global_set_disable_legacy_property_access (void);
+
void dbus_g_object_type_install_info (GType object_type,
diff --git a/dbus/dbus-gobject.c b/dbus/dbus-gobject.c
index ec93ad4..1755f2c 100644
--- a/dbus/dbus-gobject.c
+++ b/dbus/dbus-gobject.c
@@ -44,2 +44,4 @@ typedef struct
static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
+/* See comments in check_property_access */
+static gboolean disable_legacy_property_access = FALSE;
static GHashTable *marshal_table = NULL;
@@ -47,2 +49,19 @@ static GData *error_metadata = NULL;
+/* Ugly yes - but we have to accept strings from both formats */
+static gboolean
+compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
+{
+ guint i;
+
+ for (i = 0; a[i] && b[i]; i++)
+ {
+ if ((a[i] == '-' && b[i] == '_')
+ || (a[i] == '_' && b[i] == '-'))
+ continue;
+ if (a[i] != b[i])
+ return FALSE;
+ }
+ return (a[i] == '\0') && (b[i] == '\0');
+}
+
static char*
@@ -272,3 +291,3 @@ method_output_signature_from_object_info (const DBusGObjectInfo *object,
static const char *
-propsig_iterate (const char *data, const char **iface, const char **name)
+signal_iterate (const char *data, const char **iface, const char **name)
{
@@ -282,2 +301,104 @@ propsig_iterate (const char *data, const char **iface, const char **name)
+static const char *
+property_iterate (const char *data,
+ int format_version,
+ const char **iface,
+ const char **exported_name,
+ const char **name_uscored,
+ const char **access_type)
+{
+ *iface = data;
+
+ data = string_table_next (data);
+ *exported_name = data;
+
+ data = string_table_next (data);
+ if (format_version == 1)
+ {
+ *name_uscored = data;
+ data = string_table_next (data);
+ *access_type = data;
+ return string_table_next (data);
+ }
+ else
+ {
+ /* This tells the caller they need to compute it */
+ *name_uscored = NULL;
+ /* We don't know here, however note that we will still check against the
+ * readable/writable flags from GObject's metadata.
+ */
+ *access_type = "readwrite";
+ return data;
+ }
+}
+
+/**
+ * property_info_from_object_info:
+ * @object: introspection data
+ * @interface_name: (allow-none): Expected interface name, or %NULL for any
+ * @property_name: Expected property name (can use "-" or "_" as separator)
+ * @access_type: (out): Can be one of "read", "write", "readwrite"
+ *
+ * Look up property introspection data for the given interface/name pair.
+ *
+ * Returns: %TRUE if property was found
+ */
+static gboolean
+property_info_from_object_info (const DBusGObjectInfo *object,
+ const char *interface_name,
+ const char *property_name,
+ const char **access_type)
+{
+ const char *properties_iter;
+
+ properties_iter = object->exported_properties;
+ while (properties_iter != NULL && *properties_iter)
+ {
+ const char *cur_interface_name;
+ const char *cur_property_name;
+ const char *cur_uscore_property_name;
+ const char *cur_access_type;
+
+
+ properties_iter = property_iterate (properties_iter, object->format_version,
+ &cur_interface_name, &cur_property_name,
+ &cur_uscore_property_name, &cur_access_type);
+
+ if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
+ continue;
+
+ /* This big pile of ugly is necessary to support the matrix resulting from multiplying
+ * (v0 data, v1 data) * (FooBar, foo-bar)
+ * In v1 data we have both forms of string, so we do a comparison against both without
+ * having to malloc.
+ * For v0 data, we need to reconstruct the foo-bar form.
+ *
+ * Adding to the complexity is that we *also* have to ignore the distinction between
+ * '-' and '_', because g_object_{get,set} does.
+ */
+ /* First, compare against the primary property name - no malloc required */
+ if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
+ {
+ if (cur_uscore_property_name != NULL
+ && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
+ continue;
+ else
+ {
+ /* v0 metadata, construct uscore */
+ char *tmp_uscored;
+ gboolean matches;
+ tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
+ matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
+ g_free (tmp_uscored);
+ if (!matches)
+ continue;
+ }
+ }
+
+ *access_type = cur_access_type;
+ return TRUE;
+ }
+ return FALSE;
+}
+
static GQuark
@@ -292,7 +413,13 @@ dbus_g_object_type_dbus_metadata_quark (void)
-static GList *
-lookup_object_info (GObject *object)
+/* Iterator function should return FALSE to stop iteration, TRUE to continue */
+typedef gboolean (*ForeachObjectInfoFn) (const DBusGObjectInfo *info,
+ GType gtype,
+ gpointer user_data);
+
+static void
+foreach_object_info (GObject *object,
+ ForeachObjectInfoFn callback,
+ gpointer user_data)
{
GType *interfaces, *p;
- GList *info_list = NULL;
const DBusGObjectInfo *info;
@@ -306,3 +433,6 @@ lookup_object_info (GObject *object)
if (info != NULL && info->format_version >= 0)
- info_list = g_list_prepend (info_list, (gpointer) info);
+ {
+ if (!callback (info, *p, user_data))
+ break;
+ }
}
@@ -315,9 +445,28 @@ lookup_object_info (GObject *object)
if (info != NULL && info->format_version >= 0)
- info_list = g_list_prepend (info_list, (gpointer) info);
+ {
+ if (!callback (info, classtype, user_data))
+ break;
+ }
}
- /* if needed only:
- return g_list_reverse (info_list);
- */
-
+}
+
+static gboolean
+lookup_object_info_cb (const DBusGObjectInfo *info,
+ GType gtype,
+ gpointer user_data)
+{
+ GList **list = (GList **) user_data;
+
+ *list = g_list_prepend (*list, (gpointer) info);
+ return TRUE;
+}
+
+static GList *
+lookup_object_info (GObject *object)
+{
+ GList *info_list = NULL;
+
+ foreach_object_info (object, lookup_object_info_cb, &info_list);
+
return info_list;
@@ -325,2 +474,52 @@ lookup_object_info (GObject *object)
+typedef struct {
+ const char *iface;
+ const DBusGObjectInfo *info;
+ gboolean fallback;
+ GType iface_type;
+} LookupObjectInfoByIfaceData;
+
+static gboolean
+lookup_object_info_by_iface_cb (const DBusGObjectInfo *info,
+ GType gtype,
+ gpointer user_data)
+{
+ LookupObjectInfoByIfaceData *lookup_data = (LookupObjectInfoByIfaceData *) user_data;
+
+ /* If interface is not specified, choose the first info */
+ if (lookup_data->fallback && (!lookup_data->iface || strlen (lookup_data->iface) == 0))
+ {
+ lookup_data->info = info;
+ lookup_data->iface_type = gtype;
+ }
+ else if (info->exported_properties && !strcmp (info->exported_properties, lookup_data->iface))
+ {
+ lookup_data->info = info;
+ lookup_data->iface_type = gtype;
+ }
+
+ return !lookup_data->info;
+}
+
+static const DBusGObjectInfo *
+lookup_object_info_by_iface (GObject *object,
+ const char *iface,
+ gboolean fallback,
+ GType *out_iface_type)
+{
+ LookupObjectInfoByIfaceData data;
+
+ data.iface = iface;
+ data.info = NULL;
+ data.fallback = fallback;
+ data.iface_type = 0;
+
+ foreach_object_info (object, lookup_object_info_by_iface_cb, &data);
+
+ if (out_iface_type && data.info)
+ *out_iface_type = data.iface_type;
+
+ return data.info;
+}
+
static void
@@ -445,3 +644,6 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
{
+ const char *iface;
const char *propname;
+ const char *propname_uscore;
+ const char *access_type;
GParamSpec *spec;
@@ -452,19 +654,27 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
- propname = properties->data;
spec = NULL;
- s = _dbus_gutils_wincaps_to_uscore (propname);
+ property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
- spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+ if (!propname_uscore)
+ {
+ char *s = _dbus_gutils_wincaps_to_uscore (propname);
+ spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+ g_free (s);
+ }
+ else
+ {
+ spec = g_object_class_find_property (g_type_class_peek (data->gtype), propname_uscore);
+ }
g_assert (spec != NULL);
- g_free (s);
-
+
dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
g_assert (dbus_type != NULL);
-
- can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
- (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
-
+
+ can_set = strcmp (access_type, "readwrite") == 0
+ && ((spec->flags & G_PARAM_WRITABLE) != 0
+ && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
+
can_get = (spec->flags & G_PARAM_READABLE) != 0;
-
+
if (can_set || can_get)
@@ -488,6 +698,4 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
}
-
- g_free (dbus_type);
- g_string_append (xml, " </property>\n");
+ g_free (dbus_type);
}
@@ -558,3 +766,3 @@ introspect_interfaces (GObject *object, GString *xml)
- propsig = propsig_iterate (propsig, &iface, &signame);
+ propsig = signal_iterate (propsig, &iface, &signame);
@@ -569,9 +777,11 @@ introspect_interfaces (GObject *object, GString *xml)
const char *propname;
+ const char *propname_uscore;
+ const char *access_type;
- propsig = propsig_iterate (propsig, &iface, &propname);
+ propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
values = lookup_values (interfaces, iface);
- values->properties = g_slist_prepend (values->properties, (gpointer) propname);
+ values->properties = g_slist_prepend (values->properties, (gpointer)iface);
}
-
+
memset (&data, 0, sizeof (data));
@@ -1273,2 +1483,66 @@ invoke_object_method (GObject *object,
+static gboolean
+check_property_access (DBusConnection *connection,
+ DBusMessage *message,
+ GObject *object,
+ const char *wincaps_propiface,
+ const char *requested_propname,
+ const char *uscore_propname,
+ gboolean is_set)
+{
+ const DBusGObjectInfo *object_info;
+ const char *access_type;
+ DBusMessage *ret;
+
+ if (!is_set && !disable_legacy_property_access)
+ return TRUE;
+
+ object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
+ if (!object_info)
+ {
+ ret = dbus_message_new_error_printf (message,
+ DBUS_ERROR_ACCESS_DENIED,
+ "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
+ wincaps_propiface,
+ requested_propname);
+ dbus_connection_send (connection, ret, NULL);
+ dbus_message_unref (ret);
+ return FALSE;
+ }
+
+ /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
+ * reasons we accept both.
+ */
+ if (object_info
+ && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
+ || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
+ {
+ ret = dbus_message_new_error_printf (message,
+ DBUS_ERROR_ACCESS_DENIED,
+ "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
+ requested_propname,
+ wincaps_propiface);
+ dbus_connection_send (connection, ret, NULL);
+ dbus_message_unref (ret);
+ return FALSE;
+ }
+
+ if (strcmp (access_type, "readwrite") == 0)
+ return TRUE;
+ else if (is_set ? strcmp (access_type, "read") == 0
+ : strcmp (access_type, "write") == 0)
+ {
+ ret = dbus_message_new_error_printf (message,
+ DBUS_ERROR_ACCESS_DENIED,
+ "Property \"%s\" of interface \"%s\" is not %s",
+ requested_propname,
+ wincaps_propiface,
+ is_set ? "settable" : "readable");
+ dbus_connection_send (connection, ret, NULL);
+ dbus_message_unref (ret);
+ return FALSE;
+ }
+ return TRUE;
+}
+
static DBusHandlerResult
@@ -1283,4 +1557,4 @@ gobject_message_function (DBusConnection *connection,
char *s;
- const char *wincaps_propname;
- /* const char *wincaps_propiface; */
+ const char *requested_propname;
+ const char *wincaps_propiface;
DBusMessageIter iter;
@@ -1301,3 +1575,4 @@ gobject_message_function (DBusConnection *connection,
/* If no metainfo, we can still do properties and signals
- * via standard GLib introspection
+ * via standard GLib introspection. Note we do now check
+ * property access against the metainfo if available.
*/
@@ -1324,6 +1599,4 @@ gobject_message_function (DBusConnection *connection,
}
- /* We never use the interface name; if we did, we'd need to
- * remember that it can be empty string for "pick one for me"
- */
- /* dbus_message_iter_get_basic (&iter, &wincaps_propiface); */
+
+ dbus_message_iter_get_basic (&iter, &wincaps_propiface);
dbus_message_iter_next (&iter);
@@ -1335,9 +1608,15 @@ gobject_message_function (DBusConnection *connection,
}
- dbus_message_iter_get_basic (&iter, &wincaps_propname);
+
+ dbus_message_iter_get_basic (&iter, &requested_propname);
dbus_message_iter_next (&iter);
-
- s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
- s);
+ s = _dbus_gutils_wincaps_to_uscore (requested_propname);
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), s);
+
+ if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
+ {
+ g_free (s);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
@@ -1366,7 +1645,2 @@ gobject_message_function (DBusConnection *connection,
}
- else
- {
- g_assert_not_reached ();
- ret = NULL;
- }
@@ -1381,2 +1655,12 @@ gobject_message_function (DBusConnection *connection,
}
+ else
+ {
+ DBusMessage *ret;
+
+ ret = dbus_message_new_error_printf (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "No such property %s", requested_propname);
+ dbus_connection_send (connection, ret, NULL);
+ dbus_message_unref (ret);
+ }
@@ -1499,4 +1783,4 @@ export_signals (DBusGConnection *connection, const GList *info_list, GObject *ob
- sigdata = propsig_iterate (sigdata, &iface, &signame);
-
+ sigdata = signal_iterate (sigdata, &iface, &signame);
+
s = _dbus_gutils_wincaps_to_uscore (signame);
@@ -1659,2 +1943,28 @@ dbus_g_error_info_free (gpointer p)
/**
+ * dbus_glib_global_set_disable_legacy_property_access:
+ *
+ * Historically, DBus-GLib allowed read/write access to any property
+ * regardless of the access flags specified in the introspection XML,
+ * and regardless of the DBus interface given.
+ *
+ * As of version 0.88, DBus-GLib by default allows read-only access to
+ * every GObject property of an object exported to the bus, regardless
+ * of whether or not the property is listed in the type info installed
+ * with dbus_g_object_type_install_info() and regardless of whether
+ * the correct interface is specified. Write access is denied.
+ *
+ * After calling this method, it will be required that the property is
+ * exported on the given interface, and even read-only access will be
+ * checked. This method changes behavior globally for the entire
+ * process.
+ *
+ * Since: 0.88
+ */
+void
+dbus_glib_global_set_disable_legacy_property_access (void)
+{
+ disable_legacy_property_access = TRUE;
+}
+
+/**
* dbus_g_object_type_install_info:
@@ -2312,3 +2622,3 @@ _dbus_gobject_test (const char *test_data_dir)
g_assert (*sigdata != '\0');
- sigdata = propsig_iterate (sigdata, &iface, &signame);
+ sigdata = signal_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
@@ -2316,3 +2626,3 @@ _dbus_gobject_test (const char *test_data_dir)
g_assert (*sigdata != '\0');
- sigdata = propsig_iterate (sigdata, &iface, &signame);
+ sigdata = signal_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
@@ -2320,3 +2630,3 @@ _dbus_gobject_test (const char *test_data_dir)
g_assert (*sigdata != '\0');
- sigdata = propsig_iterate (sigdata, &iface, &signame);
+ sigdata = signal_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
@@ -2324,3 +2634,3 @@ _dbus_gobject_test (const char *test_data_dir)
g_assert (*sigdata != '\0');
- sigdata = propsig_iterate (sigdata, &iface, &signame);
+ sigdata = signal_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
@@ -2328,3 +2638,3 @@ _dbus_gobject_test (const char *test_data_dir)
g_assert (*sigdata == '\0');
-
+
diff --git a/test/core/Makefile.am b/test/core/Makefile.am
index 7ffda78..6216afe 100644
--- a/test/core/Makefile.am
+++ b/test/core/Makefile.am
@@ -52,3 +52,5 @@ test_service_glib_SOURCES= \
my-object-marshal.c \
- test-service-glib.c
+ my-object.c \
+ my-object.h \
+ test-service-glib.c
diff --git a/test/core/my-object.c b/test/core/my-object.c
new file mode 100644
index 0000000..a633b05
--- /dev/null
+++ b/test/core/my-object.c
@@ -0,0 +1,853 @@
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include "my-object.h"
+#include "my-object-marshal.h"
+
+#include "test-service-glib-glue.h"
+
+/* Properties */
+enum
+{
+ PROP_0,
+ PROP_THIS_IS_A_STRING,
+ PROP_NO_TOUCHING,
+ PROP_SUPER_STUDLY,
+ PROP_SHOULD_BE_HIDDEN
+};
+
+enum
+{
+ FROBNICATE,
+ SIG0,
+ SIG1,
+ SIG2,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
+
+static void
+my_object_finalize (GObject *object)
+{
+ MyObject *mobject = MY_OBJECT (object);
+
+ g_free (mobject->this_is_a_string);
+
+ (G_OBJECT_CLASS (my_object_parent_class)->finalize) (object);
+}
+
+static void
+my_object_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MyObject *mobject;
+
+ mobject = MY_OBJECT (object);
+
+ switch (prop_id)
+ {
+ case PROP_THIS_IS_A_STRING:
+ g_free (mobject->this_is_a_string);
+ mobject->this_is_a_string = g_value_dup_string (value);
+ break;
+
+ case PROP_NO_TOUCHING:
+ mobject->notouching = g_value_get_uint (value);
+ break;
+
+ case PROP_SUPER_STUDLY:
+ mobject->super_studly = g_value_get_double (value);
+ break;
+
+ case PROP_SHOULD_BE_HIDDEN:
+ mobject->should_be_hidden = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+my_object_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MyObject *mobject;
+
+ mobject = MY_OBJECT (object);
+
+ switch (prop_id)
+ {
+ case PROP_THIS_IS_A_STRING:
+ g_value_set_string (value, mobject->this_is_a_string);
+ break;
+
+ case PROP_NO_TOUCHING:
+ g_value_set_uint (value, mobject->notouching);
+ break;
+
+ case PROP_SUPER_STUDLY:
+ g_value_set_double (value, mobject->super_studly);
+ break;
+
+ case PROP_SHOULD_BE_HIDDEN:
+ g_value_set_boolean (value, mobject->should_be_hidden);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+my_object_init (MyObject *obj)
+{
+ obj->val = 0;
+ obj->notouching = 42;
+}
+
+static void
+my_object_class_init (MyObjectClass *mobject_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (mobject_class);
+
+ dbus_g_object_type_install_info (MY_TYPE_OBJECT,
+ &dbus_glib_my_object_object_info);
+
+ gobject_class->finalize = my_object_finalize;
+ gobject_class->set_property = my_object_set_property;
+ gobject_class->get_property = my_object_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_THIS_IS_A_STRING,
+ g_param_spec_string ("this_is_a_string",
+ _("Sample string"),
+ _("Example of a string property"),
+ "default value",
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_NO_TOUCHING,
+ g_param_spec_uint ("no_touching",
+ _("Don't touch"),
+ _("Example of a readonly property (for export)"),
+ 0, 100, 42,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_SUPER_STUDLY,
+ g_param_spec_double ("super-studly",
+ _("In Studly Caps"),
+ _("Example of a StudlyCaps property"),
+ 0, 256, 128,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_SHOULD_BE_HIDDEN,
+ g_param_spec_boolean ("should-be-hidden",
+ _("A non-exported property"),
+ _("Example of a property we don't want exported"),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ signals[FROBNICATE] =
+ g_signal_new ("frobnicate",
+ G_OBJECT_CLASS_TYPE (mobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+
+ signals[SIG0] =
+ g_signal_new ("sig0",
+ G_OBJECT_CLASS_TYPE (mobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ my_object_marshal_VOID__STRING_INT_STRING,
+ G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
+
+ signals[SIG1] =
+ g_signal_new ("sig1",
+ G_OBJECT_CLASS_TYPE (mobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ my_object_marshal_VOID__STRING_BOXED,
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
+
+ signals[SIG2] =
+ g_signal_new ("sig2",
+ G_OBJECT_CLASS_TYPE (mobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
+}
+
+GQuark
+my_object_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string ("my_object_error");
+
+ 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"),
+ ENUM_ENTRY (MY_OBJECT_ERROR_MULTI_WORD, "Multi-word"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static ("MyObjectError", values);
+ }
+
+ return etype;
+}
+
+gboolean
+my_object_do_nothing (MyObject *obj, GError **error)
+{
+ return TRUE;
+}
+
+gboolean
+my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
+{
+ *ret = x +1;
+ return TRUE;
+}
+
+gint32
+my_object_increment_retval (MyObject *obj, gint32 x)
+{
+ return x + 1;
+}
+
+gint32
+my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
+{
+ if (x + 1 > 10)
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "%s",
+ "x is bigger than 9");
+ return FALSE;
+ }
+ return x + 1;
+}
+
+gboolean
+my_object_throw_error (MyObject *obj, GError **error)
+{
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "%s",
+ "this method always loses");
+ return FALSE;
+}
+
+gboolean
+my_object_throw_not_supported (MyObject *obj, GError **error)
+{
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_NOT_SUPPORTED,
+ "%s",
+ "this method always loses");
+ return FALSE;
+}
+
+gboolean
+my_object_throw_error_multi_word (MyObject *obj, GError **error)
+{
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_MULTI_WORD,
+ "%s",
+ "this method's error has a hyphen");
+ return FALSE;
+}
+
+gboolean
+my_object_throw_unregistered_error (MyObject *obj, GError **error)
+{
+ /* Unregistered errors shouldn't cause a dbus abort. See
+ * https://bugzilla.redhat.com/show_bug.cgi?id=581794
+ */
+ g_set_error (error, 0, 0,
+ "%s",
+ "this method always loses more");
+ return FALSE;
+}
+
+
+gboolean
+my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error)
+{
+ *ret = g_ascii_strup (str, -1);
+ return TRUE;
+}
+
+gboolean
+my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error)
+{
+ *d_ret = trouble + (x * 2);
+ *str_ret = g_ascii_strup (str, -1);
+ return TRUE;
+}
+
+gboolean
+my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error)
+{
+ *arg0 = 42;
+ *arg1 = g_strdup ("42");
+ *arg2 = -67;
+ *arg3 = 2;
+ *arg4 = 26;
+ *arg5 = "hello world"; /* Annotation specifies as const */
+ return TRUE;
+}
+
+gboolean
+my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error)
+{
+ GValue valstr = {0, };
+
+ g_value_init (&valstr, G_TYPE_STRING);
+ if (!g_value_transform (value, &valstr))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "couldn't transform value");
+ return FALSE;
+ }
+ *ret = g_value_dup_string (&valstr);
+ g_value_unset (&valstr);
+ return TRUE;
+}
+
+gboolean
+my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error)
+{
+ if (str[0] == '\0' || !g_ascii_isdigit (str[0])) {
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, str);
+ } else {
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, (int) g_ascii_strtoull (str, NULL, 10));
+ }
+ return TRUE;
+}
+
+gboolean
+my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error)
+{
+ *len_ret = array->len;
+ return TRUE;
+}
+
+gboolean
+my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **ret, GError **error)
+{
+ guint32 val;
+ GArray *array;
+
+ array = g_array_new (FALSE, TRUE, sizeof (guint32));
+
+ while (reqlen > 0) {
+ val = 42;
+ g_array_append_val (array, val);
+ val = 26;
+ g_array_append_val (array, val);
+ reqlen--;
+ }
+ val = 2;
+ g_array_append_val (array, val);
+ *ret = array;
+ return TRUE;
+}
+
+gboolean
+my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error)
+{
+ int len;
+ int i;
+
+ len = g_strv_length ((char**) in);
+
+ *out = g_new0 (char *, len + 1);
+ for (i = 0; i < len; i++)
+ {
+ (*out)[i] = g_ascii_strup (in[i], -1);
+ }
+ (*out)[i] = NULL;
+
+ return TRUE;
+}
+
+static void
+hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data)
+{
+ const char *keystr = key;
+ const GValue *value = val;
+ GValue *sval;
+ GHashTable *ret = user_data;
+
+ sval = g_new0 (GValue, 1);
+ g_value_init (sval, G_TYPE_STRING);
+ if (!g_value_transform (value, sval))
+ g_assert_not_reached ();
+
+ g_hash_table_insert (ret, g_strdup (keystr), sval);
+}
+
+static void
+unset_and_free_gvalue (gpointer val)
+{
+ g_value_unset (val);
+ g_free (val);
+}
+
+gboolean
+my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error)
+{
+ *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, unset_and_free_gvalue);
+ g_hash_table_foreach (vals, hash_foreach_stringify, *ret);
+ return TRUE;
+}
+
+gboolean
+my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error)
+{
+ char **strs;
+ GArray *ints;
+ guint v_UINT;
+
+ if (in->len != 2)
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid array len");
+ return FALSE;
+ }
+
+ strs = g_ptr_array_index (in, 0);
+ if (!*strs || strcmp (*strs, "foo"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string 0");
+ return FALSE;
+ }
+ strs++;
+ if (!*strs || strcmp (*strs, "bar"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string 1");
+ return FALSE;
+ }
+ strs++;
+ if (*strs)
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string array len in pos 0");
+ return FALSE;
+ }
+ strs = g_ptr_array_index (in, 1);
+ if (!*strs || strcmp (*strs, "baz"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string 0");
+ return FALSE;
+ }
+ strs++;
+ if (!*strs || strcmp (*strs, "whee"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string 1");
+ return FALSE;
+ }
+ strs++;
+ if (!*strs || strcmp (*strs, "moo"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string 2");
+ return FALSE;
+ }
+ strs++;
+ if (*strs)
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid string array len in pos 1");
+ return FALSE;
+ }
+
+ *ret = g_ptr_array_new ();
+
+ ints = g_array_new (TRUE, TRUE, sizeof (guint));
+ v_UINT = 10;
+ g_array_append_val (ints, v_UINT);
+ v_UINT = 42;
+ g_array_append_val (ints, v_UINT);
+ v_UINT = 27;
+ g_array_append_val (ints, v_UINT);
+ g_ptr_array_add (*ret, ints);
+
+ ints = g_array_new (TRUE, TRUE, sizeof (guint));
+ v_UINT = 30;
+ g_array_append_val (ints, v_UINT);
+ g_ptr_array_add (*ret, ints);
+ return TRUE;
+}
+
+gboolean
+my_object_objpath (MyObject *obj, const char *incoming, const char **outgoing, GError **error)
+{
+ if (strcmp (incoming, "/org/freedesktop/DBus/GLib/Tests/MyTestObject"))
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid incoming object");
+ return FALSE;
+ }
+ *outgoing = "/org/freedesktop/DBus/GLib/Tests/MyTestObject2";
+ return TRUE;
+}
+
+gboolean
+my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error)
+{
+ *objs = g_ptr_array_new ();
+
+ g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject"));
+ g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
+
+ return TRUE;
+}
+
+static void
+hash_foreach (gpointer key, gpointer val, gpointer user_data)
+{
+ const char *keystr = key;
+ const char *valstr = val;
+ guint *count = user_data;
+
+ *count += (strlen (keystr) + strlen (valstr));
+ g_print ("%s -> %s\n", keystr, valstr);
+}
+
+gboolean
+my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error)
+{
+ *len = 0;
+ g_hash_table_foreach (table, hash_foreach, len);
+ return TRUE;
+}
+
+gboolean
+my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error)
+{
+ if (invals->n_values != 3
+ || G_VALUE_TYPE (g_value_array_get_nth (invals, 0)) != G_TYPE_STRING
+ || G_VALUE_TYPE (g_value_array_get_nth (invals, 1)) != G_TYPE_UINT
+ || G_VALUE_TYPE (g_value_array_get_nth (invals, 2)) != G_TYPE_VALUE)
+ {
+ g_set_error (error,
+ MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "invalid incoming values");
+ return FALSE;
+ }
+ *outvals = g_value_array_new (2);
+ g_value_array_append (*outvals, NULL);
+ g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), G_TYPE_UINT);
+ g_value_set_uint (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+ g_value_get_uint (g_value_array_get_nth (invals, 1)) + 1);
+ g_value_array_append (*outvals, NULL);
+ g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), DBUS_TYPE_G_OBJECT_PATH);
+ g_value_set_boxed (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+ g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
+ return TRUE;
+}
+
+gboolean
+my_object_get_hash (MyObject *obj, GHashTable **ret, GError **error)
+{
+ GHashTable *table;
+
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (table, "foo", "bar");
+ g_hash_table_insert (table, "baz", "whee");
+ g_hash_table_insert (table, "cow", "crack");
+ *ret = table;
+ return TRUE;
+}
+
+gboolean
+my_object_increment_val (MyObject *obj, GError **error)
+{
+ obj->val++;
+ return TRUE;
+}
+
+gboolean
+my_object_get_val (MyObject *obj, guint *ret, GError **error)
+{
+ *ret = obj->val;
+ return TRUE;
+}
+
+gboolean
+my_object_get_value (MyObject *obj, guint *ret, GError **error)
+{
+ *ret = obj->val;
+ return TRUE;
+}
+
+gboolean
+my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
+{
+ GType t;
+ t = G_VALUE_TYPE(variant);
+ g_value_init (ret, t);
+ g_value_copy (variant, ret);
+
+ return TRUE;
+}
+
+gboolean
+my_object_echo_signature (MyObject *obj, const gchar *in, gchar **out, GError **error)
+{
+ *out = g_strdup (in);
+ return TRUE;
+}
+
+gboolean
+my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error)
+{
+ GArray *array;
+ int i;
+ int j;
+
+ j = 0;
+
+ array = (GArray *)g_value_get_boxed (variant);
+
+ for (i = 0; i <= 2; i++)
+ {
+ j = g_array_index (array, int, i);
+ if (j != i + 1)
+ goto error;
+ }
+
+ return TRUE;
+
+error:
+ *error = g_error_new (MY_OBJECT_ERROR,
+ MY_OBJECT_ERROR_FOO,
+ "Error decoding a variant of type ai (i + 1 = %i, j = %i)",
+ i, j + 1);
+ return FALSE;
+}
+
+
+typedef struct _HashAndString HashAndString;
+
+struct _HashAndString
+{
+ GHashTable *hash;
+ gchar* string;
+};
+
+static void
+hash_foreach_prepend_string (gpointer key, gpointer val, gpointer user_data)
+{
+ HashAndString *data = (HashAndString*) user_data;
+ gchar *in = (gchar*) val;
+ g_hash_table_insert (data->hash, g_strdup ((gchar*) key),
+ g_strjoin (" ", data->string, in, NULL));
+}
+
+
+static void
+hash_foreach_mangle_dict_of_strings (gpointer key, gpointer val, gpointer user_data)
+{
+ GHashTable *out = (GHashTable*) user_data;
+ GHashTable *in_dict = (GHashTable *) val;
+ HashAndString *data = g_new0 (HashAndString, 1);
+
+ data->string = (gchar*) key;
+ data->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+ g_hash_table_foreach (in_dict, hash_foreach_prepend_string, data);
+
+ g_hash_table_insert(out, g_strdup ((gchar*) key), data->hash);
+}
+
+gboolean
+my_object_dict_of_dicts (MyObject *obj, GHashTable *in,
+ GHashTable **out, GError **error)
+{
+ *out = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_hash_table_destroy);
+ g_hash_table_foreach (in, hash_foreach_mangle_dict_of_strings, *out);
+ return TRUE;
+}
+
+void
+my_object_dict_of_sigs (MyObject *obj,
+ GHashTable *dict,
+ DBusGMethodInvocation *context)
+{
+ dbus_g_method_return (context, dict);
+}
+
+void
+my_object_dict_of_objs (MyObject *obj,
+ GHashTable *dict,
+ DBusGMethodInvocation *context)
+{
+ dbus_g_method_return (context, dict);
+}
+
+gboolean
+my_object_emit_frobnicate (MyObject *obj, GError **error)
+{
+ g_signal_emit (obj, signals[FROBNICATE], 0, 42);
+ return TRUE;
+}
+
+gboolean
+my_object_emit_signals (MyObject *obj, GError **error)
+{
+ GValue val = {0, };
+
+ g_signal_emit (obj, signals[SIG0], 0, "foo", 22, "moo");
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "bar");
+ g_signal_emit (obj, signals[SIG1], 0, "baz", &val);
+ g_value_unset (&val);
+
+ return TRUE;
+}
+
+gboolean
+my_object_emit_signal2 (MyObject *obj, GError **error)
+{
+ GHashTable *table;
+
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (table, "baz", "cow");
+ g_hash_table_insert (table, "bar", "foo");
+ g_signal_emit (obj, signals[SIG2], 0, table);
+ g_hash_table_destroy (table);
+ 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;
+}
+
+void
+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);
+}
+
+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;
+}
+
+void
+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);
+}
+
+extern GMainLoop *loop;
+
+gboolean
+my_object_terminate (MyObject *obj, GError **error)
+{
+ g_main_loop_quit (loop);
+ return TRUE;
+}
+
+void
+my_object_unsafe_disable_legacy_property_access (MyObject *obj)
+{
+ dbus_glib_global_set_disable_legacy_property_access ();
+}
diff --git a/test/core/my-object.h b/test/core/my-object.h
new file mode 100644
index 0000000..28f8704
--- /dev/null
+++ b/test/core/my-object.h
@@ -0,0 +1,118 @@
+#ifndef __MY_OBJECT_H__
+#define __MY_OBJECT_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+typedef struct MyObject MyObject;
+typedef struct MyObjectClass MyObjectClass;
+
+GType my_object_get_type (void);
+
+struct MyObject
+{
+ GObject parent;
+ char *this_is_a_string;
+ guint notouching;
+ guint val;
+ gdouble super_studly;
+ gboolean should_be_hidden;
+};
+
+struct MyObjectClass
+{
+ GObjectClass parent;
+};
+
+#define MY_TYPE_OBJECT (my_object_get_type ())
+#define MY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject))
+#define MY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass))
+#define MY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT))
+#define MY_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT))
+#define MY_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass))
+
+typedef enum
+{
+ MY_OBJECT_ERROR_FOO,
+ MY_OBJECT_ERROR_BAR,
+ MY_OBJECT_ERROR_MULTI_WORD
+} MyObjectError;
+
+#define MY_OBJECT_ERROR (my_object_error_quark ())
+#define MY_TYPE_ERROR (my_object_error_get_type ())
+
+GQuark my_object_error_quark (void);
+GType my_object_error_get_type (void);
+
+gboolean my_object_do_nothing (MyObject *obj, GError **error);
+
+gboolean my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error);
+
+gint32 my_object_increment_retval (MyObject *obj, gint32 x);
+
+gint32 my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error);
+
+gboolean my_object_throw_error (MyObject *obj, GError **error);
+gboolean my_object_throw_not_supported (MyObject *obj, GError **error);
+gboolean my_object_throw_error_multi_word (MyObject *obj, GError **error);
+gboolean my_object_throw_unregistered_error (MyObject *obj, GError **error);
+
+gboolean my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error);
+
+gboolean my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error);
+
+gboolean my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error);
+
+gboolean my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error);
+gboolean my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **array, GError **error);
+
+gboolean my_object_many_stringify (MyObject *obj, GHashTable *vals, GHashTable **ret, GError **error);
+
+gboolean my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error);
+
+gboolean my_object_objpath (MyObject *obj, const char *in, const char **arg1, GError **error);
+
+gboolean my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error);
+
+gboolean my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error);
+gboolean my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error);
+
+gboolean my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error);
+
+gboolean my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error);
+
+gboolean my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error);
+
+gboolean my_object_get_hash (MyObject *obj, GHashTable **table, GError **error);
+
+gboolean my_object_increment_val (MyObject *obj, GError **error);
+
+gboolean my_object_get_val (MyObject *obj, guint *ret, GError **error);
+
+gboolean my_object_get_value (MyObject *obj, guint *ret, GError **error);
+
+gboolean my_object_emit_signals (MyObject *obj, GError **error);
+gboolean my_object_emit_signal2 (MyObject *obj, GError **error);
+
+gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
+
+gboolean my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error);
+gboolean my_object_echo_signature (MyObject *obj, const gchar *in, gchar **out, GError **error);
+
+gboolean my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error);
+
+gboolean my_object_dict_of_dicts (MyObject *obj, GHashTable *dict, GHashTable **ret, GError **error);
+
+void my_object_dict_of_sigs (MyObject *obj, GHashTable *dict, DBusGMethodInvocation *ctx);
+
+void my_object_dict_of_objs (MyObject *obj, GHashTable *dict, DBusGMethodInvocation *ctx);
+
+gboolean my_object_terminate (MyObject *obj, GError **error);
+
+void my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
+
+void my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context);
+
+void my_object_unsafe_disable_legacy_property_access (MyObject *obj);
+
+#endif
diff --git a/test/core/test-dbus-glib.c b/test/core/test-dbus-glib.c
index f32b2d4..d78ce58 100644
--- a/test/core/test-dbus-glib.c
+++ b/test/core/test-dbus-glib.c
@@ -270,3 +270,2 @@ increment_async_cb (DBusGProxy *proxy, guint val, GError *error, gpointer data)
-
static void
@@ -315,2 +314,3 @@ main (int argc, char **argv)
DBusGProxy *proxy2;
+ DBusGProxy *property_proxy;
char **name_list;
@@ -1579,3 +1579,6 @@ main (int argc, char **argv)
if (!node)
- lose_gerror ("Failed to parse introspection data: %s", error);
+ {
+ g_printerr ("===\n%s\n===\n", v_STRING_2);
+ lose_gerror ("Failed to parse introspection data: %s", error);
+ }
@@ -1597,5 +1600,6 @@ main (int argc, char **argv)
gboolean found_manyargs;
-
+ gboolean found_no_touching = FALSE;
+
found_myobject = TRUE;
-
+
found_manyargs = FALSE;
@@ -1614,2 +1618,19 @@ main (int argc, char **argv)
lose ("Missing method org.freedesktop.DBus.GLib.Tests.MyObject.ManyArgs");
+ for (elt = interface_info_get_properties (iface); elt; elt = elt->next)
+ {
+ PropertyInfo *prop = elt->data;
+
+ if (strcmp (property_info_get_name (prop), "no-touching") == 0)
+ {
+ if (property_info_get_access (prop) != PROPERTY_READ)
+ lose ("property no-touching had incorrect access %d", property_info_get_access (prop));
+ else
+ {
+ found_no_touching = TRUE;
+ break;
+ }
+ }
+ }
+ if (!found_no_touching)
+ lose ("didn't find property \"no-touching\" in org.freedesktop.DBus.GLib.Tests.MyObject");
}
@@ -1625,3 +1646,258 @@ main (int argc, char **argv)
g_free (v_STRING_2);
-
+
+ /* Properties tests */
+ property_proxy = dbus_g_proxy_new_from_proxy (proxy, DBUS_INTERFACE_PROPERTIES, NULL);
+ g_object_unref (proxy);
+ proxy = NULL;
+
+ g_print ("Calling GetProperty (1)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "this_is_a_string",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_STRING));
+ g_assert (!strcmp (g_value_get_string (&value), ""));
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling SetProperty (1)\n");
+ {
+ GValue value = {0,};
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, "testing value");
+ if (!dbus_g_proxy_call (property_proxy, "Set", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "this_is_a_string",
+ G_TYPE_VALUE, &value, G_TYPE_INVALID, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete SetProperty call", error);
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty of read-only property\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "no-touching",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty no-touching call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_UINT));
+ g_assert (g_value_get_uint (&value) == 42);
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling SetProperty (1)\n");
+ {
+ GValue value = {0,};
+ g_value_init (&value, G_TYPE_UINT);
+ g_value_set_uint (&value, 40);
+ if (dbus_g_proxy_call (property_proxy, "Set", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "no-touching",
+ G_TYPE_VALUE, &value, G_TYPE_INVALID, G_TYPE_INVALID))
+ lose ("Unexpected success from SetProperty call for read-only value \"no-touching\"");
+ g_clear_error (&error);
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty of read-only property (again)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "no-touching",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_UINT));
+ g_assert (g_value_get_uint (&value) == 42);
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty (2)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "this_is_a_string",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_STRING));
+ g_assert (!strcmp (g_value_get_string (&value), "testing value"));
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty: SuperStudly\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "SuperStudly",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty: super-studly\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "super-studly",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty: super_studly\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "super_studly",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed to complete GetProperty call", error);
+ g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty on unknown property\n");
+ {
+ GValue value = {0,};
+ if (dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "SomeUnknownProperty",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose ("Unexpected success for GetProperty call of unknown property");
+
+ g_clear_error (&error);
+ }
+
+ /* These two are expected to pass unless we call disable_legacy_property_access */
+
+ g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "should-be-hidden",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed GetProperty call of \"should-be-hidden\" property", error);
+ g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
+ g_assert (g_value_get_boolean (&value) == FALSE);
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "ShouldBeHidden",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed GetProperty call of \"ShouldBeHidden\" property", error);
+
+ g_value_unset (&value);
+ }
+
+ g_print ("Calling SetProperty on not-exported property (legacy enabled)\n");
+ {
+ GValue value = {0,};
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, TRUE);
+ if (dbus_g_proxy_call (property_proxy, "Set", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "should-be-hidden",
+ G_TYPE_VALUE, &value,
+ G_TYPE_INVALID, G_TYPE_INVALID))
+ lose ("Unexpected success from SetProperty call of \"should-be-hidden\" property");
+ g_value_unset (&value);
+ g_clear_error (&error);
+ }
+
+ g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
+ {
+ GValue value = {0,};
+ if (!dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "should-be-hidden",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose_gerror ("Failed GetProperty call of \"should-be-hidden\" property", error);
+ g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
+ g_assert (g_value_get_boolean (&value) == FALSE);
+ g_value_unset (&value);
+ }
+
+ /* Now, call disable_legacy_property_access */
+
+ g_assert (proxy == NULL);
+ proxy = dbus_g_proxy_new_for_name_owner (connection,
+ "org.freedesktop.DBus.GLib.TestService",
+ "/org/freedesktop/DBus/GLib/Tests/MyTestObject",
+ "org.freedesktop.DBus.GLib.Tests.MyObject",
+ &error);
+
+ if (!dbus_g_proxy_call (proxy, "UnsafeDisableLegacyPropertyAccess", &error,
+ G_TYPE_INVALID, G_TYPE_INVALID))
+ lose_gerror ("Failed to invoke UnsafeDisableLegacyPropertyAccess", error);
+
+ g_object_unref (proxy);
+ proxy = NULL;
+
+ g_print ("Calling GetProperty on not-exported property (legacy *disabled*)\n");
+ {
+ GValue value = {0,};
+ if (dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "should-be-hidden",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose ("Unexpected success from GetProperty call of \"should-be-hidden\" property");
+ g_clear_error (&error);
+ }
+
+ g_print ("Calling GetProperty on not-exported property (legacy *disabled*)\n");
+ {
+ GValue value = {0,};
+ if (dbus_g_proxy_call (property_proxy, "Get", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "ShouldBeHidden",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID))
+ lose ("Unexpected success from GetProperty call of \"ShouldBeHidden\" property");
+ g_clear_error (&error);
+ }
+
+ g_print ("Calling SetProperty on not-exported property (legacy *disabled*)\n");
+ {
+ GValue value = {0,};
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, FALSE);
+ if (dbus_g_proxy_call (property_proxy, "Set", &error,
+ G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+ G_TYPE_STRING, "should-be-hidden",
+ G_TYPE_VALUE, &value,
+ G_TYPE_INVALID, G_TYPE_INVALID))
+ lose ("Unexpected success from SetProperty call of \"should-be-hidden\" property");
+ g_value_unset (&value);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (property_proxy);
+ property_proxy = NULL;
diff --git a/test/core/test-service-glib.c b/test/core/test-service-glib.c
index 222db17..bb9157e 100644
--- a/test/core/test-service-glib.c
+++ b/test/core/test-service-glib.c
@@ -12,272 +12,4 @@
#include <glib/gquark.h>
-#include "my-object-marshal.h"
-typedef struct MyObject MyObject;
-typedef struct MyObjectClass MyObjectClass;
-
-GType my_object_get_type (void);
-
-struct MyObject
-{
- GObject parent;
- char *this_is_a_string;
- guint val;
-};
-
-struct MyObjectClass
-{
- GObjectClass parent;
-};
-
-#define MY_TYPE_OBJECT (my_object_get_type ())
-#define MY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject))
-#define MY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass))
-#define MY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT))
-#define MY_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT))
-#define MY_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass))
-
-G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
-
-typedef enum
-{
- MY_OBJECT_ERROR_FOO,
- MY_OBJECT_ERROR_BAR
-} MyObjectError;
-
-#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);
-
-gboolean my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error);
-
-gint32 my_object_increment_retval (MyObject *obj, gint32 x);
-
-gint32 my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error);
-
-gboolean my_object_throw_error (MyObject *obj, GError **error);
-
-gboolean my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error);
-
-gboolean my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error);
-
-gboolean my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error);
-
-gboolean my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error);
-gboolean my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **array, GError **error);
-
-gboolean my_object_many_stringify (MyObject *obj, GHashTable *vals, GHashTable **ret, GError **error);
-
-gboolean my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error);
-
-gboolean my_object_objpath (MyObject *obj, const char *in, const char **arg1, GError **error);
-
-gboolean my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error);
-
-gboolean my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error);
-gboolean my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error);
-
-gboolean my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error);
-
-gboolean my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error);
-
-gboolean my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error);
-
-gboolean my_object_get_hash (MyObject *obj, GHashTable **table, GError **error);
-
-gboolean my_object_increment_val (MyObject *obj, GError **error);
-
-gboolean my_object_get_val (MyObject *obj, guint *ret, GError **error);
-
-gboolean my_object_get_value (MyObject *obj, guint *ret, GError **error);
-
-gboolean my_object_emit_signals (MyObject *obj, GError **error);
-gboolean my_object_emit_signal2 (MyObject *obj, GError **error);
-
-gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
-
-gboolean my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error);
-
-gboolean my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error);
-
-gboolean my_object_dict_of_dicts (MyObject *obj, GHashTable *dict, GHashTable **ret, GError **error);
-
-gboolean my_object_terminate (MyObject *obj, GError **error);
-
-void my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
-
-void 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
-{
- PROP_0,
- PROP_THIS_IS_A_STRING
-};
-
-enum
-{
- FROBNICATE,
- SIG0,
- SIG1,
- SIG2,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void
-my_object_finalize (GObject *object)
-{
- MyObject *mobject = MY_OBJECT (object);
-
- g_free (mobject->this_is_a_string);
-
- (G_OBJECT_CLASS (my_object_parent_class)->finalize) (object);
-}
-
-static void
-my_object_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MyObject *mobject;
-
- mobject = MY_OBJECT (object);
-
- switch (prop_id)
- {
- case PROP_THIS_IS_A_STRING:
- g_free (mobject->this_is_a_string);
- mobject->this_is_a_string = g_value_dup_string (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-my_object_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MyObject *mobject;
-
- mobject = MY_OBJECT (object);
-
- switch (prop_id)
- {
- case PROP_THIS_IS_A_STRING:
- g_value_set_string (value, mobject->this_is_a_string);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-my_object_init (MyObject *obj)
-{
- obj->val = 0;
-}
-
-static void
-my_object_class_init (MyObjectClass *mobject_class)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (mobject_class);
-
- gobject_class->finalize = my_object_finalize;
- gobject_class->set_property = my_object_set_property;
- gobject_class->get_property = my_object_get_property;
-
- g_object_class_install_property (gobject_class,
- PROP_THIS_IS_A_STRING,
- g_param_spec_string ("this_is_a_string",
- _("Sample string"),
- _("Example of a string property"),
- "default value",
- G_PARAM_READWRITE));
- signals[FROBNICATE] =
- g_signal_new ("frobnicate",
- G_OBJECT_CLASS_TYPE (mobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-
- signals[SIG0] =
- g_signal_new ("sig0",
- G_OBJECT_CLASS_TYPE (mobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- my_object_marshal_VOID__STRING_INT_STRING,
- G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
-
- signals[SIG1] =
- g_signal_new ("sig1",
- G_OBJECT_CLASS_TYPE (mobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- my_object_marshal_VOID__STRING_BOXED,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
-
- signals[SIG2] =
- g_signal_new ("sig2",
- G_OBJECT_CLASS_TYPE (mobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
-}
-
-GQuark
-my_object_error_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("my_object_error");
-
- 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;
-}
+#include "my-object.h"
@@ -285,560 +17,3 @@ static GObject *obj;
static GObject *obj2;
-
-gboolean
-my_object_do_nothing (MyObject *obj, GError **error)
-{
- return TRUE;
-}
-
-gboolean
-my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
-{
- *ret = x +1;
- return TRUE;
-}
-
-gint32
-my_object_increment_retval (MyObject *obj, gint32 x)
-{
- return x + 1;
-}
-
-gint32
-my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
-{
- if (x + 1 > 10)
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "%s",
- "x is bigger than 9");
- return FALSE;
- }
- return x + 1;
-}
-
-gboolean
-my_object_throw_error (MyObject *obj, GError **error)
-{
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "%s",
- "this method always loses");
- return FALSE;
-}
-
-gboolean
-my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error)
-{
- *ret = g_ascii_strup (str, -1);
- return TRUE;
-}
-
-gboolean
-my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error)
-{
- *d_ret = trouble + (x * 2);
- *str_ret = g_ascii_strup (str, -1);
- return TRUE;
-}
-
-gboolean
-my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error)
-{
- *arg0 = 42;
- *arg1 = g_strdup ("42");
- *arg2 = -67;
- *arg3 = 2;
- *arg4 = 26;
- *arg5 = "hello world"; /* Annotation specifies as const */
- return TRUE;
-}
-
-gboolean
-my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error)
-{
- GValue valstr = {0, };
-
- g_value_init (&valstr, G_TYPE_STRING);
- if (!g_value_transform (value, &valstr))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "couldn't transform value");
- return FALSE;
- }
- *ret = g_value_dup_string (&valstr);
- g_value_unset (&valstr);
- return TRUE;
-}
-
-gboolean
-my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error)
-{
- if (str[0] == '\0' || !g_ascii_isdigit (str[0])) {
- g_value_init (value, G_TYPE_STRING);
- g_value_set_string (value, str);
- } else {
- g_value_init (value, G_TYPE_INT);
- g_value_set_int (value, (int) g_ascii_strtoull (str, NULL, 10));
- }
- return TRUE;
-}
-
-gboolean
-my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error)
-{
- *len_ret = array->len;
- return TRUE;
-}
-
-gboolean
-my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **ret, GError **error)
-{
- guint32 val;
- GArray *array;
-
- array = g_array_new (FALSE, TRUE, sizeof (guint32));
-
- while (reqlen > 0) {
- val = 42;
- g_array_append_val (array, val);
- val = 26;
- g_array_append_val (array, val);
- reqlen--;
- }
- val = 2;
- g_array_append_val (array, val);
- *ret = array;
- return TRUE;
-}
-
-gboolean
-my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error)
-{
- int len;
- int i;
-
- len = g_strv_length ((char**) in);
-
- *out = g_new0 (char *, len + 1);
- for (i = 0; i < len; i++)
- {
- (*out)[i] = g_ascii_strup (in[i], -1);
- }
- (*out)[i] = NULL;
-
- return TRUE;
-}
-
-static void
-hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data)
-{
- const char *keystr = key;
- const GValue *value = val;
- GValue *sval;
- GHashTable *ret = user_data;
-
- sval = g_new0 (GValue, 1);
- g_value_init (sval, G_TYPE_STRING);
- if (!g_value_transform (value, sval))
- g_assert_not_reached ();
-
- g_hash_table_insert (ret, g_strdup (keystr), sval);
-}
-
-static void
-unset_and_free_gvalue (gpointer val)
-{
- g_value_unset (val);
- g_free (val);
-}
-
-gboolean
-my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error)
-{
- *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, unset_and_free_gvalue);
- g_hash_table_foreach (vals, hash_foreach_stringify, *ret);
- return TRUE;
-}
-
-gboolean
-my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error)
-{
- char **strs;
- GArray *ints;
- guint v_UINT;
-
- if (in->len != 2)
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid array len");
- return FALSE;
- }
-
- strs = g_ptr_array_index (in, 0);
- if (!*strs || strcmp (*strs, "foo"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string 0");
- return FALSE;
- }
- strs++;
- if (!*strs || strcmp (*strs, "bar"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string 1");
- return FALSE;
- }
- strs++;
- if (*strs)
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string array len in pos 0");
- return FALSE;
- }
- strs = g_ptr_array_index (in, 1);
- if (!*strs || strcmp (*strs, "baz"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string 0");
- return FALSE;
- }
- strs++;
- if (!*strs || strcmp (*strs, "whee"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string 1");
- return FALSE;
- }
- strs++;
- if (!*strs || strcmp (*strs, "moo"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string 2");
- return FALSE;
- }
- strs++;
- if (*strs)
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid string array len in pos 1");
- return FALSE;
- }
-
- *ret = g_ptr_array_new ();
-
- ints = g_array_new (TRUE, TRUE, sizeof (guint));
- v_UINT = 10;
- g_array_append_val (ints, v_UINT);
- v_UINT = 42;
- g_array_append_val (ints, v_UINT);
- v_UINT = 27;
- g_array_append_val (ints, v_UINT);
- g_ptr_array_add (*ret, ints);
-
- ints = g_array_new (TRUE, TRUE, sizeof (guint));
- v_UINT = 30;
- g_array_append_val (ints, v_UINT);
- g_ptr_array_add (*ret, ints);
- return TRUE;
-}
-
-gboolean
-my_object_objpath (MyObject *obj, const char *incoming, const char **outgoing, GError **error)
-{
- if (strcmp (incoming, "/org/freedesktop/DBus/GLib/Tests/MyTestObject"))
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid incoming object");
- return FALSE;
- }
- *outgoing = "/org/freedesktop/DBus/GLib/Tests/MyTestObject2";
- return TRUE;
-}
-
-gboolean
-my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error)
-{
- *objs = g_ptr_array_new ();
-
- g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject"));
- g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
-
- return TRUE;
-}
-
-static void
-hash_foreach (gpointer key, gpointer val, gpointer user_data)
-{
- const char *keystr = key;
- const char *valstr = val;
- guint *count = user_data;
-
- *count += (strlen (keystr) + strlen (valstr));
- g_print ("%s -> %s\n", keystr, valstr);
-}
-
-gboolean
-my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error)
-{
- *len = 0;
- g_hash_table_foreach (table, hash_foreach, len);
- return TRUE;
-}
-
-gboolean
-my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error)
-{
- if (invals->n_values != 3
- || G_VALUE_TYPE (g_value_array_get_nth (invals, 0)) != G_TYPE_STRING
- || G_VALUE_TYPE (g_value_array_get_nth (invals, 1)) != G_TYPE_UINT
- || G_VALUE_TYPE (g_value_array_get_nth (invals, 2)) != G_TYPE_VALUE)
- {
- g_set_error (error,
- MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "invalid incoming values");
- return FALSE;
- }
- *outvals = g_value_array_new (2);
- g_value_array_append (*outvals, NULL);
- g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), G_TYPE_UINT);
- g_value_set_uint (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
- g_value_get_uint (g_value_array_get_nth (invals, 1)) + 1);
- g_value_array_append (*outvals, NULL);
- g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), DBUS_TYPE_G_OBJECT_PATH);
- g_value_set_boxed (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
- g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
- return TRUE;
-}
-
-gboolean
-my_object_get_hash (MyObject *obj, GHashTable **ret, GError **error)
-{
- GHashTable *table;
-
- table = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (table, "foo", "bar");
- g_hash_table_insert (table, "baz", "whee");
- g_hash_table_insert (table, "cow", "crack");
- *ret = table;
- return TRUE;
-}
-
-gboolean
-my_object_increment_val (MyObject *obj, GError **error)
-{
- obj->val++;
- return TRUE;
-}
-
-gboolean
-my_object_get_val (MyObject *obj, guint *ret, GError **error)
-{
- *ret = obj->val;
- return TRUE;
-}
-
-gboolean
-my_object_get_value (MyObject *obj, guint *ret, GError **error)
-{
- *ret = obj->val;
- return TRUE;
-}
-
-gboolean
-my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
-{
- GType t;
- t = G_VALUE_TYPE(variant);
- g_value_init (ret, t);
- g_value_copy (variant, ret);
-
- return TRUE;
-}
-
-gboolean
-my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error)
-{
- GArray *array;
- int i;
- int j;
-
- j = 0;
-
- array = (GArray *)g_value_get_boxed (variant);
-
- for (i = 0; i <= 2; i++)
- {
- j = g_array_index (array, int, i);
- if (j != i + 1)
- goto error;
- }
-
- return TRUE;
-
-error:
- *error = g_error_new (MY_OBJECT_ERROR,
- MY_OBJECT_ERROR_FOO,
- "Error decoding a variant of type ai (i + 1 = %i, j = %i)",
- i, j + 1);
- return FALSE;
-}
-
-
-typedef struct _HashAndString HashAndString;
-
-struct _HashAndString
-{
- GHashTable *hash;
- gchar* string;
-};
-
-static void
-hash_foreach_prepend_string (gpointer key, gpointer val, gpointer user_data)
-{
- HashAndString *data = (HashAndString*) user_data;
- gchar *in = (gchar*) val;
- g_hash_table_insert (data->hash, g_strdup ((gchar*) key),
- g_strjoin (" ", data->string, in, NULL));
-}
-
-
-static void
-hash_foreach_mangle_dict_of_strings (gpointer key, gpointer val, gpointer user_data)
-{
- GHashTable *out = (GHashTable*) user_data;
- GHashTable *in_dict = (GHashTable *) val;
- HashAndString *data = g_new0 (HashAndString, 1);
-
- data->string = (gchar*) key;
- data->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- g_hash_table_foreach (in_dict, hash_foreach_prepend_string, data);
-
- g_hash_table_insert(out, g_strdup ((gchar*) key), data->hash);
-}
-
-gboolean
-my_object_dict_of_dicts (MyObject *obj, GHashTable *in,
- GHashTable **out, GError **error)
-{
- *out = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_hash_table_destroy);
- g_hash_table_foreach (in, hash_foreach_mangle_dict_of_strings, *out);
- return TRUE;
-}
-
-gboolean
-my_object_emit_frobnicate (MyObject *obj, GError **error)
-{
- g_signal_emit (obj, signals[FROBNICATE], 0, 42);
- return TRUE;
-}
-
-gboolean
-my_object_emit_signals (MyObject *obj, GError **error)
-{
- GValue val = {0, };
-
- g_signal_emit (obj, signals[SIG0], 0, "foo", 22, "moo");
-
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, "bar");
- g_signal_emit (obj, signals[SIG1], 0, "baz", &val);
- g_value_unset (&val);
-
- return TRUE;
-}
-
-gboolean
-my_object_emit_signal2 (MyObject *obj, GError **error)
-{
- GHashTable *table;
-
- table = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (table, "baz", "cow");
- g_hash_table_insert (table, "bar", "foo");
- g_signal_emit (obj, signals[SIG2], 0, table);
- g_hash_table_destroy (table);
- 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;
-}
-
-void
-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);
-}
-
-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;
-}
-
-void
-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);
-}
-
-
-static GMainLoop *loop;
-
-gboolean
-my_object_terminate (MyObject *obj, GError **error)
-{
- g_main_loop_quit (loop);
- return TRUE;
-}
+GMainLoop *loop;
@@ -857,5 +32,2 @@ main (int argc, char **argv)
- dbus_g_object_type_install_info (MY_TYPE_OBJECT,
- &dbus_glib_my_object_object_info);
-
dbus_g_error_domain_register (MY_OBJECT_ERROR,
diff --git a/test/core/test-service-glib.xml b/test/core/test-service-glib.xml
index fca02af..be262d6 100644
--- a/test/core/test-service-glib.xml
+++ b/test/core/test-service-glib.xml
@@ -4,2 +4,6 @@
<interface name="org.freedesktop.DBus.GLib.Tests.MyObject">
+ <property name="this_is_a_string" type="s" access="readwrite"/>
+ <property name="no-touching" type="u" access="read"/>
+ <property name="SuperStudly" type="d" access="readwrite"/>
+
<method name="DoNothing">
@@ -147,2 +151,5 @@
+ <method name="UnsafeDisableLegacyPropertyAccess">
+ </method>
+
<!-- Export signals -->