1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gobject.c Exporting a GObject remotely
4 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
5 * Copyright (C) 2005 Nokia
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <gobject/gvaluecollector.h>
27 #include <dbus/dbus-glib.h>
28 #include <dbus/dbus-glib-lowlevel.h>
29 #include "dbus-gtest.h"
30 #include "dbus-gutils.h"
31 #include "dbus-gobject.h"
32 #include "dbus-gsignature.h"
33 #include "dbus-gvalue.h"
34 #include "dbus-gmarshal.h"
35 #include "dbus-gvalue-utils.h"
38 static char *lookup_property_name (GObject *object,
39 const char *wincaps_propiface,
40 const char *requested_propname);
48 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
49 /* See comments in check_property_access */
50 static gboolean disable_legacy_property_access = FALSE;
51 static GHashTable *marshal_table = NULL;
52 static GData *error_metadata = NULL;
55 uscore_to_wincaps_full (const char *uscore,
56 gboolean uppercase_first)
60 gboolean last_was_uscore;
62 last_was_uscore = uppercase_first;
64 str = g_string_new (NULL);
68 if (*p == '-' || *p == '_')
70 last_was_uscore = TRUE;
76 g_string_append_c (str, g_ascii_toupper (*p));
77 last_was_uscore = FALSE;
80 g_string_append_c (str, *p);
85 return g_string_free (str, FALSE);
88 /* Ugly yes - but we have to accept strings from both formats */
90 compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
94 for (i = 0; a[i] && b[i]; i++)
96 if ((a[i] == '-' && b[i] == '_')
97 || (a[i] == '_' && b[i] == '-'))
102 return (a[i] == '\0') && (b[i] == '\0');
106 uscore_to_wincaps (const char *uscore)
108 return uscore_to_wincaps_full (uscore, TRUE);
112 string_table_next (const char *table)
114 return (table + (strlen (table) + 1));
118 string_table_lookup (const char *table, int index)
125 ret = string_table_next (ret);
131 get_method_data (const DBusGObjectInfo *object,
132 const DBusGMethodInfo *method)
134 return object->data + method->data_offset;
138 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
145 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
152 method_interface_from_object_info (const DBusGObjectInfo *object,
153 const DBusGMethodInfo *method)
155 return string_table_lookup (get_method_data (object, method), 0);
159 method_name_from_object_info (const DBusGObjectInfo *object,
160 const DBusGMethodInfo *method)
162 return string_table_lookup (get_method_data (object, method), 1);
166 method_arg_info_from_object_info (const DBusGObjectInfo *object,
167 const DBusGMethodInfo *method)
169 return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
180 arg_iterate (const char *data,
192 data = string_table_next (data);
202 g_warning ("invalid arg direction '%c'", *data);
211 data = string_table_next (data);
223 g_warning ("invalid arg const value '%c'", *data);
226 data = string_table_next (data);
231 *retval = RETVAL_NONE;
235 *retval = RETVAL_ERROR;
239 *retval = RETVAL_NOERROR;
242 g_warning ("invalid arg ret value '%c'", *data);
254 data = string_table_next (data);
258 return string_table_next (data);
262 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
263 const DBusGMethodInfo *method,
269 arg = method_arg_info_from_object_info (object, method);
271 ret = g_string_new (NULL);
279 arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
282 g_string_append (ret, type);
285 return g_string_free (ret, FALSE);
289 method_input_signature_from_object_info (const DBusGObjectInfo *object,
290 const DBusGMethodInfo *method)
292 return method_dir_signature_from_object_info (object, method, TRUE);
296 method_output_signature_from_object_info (const DBusGObjectInfo *object,
297 const DBusGMethodInfo *method)
299 return method_dir_signature_from_object_info (object, method, FALSE);
303 signal_iterate (const char *data, const char **iface, const char **name)
307 data = string_table_next (data);
310 return string_table_next (data);
314 property_iterate (const char *data,
317 const char **exported_name,
318 const char **name_uscored,
319 const char **access_type)
323 data = string_table_next (data);
324 *exported_name = data;
326 data = string_table_next (data);
327 if (format_version == 1)
329 *name_uscored = data;
330 data = string_table_next (data);
332 return string_table_next (data);
336 /* This tells the caller they need to compute it */
337 *name_uscored = NULL;
338 /* We don't know here, however note that we will still check against the
339 * readable/writable flags from GObject's metadata.
341 *access_type = "readwrite";
347 * property_info_from_object_info:
348 * @object: introspection data
349 * @interface_name: (allow-none): Expected interface name, or %NULL for any
350 * @property_name: Expected property name (can use "-" or "_" as separator)
351 * @access_type: (out): Can be one of "read", "write", "readwrite"
353 * Look up property introspection data for the given interface/name pair.
355 * Returns: %TRUE if property was found
358 property_info_from_object_info (const DBusGObjectInfo *object,
359 const char *interface_name,
360 const char *property_name,
361 const char **access_type)
363 const char *properties_iter;
365 properties_iter = object->exported_properties;
366 while (properties_iter != NULL && *properties_iter)
368 const char *cur_interface_name;
369 const char *cur_property_name;
370 const char *cur_uscore_property_name;
371 const char *cur_access_type;
374 properties_iter = property_iterate (properties_iter, object->format_version,
375 &cur_interface_name, &cur_property_name,
376 &cur_uscore_property_name, &cur_access_type);
378 if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
381 /* This big pile of ugly is necessary to support the matrix resulting from multiplying
382 * (v0 data, v1 data) * (FooBar, foo-bar)
383 * In v1 data we have both forms of string, so we do a comparison against both without
385 * For v0 data, we need to reconstruct the foo-bar form.
387 * Adding to the complexity is that we *also* have to ignore the distinction between
388 * '-' and '_', because g_object_{get,set} does.
390 /* First, compare against the primary property name - no malloc required */
391 if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
393 if (cur_uscore_property_name != NULL
394 && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
398 /* v0 metadata, construct uscore */
401 tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
402 matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
403 g_free (tmp_uscored);
409 *access_type = cur_access_type;
416 dbus_g_object_type_dbus_metadata_quark (void)
421 quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
425 /* Iterator function should return FALSE to stop iteration, TRUE to continue */
426 typedef gboolean (*ForeachObjectInfoFn) (const DBusGObjectInfo *info,
431 foreach_object_info (GObject *object,
432 ForeachObjectInfoFn callback,
435 GType *interfaces, *p;
436 const DBusGObjectInfo *info;
439 interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
441 for (p = interfaces; *p != 0; p++)
443 info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
444 if (info != NULL && info->format_version >= 0)
446 if (!callback (info, *p, user_data))
453 for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
455 info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
456 if (info != NULL && info->format_version >= 0)
458 if (!callback (info, classtype, user_data))
466 lookup_object_info_cb (const DBusGObjectInfo *info,
470 GList **list = (GList **) user_data;
472 *list = g_list_prepend (*list, (gpointer) info);
477 lookup_object_info (GObject *object)
479 GList *info_list = NULL;
481 foreach_object_info (object, lookup_object_info_cb, &info_list);
488 const DBusGObjectInfo *info;
491 } LookupObjectInfoByIfaceData;
494 lookup_object_info_by_iface_cb (const DBusGObjectInfo *info,
498 LookupObjectInfoByIfaceData *lookup_data = (LookupObjectInfoByIfaceData *) user_data;
500 /* If interface is not specified, choose the first info */
501 if (lookup_data->fallback && (!lookup_data->iface || strlen (lookup_data->iface) == 0))
503 lookup_data->info = info;
504 lookup_data->iface_type = gtype;
506 else if (info->exported_properties && !strcmp (info->exported_properties, lookup_data->iface))
508 lookup_data->info = info;
509 lookup_data->iface_type = gtype;
512 return !lookup_data->info;
515 static const DBusGObjectInfo *
516 lookup_object_info_by_iface (GObject *object,
519 GType *out_iface_type)
521 LookupObjectInfoByIfaceData data;
525 data.fallback = fallback;
528 foreach_object_info (object, lookup_object_info_by_iface_cb, &data);
530 if (out_iface_type && data.info)
531 *out_iface_type = data.iface_type;
537 DBusGConnection *connection;
540 } ObjectRegistration;
542 static void object_registration_object_died (gpointer user_data, GObject *dead);
544 static ObjectRegistration *
545 object_registration_new (DBusGConnection *connection,
546 const gchar *object_path,
549 ObjectRegistration *o = g_slice_new0 (ObjectRegistration);
551 o->connection = connection;
552 o->object_path = g_strdup (object_path);
555 g_object_weak_ref (o->object, object_registration_object_died, o);
561 object_registration_free (ObjectRegistration *o)
563 if (o->object != NULL)
565 GSList *registrations;
567 /* Ok, the object is still around; clear out this particular registration
568 * from the registrations list.
570 registrations = g_object_steal_data (o->object, "dbus_glib_object_registrations");
571 registrations = g_slist_remove (registrations, o);
573 if (registrations != NULL)
574 g_object_set_data (o->object, "dbus_glib_object_registrations", registrations);
576 g_object_weak_unref (o->object, object_registration_object_died, o);
579 g_free (o->object_path);
581 g_slice_free (ObjectRegistration, o);
584 /* Called when the object falls off the bus (e.g. because connection just
587 object_registration_unregistered (DBusConnection *connection,
590 object_registration_free (user_data);
598 const DBusGObjectInfo *object_info;
599 } DBusGLibWriteIterfaceData;
606 } DBusGLibWriteInterfaceValues;
609 write_interface (gpointer key, gpointer val, gpointer user_data)
616 const DBusGObjectInfo *object_info;
617 DBusGLibWriteIterfaceData *data;
618 DBusGLibWriteInterfaceValues *values;
623 methods = values->methods;
624 signals = values->signals;
625 properties = values->properties;
629 object_info = data->object_info;
631 g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
633 /* FIXME: recurse to parent types ? */
634 for (; methods; methods = methods->next)
636 DBusGMethodInfo *method;
638 method = methods->data;
640 g_string_append_printf (xml, " <method name=\"%s\">\n",
641 method_name_from_object_info (object_info, method));
643 args = method_arg_info_from_object_info (object_info, method);
651 args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
653 /* FIXME - handle container types */
654 g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
655 name, type, arg_in ? "in" : "out");
658 g_string_append (xml, " </method>\n");
661 g_slist_free (values->methods);
663 for (; signals; signals = signals->next)
671 signame = signals->data;
673 s = _dbus_gutils_wincaps_to_uscore (signame);
675 id = g_signal_lookup (s, data->gtype);
678 g_signal_query (id, &query);
679 g_assert (query.return_type == G_TYPE_NONE);
681 g_string_append_printf (xml, " <signal name=\"%s\">\n", signame);
683 for (arg = 0; arg < query.n_params; arg++)
685 char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
687 g_assert (dbus_type != NULL);
689 g_string_append (xml, " <arg type=\"");
690 g_string_append (xml, dbus_type);
691 g_string_append (xml, "\"/>\n");
695 g_string_append (xml, " </signal>\n");
698 g_slist_free (values->signals);
700 for (; properties; properties = properties->next)
703 const char *propname;
704 const char *propname_uscore;
705 const char *access_type;
714 property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
716 s = lookup_property_name (data->object, name, propname);
718 spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
719 g_assert (spec != NULL);
722 dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
723 g_assert (dbus_type != NULL);
725 can_set = strcmp (access_type, "readwrite") == 0
726 && ((spec->flags & G_PARAM_WRITABLE) != 0
727 && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
729 can_get = (spec->flags & G_PARAM_READABLE) != 0;
731 if (can_set || can_get)
733 g_string_append_printf (xml, " <property name=\"%s\" ", propname);
734 g_string_append (xml, "type=\"");
735 g_string_append (xml, dbus_type);
736 g_string_append (xml, "\" access=\"");
738 if (can_set && can_get)
739 g_string_append (xml, "readwrite");
741 g_string_append (xml, "read");
745 g_string_append (xml, "write");
748 g_string_append (xml, "\"/>\n");
753 g_slist_free (values->properties);
756 g_string_append (xml, " </interface>\n");
759 static DBusGLibWriteInterfaceValues *
760 lookup_values (GHashTable *interfaces, const char *method_interface)
762 DBusGLibWriteInterfaceValues *values;
763 if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
765 values = g_new0 (DBusGLibWriteInterfaceValues, 1);
766 g_hash_table_insert (interfaces, (gpointer) method_interface, values);
772 introspect_interfaces (GObject *object, GString *xml)
775 const GList *info_list_walk;
776 const DBusGObjectInfo *info;
777 DBusGLibWriteIterfaceData data;
779 GHashTable *interfaces;
780 DBusGLibWriteInterfaceValues *values;
783 info_list = lookup_object_info (object);
785 g_assert (info_list != NULL);
787 /* Gather a list of all interfaces, indexed into their methods */
788 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
790 info = (DBusGObjectInfo *) info_list_walk->data;
791 interfaces = g_hash_table_new (g_str_hash, g_str_equal);
793 g_assert (info != NULL);
795 for (i = 0; i < info->n_method_infos; i++)
797 const char *method_name;
798 const char *method_interface;
799 const char *method_args;
800 const DBusGMethodInfo *method;
802 method = &(info->method_infos[i]);
804 method_interface = method_interface_from_object_info (info, method);
805 method_name = method_name_from_object_info (info, method);
806 method_args = method_arg_info_from_object_info (info, method);
808 values = lookup_values (interfaces, method_interface);
809 values->methods = g_slist_prepend (values->methods, (gpointer) method);
812 propsig = info->exported_signals;
813 while (propsig != NULL && *propsig)
818 propsig = signal_iterate (propsig, &iface, &signame);
820 values = lookup_values (interfaces, iface);
821 values->signals = g_slist_prepend (values->signals, (gpointer) signame);
824 propsig = info->exported_properties;
825 while (propsig != NULL && *propsig)
828 const char *propname;
829 const char *propname_uscore;
830 const char *access_type;
832 propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
834 values = lookup_values (interfaces, iface);
835 values->properties = g_slist_prepend (values->properties, (gpointer)iface);
838 memset (&data, 0, sizeof (data));
840 data.gtype = G_TYPE_FROM_INSTANCE (object);
841 data.object_info = info;
842 data.object = object;
844 g_hash_table_foreach (interfaces, write_interface, &data);
845 g_hash_table_destroy (interfaces);
848 g_list_free (info_list);
851 static DBusHandlerResult
852 handle_introspect (DBusConnection *connection,
853 DBusMessage *message,
861 if (!dbus_connection_list_registered (connection,
862 dbus_message_get_path (message),
864 g_error ("Out of memory");
866 xml = g_string_new (NULL);
868 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
870 g_string_append (xml, "<node>\n");
872 /* We are introspectable, though I guess that was pretty obvious */
873 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
874 g_string_append (xml, " <method name=\"Introspect\">\n");
875 g_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
876 g_string_append (xml, " </method>\n");
877 g_string_append (xml, " </interface>\n");
879 /* We support get/set/getall properties */
880 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
881 g_string_append (xml, " <method name=\"Get\">\n");
882 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
883 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
884 g_string_append_printf (xml, " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
885 g_string_append (xml, " </method>\n");
886 g_string_append (xml, " <method name=\"Set\">\n");
887 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
888 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
889 g_string_append_printf (xml, " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
890 g_string_append (xml, " </method>\n");
891 g_string_append (xml, " <method name=\"GetAll\">\n");
892 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
893 g_string_append_printf (xml, " <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
894 DBUS_TYPE_ARRAY_AS_STRING
895 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
896 DBUS_TYPE_STRING_AS_STRING
897 DBUS_TYPE_VARIANT_AS_STRING
898 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
901 g_string_append (xml, " </method>\n");
902 g_string_append (xml, " </interface>\n");
904 introspect_interfaces (object, xml);
906 /* Append child nodes */
907 for (i = 0; children[i]; i++)
908 g_string_append_printf (xml, " <node name=\"%s\"/>\n",
911 /* Close the XML, and send it to the requesting app */
912 g_string_append (xml, "</node>\n");
914 ret = dbus_message_new_method_return (message);
916 g_error ("Out of memory");
918 dbus_message_append_args (ret,
919 DBUS_TYPE_STRING, &xml->str,
922 dbus_connection_send (connection, ret, NULL);
923 dbus_message_unref (ret);
925 g_string_free (xml, TRUE);
927 dbus_free_string_array (children);
929 return DBUS_HANDLER_RESULT_HANDLED;
933 set_object_property (DBusConnection *connection,
934 DBusMessage *message,
935 DBusMessageIter *iter,
939 GValue value = { 0, };
942 DBusGValueMarshalCtx context;
944 dbus_message_iter_recurse (iter, &sub);
946 context.recursion_depth = 0;
947 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
948 context.proxy = NULL;
950 g_value_init (&value, pspec->value_type);
951 if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
953 g_object_set_property (object,
957 g_value_unset (&value);
959 ret = dbus_message_new_method_return (message);
961 g_error ("out of memory");
965 ret = dbus_message_new_error (message,
966 DBUS_ERROR_INVALID_ARGS,
967 "Argument's D-BUS type can't be converted to a GType");
969 g_error ("out of memory");
976 get_object_property (DBusConnection *connection,
977 DBusMessage *message,
982 GValue value = {0, };
985 DBusMessageIter iter, subiter;
987 ret = dbus_message_new_method_return (message);
989 g_error ("out of memory");
992 g_value_init (&value, pspec->value_type);
993 g_object_get_property (object, pspec->name, &value);
995 variant_sig = _dbus_gvalue_to_signature (&value);
996 if (variant_sig == NULL)
998 value_gtype = G_VALUE_TYPE (&value);
999 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1000 g_value_unset (&value);
1004 dbus_message_iter_init_append (ret, &iter);
1005 if (!dbus_message_iter_open_container (&iter,
1010 g_free (variant_sig);
1011 g_value_unset (&value);
1015 if (!_dbus_gvalue_marshal (&subiter, &value))
1017 dbus_message_unref (ret);
1018 ret = dbus_message_new_error (message,
1019 DBUS_ERROR_UNKNOWN_METHOD,
1020 "Can't convert GType of object property to a D-BUS type");
1023 dbus_message_iter_close_container (&iter, &subiter);
1025 g_value_unset (&value);
1026 g_free (variant_sig);
1031 #define SHADOW_PROP_QUARK (dbus_g_object_type_dbus_shadow_property_quark ())
1034 dbus_g_object_type_dbus_shadow_property_quark (void)
1036 static GQuark quark;
1039 quark = g_quark_from_static_string ("DBusGObjectTypeDBusShadowPropertyQuark");
1043 /* Look for shadow properties on the given interface first, otherwise
1044 * just return the original property name. This allows implementations to
1045 * get around the glib limitation of unique property names among all
1046 * GInterfaces by registering a "shadow" property name that the get/set
1047 * request will be redirected to.
1049 * Shadow property data is stored as qdata on each GInterface. If there
1050 * is no interface info, or there is no registered shadow property, just
1051 * return the original property name.
1054 lookup_property_name (GObject *object,
1055 const char *wincaps_propiface,
1056 const char *requested_propname)
1058 const DBusGObjectInfo *object_info;
1059 GHashTable *shadow_props;
1060 char *shadow_prop_name = NULL, *uscore_name;
1061 GType iface_type = 0;
1063 g_assert (wincaps_propiface != NULL);
1064 g_assert (requested_propname != NULL);
1066 uscore_name = _dbus_gutils_wincaps_to_uscore (requested_propname);
1068 object_info = lookup_object_info_by_iface (object, wincaps_propiface, FALSE, &iface_type);
1072 shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1075 shadow_prop_name = g_strdup (g_hash_table_lookup (shadow_props, requested_propname));
1076 if (shadow_prop_name)
1077 g_free (uscore_name);
1080 return shadow_prop_name ? shadow_prop_name : uscore_name;
1084 * dbus_g_object_type_register_shadow_property:
1085 * @iface_type: #GType for the #GInterface
1086 * @dbus_prop_name: D-Bus property name (as specified in the introspection data)
1087 * to override with the shadow property name (as specified in the GType's
1088 * initialization function, ie glib-style)
1089 * @shadow_prop_name: property name which should override the shadow property
1091 * Registers a new property name @shadow_prop_name that overrides the
1092 * @dbus_prop_name in D-Bus property get/set requests. Since all properties for
1093 * all interfaces implemented by a GObject exist in the same namespace, this
1094 * allows implementations to use the same property name in two or more D-Bus
1095 * interfaces implemented by the same GObject, as long as one of those D-Bus
1096 * interface properties is registered with a shadow property name.
1098 * For example, if both org.foobar.Baz.InterfaceA and org.foobar.Baz.InterfaceB
1099 * have a D-Bus property called "Bork", the developer assigns a shadow property
1100 * name to the conflicting property name in one or both of these GInterfaces to
1101 * resolve the conflict. Assume the GInterface implementing
1102 * org.foobar.Baz.InterfaceA registers a shadow property called "a-bork", while
1103 * the GInterface implementing org.foobar.Baz.InterfaceB registers a shadow
1104 * property called "b-bork". The GObject implementing both these GInterfaces
1105 * would then use #g_object_class_override_property() to implement both
1106 * "a-bork" and "b-bork" and D-Bus requests for "Bork" on either D-Bus interface
1107 * will not conflict.
1110 dbus_g_object_type_register_shadow_property (GType iface_type,
1111 const char *dbus_prop_name,
1112 const char *shadow_prop_name)
1114 GHashTable *shadow_props;
1116 g_return_if_fail (G_TYPE_IS_CLASSED (iface_type) || G_TYPE_IS_INTERFACE (iface_type));
1117 g_return_if_fail (dbus_prop_name != NULL);
1118 g_return_if_fail (shadow_prop_name != NULL);
1120 shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1123 shadow_props = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1124 g_type_set_qdata (iface_type,
1125 dbus_g_object_type_dbus_shadow_property_quark (),
1129 g_assert (shadow_props);
1130 g_hash_table_insert (shadow_props, g_strdup (dbus_prop_name), g_strdup (shadow_prop_name));
1134 get_all_object_properties (DBusConnection *connection,
1135 DBusMessage *message,
1136 const DBusGObjectInfo *object_info,
1137 const char *wincaps_propiface,
1141 DBusMessageIter iter_ret;
1142 DBusMessageIter iter_dict;
1143 DBusMessageIter iter_dict_entry;
1144 DBusMessageIter iter_dict_value;
1146 char *uscore_propname;
1148 ret = dbus_message_new_method_return (message);
1152 dbus_message_iter_init_append (ret, &iter_ret);
1154 if (!dbus_message_iter_open_container (&iter_ret,
1156 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1157 DBUS_TYPE_STRING_AS_STRING
1158 DBUS_TYPE_VARIANT_AS_STRING
1159 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1163 p = object_info->exported_properties;
1164 while (p != NULL && *p != '\0')
1166 const char *prop_ifname;
1167 const char *prop_name;
1168 const char *prop_uscored;
1169 const char *access_flags;
1172 GValue value = {0, };
1175 p = property_iterate (p, object_info->format_version, &prop_ifname, &prop_name, &prop_uscored, &access_flags);
1177 uscore_propname = lookup_property_name (object, wincaps_propiface, prop_name);
1179 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), uscore_propname);
1182 g_warning ("introspection data references non-existing property %s", uscore_propname);
1183 g_free (uscore_propname);
1187 g_free (uscore_propname);
1189 g_value_init (&value, pspec->value_type);
1190 g_object_get_property (object, pspec->name, &value);
1192 variant_sig = _dbus_gvalue_to_signature (&value);
1193 if (variant_sig == NULL)
1195 value_gtype = G_VALUE_TYPE (&value);
1196 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1197 g_value_unset (&value);
1201 if (!dbus_message_iter_open_container (&iter_dict,
1202 DBUS_TYPE_DICT_ENTRY,
1206 if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name))
1209 if (!dbus_message_iter_open_container (&iter_dict_entry,
1215 if (!_dbus_gvalue_marshal (&iter_dict_value, &value))
1218 if (!dbus_message_iter_close_container (&iter_dict_entry,
1221 if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
1224 g_value_unset (&value);
1225 g_free (variant_sig);
1228 if (!dbus_message_iter_close_container (&iter_ret, &iter_dict))
1234 g_error ("out of memory");
1238 lookup_object_and_method (GObject *object,
1239 DBusMessage *message,
1240 const DBusGObjectInfo **object_ret,
1241 const DBusGMethodInfo **method_ret)
1243 const char *interface;
1245 const char *signature;
1247 const GList *info_list_walk;
1248 const DBusGObjectInfo *info;
1251 interface = dbus_message_get_interface (message);
1252 member = dbus_message_get_member (message);
1253 signature = dbus_message_get_signature (message);
1255 info_list = lookup_object_info (object);
1257 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
1259 info = (DBusGObjectInfo *) info_list_walk->data;
1262 for (i = 0; i < info->n_method_infos; i++)
1264 const char *expected_member;
1265 const char *expected_interface;
1266 char *expected_signature;
1267 const DBusGMethodInfo *method;
1269 method = &(info->method_infos[i]);
1271 /* Check method interface/name and input signature */
1272 expected_interface = method_interface_from_object_info (*object_ret, method);
1273 expected_member = method_name_from_object_info (*object_ret, method);
1274 expected_signature = method_input_signature_from_object_info (*object_ret, method);
1276 if ((interface == NULL
1277 || strcmp (expected_interface, interface) == 0)
1278 && strcmp (expected_member, member) == 0
1279 && strcmp (expected_signature, signature) == 0)
1281 g_free (expected_signature);
1282 *method_ret = method;
1283 g_list_free (info_list);
1286 g_free (expected_signature);
1291 g_list_free (info_list);
1297 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
1298 const char *msg_interface,
1299 GQuark domain, gint code)
1301 const char *domain_str;
1302 const char *code_str;
1303 GString *dbus_error_name;
1305 domain_str = object_error_domain_prefix_from_object_info (object_info);
1306 code_str = object_error_code_from_object_info (object_info, domain, code);
1308 if (!domain_str || !code_str)
1310 DBusGErrorInfo *info;
1312 g_static_rw_lock_reader_lock (&globals_lock);
1314 if (error_metadata != NULL)
1315 info = g_datalist_id_get_data (&error_metadata, domain);
1319 g_static_rw_lock_reader_unlock (&globals_lock);
1326 klass = g_type_class_ref (info->code_enum);
1327 value = g_enum_get_value (klass, code);
1328 g_type_class_unref (klass);
1330 domain_str = info->default_iface;
1331 code_str = value->value_nick;
1336 domain_str = msg_interface;
1338 if (!domain_str || !code_str)
1340 const char *domain_string;
1341 /* If we can't map it sensibly, make up an error name */
1343 dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
1345 domain_string = g_quark_to_string (domain);
1346 if (domain_string != NULL)
1348 char *uscored = uscore_to_wincaps (domain_string);
1349 g_string_append (dbus_error_name, uscored);
1350 g_string_append_c (dbus_error_name, '.');
1354 g_string_append_printf (dbus_error_name, "Code%d", code);
1358 gchar *code_str_wincaps;
1359 dbus_error_name = g_string_new (domain_str);
1360 g_string_append_c (dbus_error_name, '.');
1361 /* We can't uppercase here for backwards compatibility
1362 * reasons; if someone had a lowercase enumeration value,
1363 * previously we'd just send it across unaltered.
1365 code_str_wincaps = uscore_to_wincaps_full (code_str, FALSE);
1366 g_string_append (dbus_error_name, code_str_wincaps);
1367 g_free (code_str_wincaps);
1370 return g_string_free (dbus_error_name, FALSE);
1373 static DBusMessage *
1374 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
1375 DBusMessage *message,
1376 const GError *error)
1384 error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
1385 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
1390 if (error->domain == DBUS_GERROR)
1392 const gchar *name = DBUS_ERROR_FAILED;
1394 switch (error->code)
1396 case DBUS_GERROR_FAILED:
1397 name = DBUS_ERROR_FAILED;
1399 case DBUS_GERROR_NO_MEMORY:
1400 name = DBUS_ERROR_NO_MEMORY;
1402 case DBUS_GERROR_SERVICE_UNKNOWN:
1403 name = DBUS_ERROR_SERVICE_UNKNOWN;
1405 case DBUS_GERROR_NAME_HAS_NO_OWNER:
1406 name = DBUS_ERROR_NAME_HAS_NO_OWNER;
1408 case DBUS_GERROR_NO_REPLY:
1409 name = DBUS_ERROR_NO_REPLY;
1411 case DBUS_GERROR_IO_ERROR:
1412 name = DBUS_ERROR_IO_ERROR;
1414 case DBUS_GERROR_BAD_ADDRESS:
1415 name = DBUS_ERROR_BAD_ADDRESS;
1417 case DBUS_GERROR_NOT_SUPPORTED:
1418 name = DBUS_ERROR_NOT_SUPPORTED;
1420 case DBUS_GERROR_LIMITS_EXCEEDED:
1421 name = DBUS_ERROR_LIMITS_EXCEEDED;
1423 case DBUS_GERROR_ACCESS_DENIED:
1424 name = DBUS_ERROR_ACCESS_DENIED;
1426 case DBUS_GERROR_AUTH_FAILED:
1427 name = DBUS_ERROR_AUTH_FAILED;
1429 case DBUS_GERROR_NO_SERVER:
1430 name = DBUS_ERROR_NO_SERVER;
1432 case DBUS_GERROR_TIMEOUT:
1433 name = DBUS_ERROR_TIMEOUT;
1435 case DBUS_GERROR_NO_NETWORK:
1436 name = DBUS_ERROR_NO_NETWORK;
1438 case DBUS_GERROR_ADDRESS_IN_USE:
1439 name = DBUS_ERROR_ADDRESS_IN_USE;
1441 case DBUS_GERROR_DISCONNECTED:
1442 name = DBUS_ERROR_DISCONNECTED;
1444 case DBUS_GERROR_INVALID_ARGS:
1445 name = DBUS_ERROR_INVALID_ARGS;
1447 case DBUS_GERROR_FILE_NOT_FOUND:
1448 name = DBUS_ERROR_FILE_NOT_FOUND;
1450 case DBUS_GERROR_REMOTE_EXCEPTION:
1451 name = dbus_g_error_get_name ((GError*) error);
1455 reply = dbus_message_new_error (message, name, error->message);
1460 error_name = gerror_domaincode_to_dbus_error_name (object_info,
1461 dbus_message_get_interface (message),
1462 error->domain, error->code);
1463 reply = dbus_message_new_error (message, error_name, error->message);
1464 g_free (error_name);
1471 * SECTION:dbus-gmethod
1472 * @short_description: GMethod Info & Invocation
1473 * @see_also: #DBusGMessage
1474 * @stability: Stable
1476 * These types are used to call methods on #GObject objects.
1480 * The context of an asynchronous method call. See dbus_g_method_return() and
1481 * dbus_g_method_return_error().
1483 struct _DBusGMethodInvocation {
1484 DBusGConnection *connection; /**< The connection */
1485 DBusGMessage *message; /**< The message which generated the method call */
1486 const DBusGObjectInfo *object; /**< The object the method was called on */
1487 const DBusGMethodInfo *method; /**< The method called */
1488 gboolean send_reply;
1491 static DBusHandlerResult
1492 invoke_object_method (GObject *object,
1493 const DBusGObjectInfo *object_info,
1494 const DBusGMethodInfo *method,
1495 DBusConnection *connection,
1496 DBusMessage *message)
1498 gboolean had_error, is_async, send_reply;
1500 GValueArray *value_array;
1501 GValue return_value = {0,};
1504 GArray *out_param_values = NULL;
1505 GValueArray *out_param_gvalues = NULL;
1506 int out_param_count;
1507 int out_param_pos, out_param_gvalue_pos;
1508 DBusHandlerResult result;
1509 DBusMessage *reply = NULL;
1510 gboolean have_retval;
1511 gboolean retval_signals_error;
1512 gboolean retval_is_synthetic;
1513 gboolean retval_is_constant;
1514 const char *arg_metadata;
1518 /* This flag says whether invokee is handed a special DBusGMethodInvocation structure,
1519 * instead of being required to fill out all return values in the context of the function.
1520 * Some additional data is also exposed, such as the message sender.
1522 is_async = strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0;
1524 /* Messages can be sent with a flag that says "I don't need a reply". This is an optimization
1525 * normally, but in the context of the system bus it's important to not send a reply
1526 * to these kinds of messages, because they will be unrequested replies, and thus subject
1527 * to denial and logging. We don't want to fill up logs.
1528 * http://bugs.freedesktop.org/show_bug.cgi?id=19441
1530 send_reply = !dbus_message_get_no_reply (message);
1532 have_retval = FALSE;
1533 retval_signals_error = FALSE;
1534 retval_is_synthetic = FALSE;
1535 retval_is_constant = FALSE;
1537 /* This is evil. We do this to work around the fact that
1538 * the generated glib marshallers check a flag in the closure object
1539 * which we don't care about. We don't need/want to create
1540 * a new closure for each invocation.
1542 memset (&closure, 0, sizeof (closure));
1544 in_signature = method_input_signature_from_object_info (object_info, method);
1546 /* Convert method IN parameters to GValueArray */
1548 GArray *types_array;
1551 DBusGValueMarshalCtx context;
1552 GError *error = NULL;
1554 context.recursion_depth = 0;
1555 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
1556 context.proxy = NULL;
1558 types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
1559 n_params = types_array->len;
1560 types = (const GType*) types_array->data;
1562 value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
1563 if (value_array == NULL)
1565 g_free (in_signature);
1566 g_array_free (types_array, TRUE);
1567 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
1568 dbus_connection_send (connection, reply, NULL);
1569 dbus_message_unref (reply);
1570 g_error_free (error);
1571 return DBUS_HANDLER_RESULT_HANDLED;
1573 g_array_free (types_array, TRUE);
1576 /* Prepend object as first argument */
1577 g_value_array_prepend (value_array, NULL);
1578 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
1579 g_value_set_object (g_value_array_get_nth (value_array, 0), object);
1583 GValue context_value = {0,};
1584 DBusGMethodInvocation *context;
1585 context = g_new (DBusGMethodInvocation, 1);
1586 context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
1587 context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
1588 context->object = object_info;
1589 context->method = method;
1590 context->send_reply = send_reply;
1591 g_value_init (&context_value, G_TYPE_POINTER);
1592 g_value_set_pointer (&context_value, context);
1593 g_value_array_append (value_array, &context_value);
1602 arg_metadata = method_arg_info_from_object_info (object_info, method);
1604 /* Count number of output parameters, and look for a return value */
1605 out_param_count = 0;
1606 while (*arg_metadata)
1608 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
1611 if (retval != RETVAL_NONE)
1613 DBusSignatureIter tmp_sigiter;
1614 /* This is the function return value */
1615 g_assert (!have_retval);
1617 retval_is_synthetic = FALSE;
1622 g_assert_not_reached ();
1624 case RETVAL_NOERROR:
1625 retval_signals_error = FALSE;
1628 retval_signals_error = TRUE;
1632 retval_is_constant = arg_const;
1634 /* Initialize our return GValue with the specified type */
1635 dbus_signature_iter_init (&tmp_sigiter, argsig);
1636 g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
1640 /* It's a regular output value */
1645 /* For compatibility, if we haven't found a return value, we assume
1646 * the function returns a gboolean for signalling an error
1647 * (and therefore also takes a GError). We also note that it
1648 * is a "synthetic" return value; i.e. we aren't going to be
1649 * sending it over the bus, it's just to signal an error.
1654 retval_is_synthetic = TRUE;
1655 retval_signals_error = TRUE;
1656 g_value_init (&return_value, G_TYPE_BOOLEAN);
1659 /* Create an array to store the actual values of OUT parameters
1660 * (other than the real function return, if any). Then, create
1661 * a GValue boxed POINTER to each of those values, and append to
1662 * the invocation, so the method can return the OUT parameters.
1664 out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
1666 /* We have a special array of GValues for toplevel GValue return
1669 out_param_gvalues = g_value_array_new (out_param_count);
1671 out_param_gvalue_pos = 0;
1673 /* Reset argument metadata pointer */
1674 arg_metadata = method_arg_info_from_object_info (object_info, method);
1676 /* Iterate over output arguments again, this time allocating space for
1677 * them as appopriate.
1679 while (*arg_metadata)
1681 GValue value = {0, };
1682 GTypeCValue storage;
1683 DBusSignatureIter tmp_sigiter;
1684 GType current_gtype;
1686 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
1687 /* Skip over input arguments and the return value, if any */
1688 if (arg_in || retval != RETVAL_NONE)
1691 dbus_signature_iter_init (&tmp_sigiter, argsig);
1692 current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
1694 g_value_init (&value, G_TYPE_POINTER);
1696 /* We special case variants to make method invocation a bit nicer */
1697 if (current_gtype != G_TYPE_VALUE)
1699 memset (&storage, 0, sizeof (storage));
1700 g_array_append_val (out_param_values, storage);
1701 g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
1706 g_value_array_append (out_param_gvalues, NULL);
1707 g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
1708 out_param_gvalue_pos++;
1710 g_value_array_append (value_array, &value);
1714 /* Append GError as final argument if necessary */
1715 if (retval_signals_error)
1717 g_assert (have_retval);
1718 g_value_array_append (value_array, NULL);
1719 g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
1720 g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
1723 /* Actually invoke method */
1724 method->marshaller (&closure, have_retval ? &return_value : NULL,
1725 value_array->n_values,
1726 value_array->values,
1727 NULL, method->function);
1730 result = DBUS_HANDLER_RESULT_HANDLED;
1733 if (retval_signals_error)
1734 had_error = _dbus_gvalue_signals_error (&return_value);
1740 DBusMessageIter iter;
1742 /* Careful here - there are two major cases in this section of the code.
1743 * If send_reply is TRUE, we're constructing a dbus message and freeing
1744 * the return values. If it's FALSE, then we just need to free the
1749 reply = dbus_message_new_method_return (message);
1753 /* Append output arguments to reply */
1754 dbus_message_iter_init_append (reply, &iter);
1757 /* First, append the return value, unless it's synthetic */
1758 if (have_retval && !retval_is_synthetic)
1760 if (send_reply && !_dbus_gvalue_marshal (&iter, &return_value))
1762 if (!retval_is_constant)
1763 g_value_unset (&return_value);
1766 /* Grab the argument metadata and iterate over it */
1767 arg_metadata = method_arg_info_from_object_info (object_info, method);
1769 /* Now append any remaining return values */
1771 out_param_gvalue_pos = 0;
1772 while (*arg_metadata)
1774 GValue gvalue = {0, };
1775 const char *arg_name;
1779 const char *arg_signature;
1780 DBusSignatureIter argsigiter;
1784 /* Iterate over only output values; skip over input
1785 arguments and the return value */
1786 arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
1788 while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
1790 /* If the last argument we saw was input or the return
1791 * value, we must be done iterating over output arguments.
1793 if (arg_in || retval != RETVAL_NONE)
1796 dbus_signature_iter_init (&argsigiter, arg_signature);
1798 g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
1799 if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
1801 if (!_dbus_gvalue_take (&gvalue,
1802 &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
1803 g_assert_not_reached ();
1808 g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
1809 out_param_gvalue_pos++;
1812 if (send_reply && !_dbus_gvalue_marshal (&iter, &gvalue))
1814 /* Here we actually free the allocated value; we
1815 * took ownership of it with _dbus_gvalue_take, unless
1816 * an annotation has specified this value as constant.
1819 g_value_unset (&gvalue);
1822 else if (send_reply)
1823 reply = gerror_to_dbus_error_message (object_info, message, gerror);
1827 dbus_connection_send (connection, reply, NULL);
1828 dbus_message_unref (reply);
1831 result = DBUS_HANDLER_RESULT_HANDLED;
1833 g_free (in_signature);
1836 g_array_free (out_param_values, TRUE);
1837 g_value_array_free (out_param_gvalues);
1841 g_clear_error (&gerror);
1843 g_value_array_free (value_array);
1846 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
1851 check_property_access (DBusConnection *connection,
1852 DBusMessage *message,
1854 const char *wincaps_propiface,
1855 const char *requested_propname,
1856 const char *uscore_propname,
1859 const DBusGObjectInfo *object_info;
1860 const char *access_type;
1863 if (!is_set && !disable_legacy_property_access)
1866 object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
1869 ret = dbus_message_new_error_printf (message,
1870 DBUS_ERROR_ACCESS_DENIED,
1871 "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
1873 requested_propname);
1874 dbus_connection_send (connection, ret, NULL);
1875 dbus_message_unref (ret);
1879 /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
1880 * reasons we accept both.
1883 && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
1884 || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
1886 ret = dbus_message_new_error_printf (message,
1887 DBUS_ERROR_ACCESS_DENIED,
1888 "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
1891 dbus_connection_send (connection, ret, NULL);
1892 dbus_message_unref (ret);
1896 if (strcmp (access_type, "readwrite") == 0)
1898 else if (is_set ? strcmp (access_type, "read") == 0
1899 : strcmp (access_type, "write") == 0)
1901 ret = dbus_message_new_error_printf (message,
1902 DBUS_ERROR_ACCESS_DENIED,
1903 "Property \"%s\" of interface \"%s\" is not %s",
1906 is_set ? "settable" : "readable");
1907 dbus_connection_send (connection, ret, NULL);
1908 dbus_message_unref (ret);
1914 static DBusHandlerResult
1915 object_registration_message (DBusConnection *connection,
1916 DBusMessage *message,
1925 const char *requested_propname;
1926 const char *wincaps_propiface;
1927 DBusMessageIter iter;
1928 const DBusGMethodInfo *method;
1929 const DBusGObjectInfo *object_info;
1931 ObjectRegistration *o;
1934 object = G_OBJECT (o->object);
1936 if (dbus_message_is_method_call (message,
1937 DBUS_INTERFACE_INTROSPECTABLE,
1939 return handle_introspect (connection, message, object);
1941 /* Try the metainfo, which lets us invoke methods */
1943 if (lookup_object_and_method (object, message, &object_info, &method))
1944 return invoke_object_method (object, object_info, method, connection, message);
1946 /* If no metainfo, we can still do properties and signals
1947 * via standard GLib introspection. Note we do now check
1948 * property access against the metainfo if available.
1953 if (dbus_message_is_method_call (message,
1954 DBUS_INTERFACE_PROPERTIES,
1957 else if (dbus_message_is_method_call (message,
1958 DBUS_INTERFACE_PROPERTIES,
1961 else if (dbus_message_is_method_call (message,
1962 DBUS_INTERFACE_PROPERTIES,
1966 if (!(setter || getter || getall))
1967 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1971 dbus_message_iter_init (message, &iter);
1973 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1975 g_warning ("Property get or set does not have an interface string as first arg\n");
1976 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1979 dbus_message_iter_get_basic (&iter, &wincaps_propiface);
1980 dbus_message_iter_next (&iter);
1984 object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
1985 if (object_info != NULL)
1986 ret = get_all_object_properties (connection, message, object_info, wincaps_propiface, object);
1988 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1990 else if (getter || setter)
1992 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1994 g_warning ("Property get or set does not have a property name string as second arg\n");
1995 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1997 dbus_message_iter_get_basic (&iter, &requested_propname);
1998 dbus_message_iter_next (&iter);
2000 s = lookup_property_name (object, wincaps_propiface, requested_propname);
2002 if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
2005 return DBUS_HANDLER_RESULT_HANDLED;
2008 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
2017 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
2019 g_warning ("Property set does not have a variant value as third arg\n");
2020 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2023 ret = set_object_property (connection, message, &iter,
2025 dbus_message_iter_next (&iter);
2029 ret = get_object_property (connection, message,
2034 g_assert_not_reached ();
2040 ret = dbus_message_new_error_printf (message,
2041 DBUS_ERROR_INVALID_ARGS,
2042 "No such property %s", requested_propname);
2046 g_assert (ret != NULL);
2048 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
2049 g_warning ("Property get, set or set all had too many arguments\n");
2051 dbus_connection_send (connection, ret, NULL);
2052 dbus_message_unref (ret);
2053 return DBUS_HANDLER_RESULT_HANDLED;
2056 static const DBusObjectPathVTable gobject_dbus_vtable = {
2057 object_registration_unregistered,
2058 object_registration_message,
2064 DBusGConnection *connection;
2066 const char *signame;
2067 const char *sigiface;
2068 } DBusGSignalClosure;
2071 dbus_g_signal_closure_new (DBusGConnection *connection,
2073 const char *signame,
2074 const char *sigiface)
2076 DBusGSignalClosure *closure;
2078 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
2080 closure->connection = dbus_g_connection_ref (connection);
2081 closure->object = object;
2082 closure->signame = signame;
2083 closure->sigiface = sigiface;
2084 return (GClosure*) closure;
2088 dbus_g_signal_closure_finalize (gpointer data,
2091 DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
2093 dbus_g_connection_unref (sigclosure->connection);
2097 emit_signal_for_registration (ObjectRegistration *o,
2098 DBusGSignalClosure *sigclosure,
2100 guint n_param_values,
2101 const GValue *param_values)
2103 DBusMessage *signal;
2104 DBusMessageIter iter;
2107 signal = dbus_message_new_signal (o->object_path,
2108 sigclosure->sigiface,
2109 sigclosure->signame);
2112 g_error ("out of memory");
2116 dbus_message_iter_init_append (signal, &iter);
2118 /* First argument is the object itself, and we can't marshall that */
2119 for (i = 1; i < n_param_values; i++)
2121 if (!_dbus_gvalue_marshal (&iter,
2122 (GValue *) (&(param_values[i]))))
2124 g_warning ("failed to marshal parameter %d for signal %s",
2125 i, sigclosure->signame);
2129 dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
2132 dbus_message_unref (signal);
2136 signal_emitter_marshaller (GClosure *closure,
2138 guint n_param_values,
2139 const GValue *param_values,
2140 gpointer invocation_hint,
2141 gpointer marshal_data)
2143 DBusGSignalClosure *sigclosure;
2144 GSList *registrations, *iter;
2146 sigclosure = (DBusGSignalClosure *) closure;
2148 g_assert (retval == NULL);
2150 registrations = g_object_get_data (sigclosure->object, "dbus_glib_object_registrations");
2152 for (iter = registrations; iter; iter = iter->next)
2154 ObjectRegistration *o = iter->data;
2156 emit_signal_for_registration (o, sigclosure, retval, n_param_values, param_values);
2161 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
2164 const char *sigdata;
2166 const char *signame;
2167 const DBusGObjectInfo *info;
2169 gtype = G_TYPE_FROM_INSTANCE (object);
2171 for (; info_list != NULL; info_list = g_list_next (info_list))
2173 info = (DBusGObjectInfo *) info_list->data;
2175 sigdata = info->exported_signals;
2177 while (*sigdata != '\0')
2184 sigdata = signal_iterate (sigdata, &iface, &signame);
2186 s = _dbus_gutils_wincaps_to_uscore (signame);
2188 id = g_signal_lookup (s, gtype);
2191 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
2192 s, signame, g_type_name (gtype));
2197 g_signal_query (id, &query);
2199 if (query.return_type != G_TYPE_NONE)
2201 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
2202 s, g_type_name (gtype), g_type_name (query.return_type));
2204 continue; /* FIXME: these could be listed as methods ? */
2207 closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
2208 g_closure_set_marshal (closure, signal_emitter_marshaller);
2210 g_signal_connect_closure_by_id (object,
2216 g_closure_add_finalize_notifier (closure, NULL,
2217 dbus_g_signal_closure_finalize);
2224 dbus_error_to_gerror_code (const char *derr)
2227 else if (!strcmp (derr, DBUS_ERROR_FAILED ))
2228 return DBUS_GERROR_FAILED ;
2229 else if (!strcmp (derr, DBUS_ERROR_NO_MEMORY ))
2230 return DBUS_GERROR_NO_MEMORY ;
2231 else if (!strcmp (derr, DBUS_ERROR_SERVICE_UNKNOWN ))
2232 return DBUS_GERROR_SERVICE_UNKNOWN ;
2233 else if (!strcmp (derr, DBUS_ERROR_NAME_HAS_NO_OWNER ))
2234 return DBUS_GERROR_NAME_HAS_NO_OWNER ;
2235 else if (!strcmp (derr, DBUS_ERROR_NO_REPLY ))
2236 return DBUS_GERROR_NO_REPLY ;
2237 else if (!strcmp (derr, DBUS_ERROR_IO_ERROR ))
2238 return DBUS_GERROR_IO_ERROR ;
2239 else if (!strcmp (derr, DBUS_ERROR_BAD_ADDRESS ))
2240 return DBUS_GERROR_BAD_ADDRESS ;
2241 else if (!strcmp (derr, DBUS_ERROR_NOT_SUPPORTED ))
2242 return DBUS_GERROR_NOT_SUPPORTED ;
2243 else if (!strcmp (derr, DBUS_ERROR_LIMITS_EXCEEDED ))
2244 return DBUS_GERROR_LIMITS_EXCEEDED ;
2245 else if (!strcmp (derr, DBUS_ERROR_ACCESS_DENIED ))
2246 return DBUS_GERROR_ACCESS_DENIED ;
2247 else if (!strcmp (derr, DBUS_ERROR_AUTH_FAILED ))
2248 return DBUS_GERROR_AUTH_FAILED ;
2249 else if (!strcmp (derr, DBUS_ERROR_NO_SERVER ))
2250 return DBUS_GERROR_NO_SERVER ;
2251 else if (!strcmp (derr, DBUS_ERROR_TIMEOUT ))
2252 return DBUS_GERROR_TIMEOUT ;
2253 else if (!strcmp (derr, DBUS_ERROR_NO_NETWORK ))
2254 return DBUS_GERROR_NO_NETWORK ;
2255 else if (!strcmp (derr, DBUS_ERROR_ADDRESS_IN_USE ))
2256 return DBUS_GERROR_ADDRESS_IN_USE ;
2257 else if (!strcmp (derr, DBUS_ERROR_DISCONNECTED ))
2258 return DBUS_GERROR_DISCONNECTED ;
2259 else if (!strcmp (derr, DBUS_ERROR_INVALID_ARGS ))
2260 return DBUS_GERROR_INVALID_ARGS ;
2261 else if (!strcmp (derr, DBUS_ERROR_FILE_NOT_FOUND ))
2262 return DBUS_GERROR_FILE_NOT_FOUND ;
2263 else if (!strcmp (derr, DBUS_ERROR_FILE_EXISTS ))
2264 return DBUS_GERROR_FILE_EXISTS ;
2265 else if (!strcmp (derr, DBUS_ERROR_UNKNOWN_METHOD ))
2266 return DBUS_GERROR_UNKNOWN_METHOD ;
2267 else if (!strcmp (derr, DBUS_ERROR_TIMED_OUT ))
2268 return DBUS_GERROR_TIMED_OUT ;
2269 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_NOT_FOUND ))
2270 return DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
2271 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_INVALID ))
2272 return DBUS_GERROR_MATCH_RULE_INVALID ;
2273 else if (!strcmp (derr, DBUS_ERROR_SPAWN_EXEC_FAILED ))
2274 return DBUS_GERROR_SPAWN_EXEC_FAILED ;
2275 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FORK_FAILED ))
2276 return DBUS_GERROR_SPAWN_FORK_FAILED ;
2277 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_EXITED ))
2278 return DBUS_GERROR_SPAWN_CHILD_EXITED ;
2279 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_SIGNALED ))
2280 return DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
2281 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FAILED ))
2282 return DBUS_GERROR_SPAWN_FAILED ;
2283 else if (!strcmp (derr, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN ))
2284 return DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
2285 else if (!strcmp (derr, DBUS_ERROR_INVALID_SIGNATURE ))
2286 return DBUS_GERROR_INVALID_SIGNATURE ;
2287 else if (!strcmp (derr, DBUS_ERROR_INVALID_FILE_CONTENT ))
2288 return DBUS_GERROR_INVALID_FILE_CONTENT ;
2289 else if (!strcmp (derr, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ))
2290 return DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
2292 return DBUS_GERROR_REMOTE_EXCEPTION;
2298 * @error: a #DBusError
2300 * Store the information from a DBus method error return into a
2301 * GError. For the normal case of an arbitrary remote process,
2302 * the error code will be DBUS_GERROR_REMOTE_EXCEPTION. Now,
2303 * DBus errors have two components; a message and a "name".
2304 * The former is an arbitrary (normally American English) string.
2305 * The second is a string like com.example.FooFailure which
2306 * programs can use as a conditional source. Because a GError
2307 * only has one string, we use a hack to encode both values:
2309 * <human readable string><null><error name><null>
2311 * You can use the following code to retrieve both values:
2313 * |[const char *msg = error->message;
2314 * size_t len = strlen(msg);
2315 * const char *error_name = msg+len+1;]|
2318 dbus_set_g_error (GError **gerror,
2323 code = dbus_error_to_gerror_code (error->name);
2324 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
2325 g_set_error (gerror, DBUS_GERROR,
2330 g_set_error (gerror, DBUS_GERROR,
2333 error->message ? error->message : "",
2339 dbus_g_error_info_free (gpointer p)
2341 DBusGErrorInfo *info;
2345 g_free (info->default_iface);
2350 * SECTION:dbus-gobject
2351 * @short_description: Exporting a #GObject remotely
2352 * @see_also: #GObject
2353 * @stability: Stable
2359 * dbus_glib_global_set_disable_legacy_property_access:
2361 * For historical reasons, DBus-GLib will allow read-only
2362 * access to every GObject property of an object exported
2363 * to the bus, regardless of whether or not the property
2364 * is listed in the type info installed with
2365 * dbus_g_object_type_install_info(). (Write access is
2368 * If you wish to restrict even read-only access, you
2369 * can call this method to globally change the behavior
2370 * for the entire process.
2375 dbus_glib_global_set_disable_legacy_property_access (void)
2377 disable_legacy_property_access = TRUE;
2381 * dbus_g_object_type_install_info:
2382 * @object_type: #GType for the object
2383 * @info: introspection data generated by #dbus-glib-tool
2385 * Install introspection information about the given object #GType
2386 * sufficient to allow methods on the object to be invoked by name.
2387 * The introspection information is normally generated by
2388 * dbus-glib-tool, then this function is called in the
2389 * class_init() for the object class.
2391 * Once introspection information has been installed, instances of the
2392 * object registered with #dbus_g_connection_register_g_object() can have
2393 * their methods invoked remotely.
2396 dbus_g_object_type_install_info (GType object_type,
2397 const DBusGObjectInfo *info)
2399 g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
2401 _dbus_g_value_types_init ();
2403 g_type_set_qdata (object_type,
2404 dbus_g_object_type_dbus_metadata_quark (),
2409 * dbus_g_error_domain_register:
2410 * @domain: the #GError domain
2411 * @default_iface: the prefix used for error values, or %NULL
2412 * @code_enum: a #GType for a #GEnum of the error codes
2414 * Register a #GError domain and set of codes with D-Bus. When an object
2415 * raises a #GError in the domain @domain from one of its D-Bus methods,
2416 * the D-Bus error name used will be @default_iface, followed by a dot,
2417 * followed by the #GEnumValue.value_nick corresponding to the #GError.code.
2418 * For D-Bus, it's conventional to use an error name (value_nick) that is
2421 * (For instance, if a D-Bus method <code>com.example.MyObject.GetThings</code>
2422 * can raise a #GError with domain <code>MY_ERROR</code> and code
2423 * <code>MY_ERROR_NOT_HAPPY</code>, you could call
2424 * <code>dbus_g_error_domain_register (MY_ERROR, "com.example.MyError",
2425 * MY_TYPE_ERROR)</code>, and set up the value_nick for
2426 * <code>MY_ERROR_NOT_HAPPY</code> to be <code>NotHappy</code>,
2427 * resulting in the D-Bus error string
2428 * <code>com.example.MyError.NotHappy</code>.)
2430 * If @default_iface is %NULL, the D-Bus interface of the method that failed
2433 * (For instance, if the above example had called
2434 * <code>dbus_g_error_domain_register (MY_ERROR, NULL, MY_TYPE_ERROR)</code>
2435 * instead, then the D-Bus error string would be
2436 * <code>com.example.MyObject.NotHappy</code>.)
2439 dbus_g_error_domain_register (GQuark domain,
2440 const char *default_iface,
2443 DBusGErrorInfo *info;
2445 g_return_if_fail (g_quark_to_string (domain) != NULL);
2446 g_return_if_fail (code_enum != G_TYPE_INVALID);
2447 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
2449 g_static_rw_lock_writer_lock (&globals_lock);
2451 if (error_metadata == NULL)
2452 g_datalist_init (&error_metadata);
2454 info = g_datalist_id_get_data (&error_metadata, domain);
2458 g_warning ("Metadata for error domain \"%s\" already registered\n",
2459 g_quark_to_string (domain));
2463 info = g_new0 (DBusGErrorInfo, 1);
2464 info->default_iface = g_strdup (default_iface);
2465 info->code_enum = code_enum;
2467 g_datalist_id_set_data_full (&error_metadata,
2470 dbus_g_error_info_free);
2473 g_static_rw_lock_writer_unlock (&globals_lock);
2476 /* Called when the object is destroyed */
2478 object_registration_object_died (gpointer user_data, GObject *dead)
2480 ObjectRegistration *o = user_data;
2482 g_assert (dead == o->object);
2484 /* this prevents the weak unref from taking place, which would cause an
2485 * assertion failure since the object has already gone... */
2488 /* ... while this results in a call to object_registration_unregistered */
2489 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection), o->object_path);
2493 * dbus_g_connection_unregister_g_object:
2494 * @connection: the D-BUS connection
2495 * @object: the object
2497 * Removes @object from the bus. Properties, methods, and signals
2498 * of the object can no longer be accessed remotely.
2501 dbus_g_connection_unregister_g_object (DBusGConnection *connection,
2504 GList *registrations, *iter;
2506 /* Copy the list before iterating it: it will be modified in
2507 * object_registration_free() each time an object path is unregistered.
2509 registrations = g_list_copy (g_object_get_data (object, "dbus_glib_object_registrations"));
2511 g_return_if_fail (registrations != NULL);
2513 for (iter = registrations; iter; iter = iter->next)
2515 ObjectRegistration *o = iter->data;
2516 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
2520 g_list_free (registrations);
2521 g_assert (g_object_get_data (object, "dbus_glib_object_registrations") == NULL);
2525 * dbus_g_connection_register_g_object:
2526 * @connection: the D-BUS connection
2527 * @at_path: the path where the object will live (the object's name)
2528 * @object: the object
2530 * Registers a #GObject at the given path. Properties, methods, and signals
2531 * of the object can then be accessed remotely. Methods are only available
2532 * if method introspection data has been added to the object's class
2533 * with dbus_g_object_type_install_info().
2535 * The registration will be cancelled if either the #DBusConnection or
2536 * the #GObject gets finalized, or if dbus_g_connection_unregister_g_object()
2539 * Note: If an object is registered multiple times, the first registration
2540 * takes priority for cases such as turning an object into an object path.
2543 dbus_g_connection_register_g_object (DBusGConnection *connection,
2544 const char *at_path,
2548 GSList *registrations, *iter;
2549 ObjectRegistration *o;
2550 gboolean is_first_registration;
2552 g_return_if_fail (connection != NULL);
2553 g_return_if_fail (at_path != NULL);
2554 g_return_if_fail (G_IS_OBJECT (object));
2556 /* This is a GSList of ObjectRegistration* */
2557 registrations = g_object_steal_data (object, "dbus_glib_object_registrations");
2559 for (iter = registrations; iter; iter = iter->next)
2563 /* Silently ignore duplicate registrations */
2564 if (strcmp (o->object_path, at_path) == 0 && o->connection == connection)
2568 is_first_registration = registrations == NULL;
2570 /* This is used to hook up signals below, but we do this check
2571 * before trying to register the object to make sure we have
2572 * introspection data for it.
2574 if (is_first_registration)
2576 info_list = lookup_object_info (object);
2577 if (info_list == NULL)
2579 g_warning ("No introspection data registered for object class \"%s\"",
2580 g_type_name (G_TYPE_FROM_INSTANCE (object)));
2587 o = object_registration_new (connection, at_path, object);
2589 if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
2591 &gobject_dbus_vtable,
2594 g_error ("Failed to register GObject with DBusConnection");
2595 object_registration_free (o);
2596 g_list_free (info_list);
2600 if (is_first_registration)
2602 /* This adds a hook into every signal for the object. Only do this
2603 * on the first registration, because inside the signal marshaller
2604 * we emit a signal for each registration.
2606 export_signals (connection, info_list, object);
2607 g_list_free (info_list);
2610 registrations = g_slist_append (registrations, o);
2611 g_object_set_data (object, "dbus_glib_object_registrations", registrations);
2615 * dbus_g_connection_lookup_g_object:
2616 * @connection: a #DBusGConnection
2621 * Returns: the object at path @at_path
2624 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
2625 const char *at_path)
2628 ObjectRegistration *o;
2630 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &p))
2637 return G_OBJECT (o->object);
2644 } DBusGFuncSignature;
2647 funcsig_hash (gconstpointer key)
2649 const DBusGFuncSignature *sig = key;
2655 types = sig->params;
2657 for (i = 0; i < sig->n_params; i++)
2659 ret += (int) (*types);
2667 funcsig_equal (gconstpointer aval,
2670 const DBusGFuncSignature *a = aval;
2671 const DBusGFuncSignature *b = bval;
2672 const GType *atypes;
2673 const GType *btypes;
2676 if (a->rettype != b->rettype
2677 || a->n_params != b->n_params)
2683 for (i = 0; i < a->n_params; i++)
2685 if (*btypes != *atypes)
2695 funcsig_free (DBusGFuncSignature *sig)
2697 g_free (sig->params);
2702 _dbus_gobject_lookup_marshaller (GType rettype,
2704 const GType *param_types)
2706 GClosureMarshal ret;
2707 DBusGFuncSignature sig;
2711 /* Convert to fundamental types */
2712 rettype = G_TYPE_FUNDAMENTAL (rettype);
2713 params = g_new (GType, n_params);
2714 for (i = 0; i < n_params; i++)
2715 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
2717 sig.rettype = rettype;
2718 sig.n_params = n_params;
2719 sig.params = params;
2721 g_static_rw_lock_reader_lock (&globals_lock);
2724 ret = g_hash_table_lookup (marshal_table, &sig);
2728 g_static_rw_lock_reader_unlock (&globals_lock);
2732 if (rettype == G_TYPE_NONE)
2735 ret = g_cclosure_marshal_VOID__VOID;
2736 else if (n_params == 1)
2740 case G_TYPE_BOOLEAN:
2741 ret = g_cclosure_marshal_VOID__BOOLEAN;
2744 ret = g_cclosure_marshal_VOID__UCHAR;
2747 ret = g_cclosure_marshal_VOID__INT;
2750 ret = g_cclosure_marshal_VOID__UINT;
2753 ret = g_cclosure_marshal_VOID__DOUBLE;
2756 ret = g_cclosure_marshal_VOID__STRING;
2759 ret = g_cclosure_marshal_VOID__BOXED;
2763 else if (n_params == 3
2764 && params[0] == G_TYPE_STRING
2765 && params[1] == G_TYPE_STRING
2766 && params[2] == G_TYPE_STRING)
2768 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
2778 * dbus_g_object_register_marshaller:
2779 * @marshaller: a GClosureMarshal to be used for invocation
2780 * @rettype: a GType for the return type of the function
2781 * @:... The parameter #GTypes, followed by %G_TYPE_INVALID
2783 * Register a #GClosureMarshal to be used for signal invocations,
2784 * giving its return type and a list of parameter types,
2785 * followed by %G_TYPE_INVALID.
2787 * This function will not be needed once GLib includes libffi.
2790 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
2798 va_start (args, rettype);
2800 types = g_array_new (TRUE, TRUE, sizeof (GType));
2802 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
2803 g_array_append_val (types, gtype);
2805 dbus_g_object_register_marshaller_array (marshaller, rettype,
2806 types->len, (GType*) types->data);
2808 g_array_free (types, TRUE);
2813 * dbus_g_object_register_marshaller_array:
2814 * @marshaller: a #GClosureMarshal to be used for invocation
2815 * @rettype: a #GType for the return type of the function
2816 * @n_types: number of function parameters
2817 * @types: a C array of GTypes values
2819 * Register a #GClosureMarshal to be used for signal invocations.
2820 * @see_also #dbus_g_object_register_marshaller
2823 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
2828 DBusGFuncSignature *sig;
2831 g_static_rw_lock_writer_lock (&globals_lock);
2833 if (marshal_table == NULL)
2834 marshal_table = g_hash_table_new_full (funcsig_hash,
2836 (GDestroyNotify) funcsig_free,
2838 sig = g_new0 (DBusGFuncSignature, 1);
2839 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
2840 sig->n_params = n_types;
2841 sig->params = g_new (GType, n_types);
2842 for (i = 0; i < n_types; i++)
2843 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
2845 g_hash_table_insert (marshal_table, sig, marshaller);
2847 g_static_rw_lock_writer_unlock (&globals_lock);
2851 * dbus_g_method_get_sender:
2852 * @context: the method context
2854 * Get the sender of a message so we can send a
2855 * "reply" later (i.e. send a message directly
2856 * to a service which invoked the method at a
2859 * Returns: the unique name of the sender. It
2860 * is up to the caller to free the returned string.
2863 dbus_g_method_get_sender (DBusGMethodInvocation *context)
2865 const gchar *sender;
2867 sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
2868 return g_strdup (sender);
2872 * dbus_g_method_get_reply:
2873 * @context: the method context
2875 * Get the reply message to append reply values
2876 * Used as a sidedoor when you can't generate dbus values
2877 * of the correct type due to glib binding limitations
2879 * Returns: a #DBusMessage with the reply
2882 dbus_g_method_get_reply (DBusGMethodInvocation *context)
2884 return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
2888 * dbus_g_method_send_reply:
2889 * Send a manually created reply message
2890 * @context: the method context
2891 * @reply: the reply message, will be unreffed
2893 * Used as a sidedoor when you can't generate dbus values
2894 * of the correct type due to glib binding limitations
2897 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
2899 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2900 dbus_message_unref (reply);
2902 dbus_g_connection_unref (context->connection);
2903 dbus_g_message_unref (context->message);
2909 * dbus_g_method_return:
2910 * @context: the method context
2912 * Send a return message for a given method invocation, with arguments.
2913 * This function also frees the sending context.
2916 dbus_g_method_return (DBusGMethodInvocation *context, ...)
2919 DBusMessageIter iter;
2925 /* This field was initialized inside invoke_object_method; we
2926 * carry it over through the async invocation to here.
2928 if (!context->send_reply)
2931 reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
2932 out_sig = method_output_signature_from_object_info (context->object, context->method);
2933 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
2935 dbus_message_iter_init_append (reply, &iter);
2937 va_start (args, context);
2938 for (i = 0; i < argsig->len; i++)
2940 GValue value = {0,};
2942 g_value_init (&value, g_array_index (argsig, GType, i));
2944 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
2947 g_warning("%s", error);
2950 _dbus_gvalue_marshal (&iter, &value);
2954 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2955 dbus_message_unref (reply);
2958 g_array_free (argsig, TRUE);
2961 dbus_g_connection_unref (context->connection);
2962 dbus_g_message_unref (context->message);
2967 * dbus_g_method_return_error:
2968 * @context: the method context
2969 * @error: the error to send
2971 * Send a error message for a given method invocation.
2972 * This function also frees the sending context.
2975 dbus_g_method_return_error (DBusGMethodInvocation *context, const GError *error)
2979 /* See comment in dbus_g_method_return */
2980 if (!context->send_reply)
2983 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
2984 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2985 dbus_message_unref (reply);
2988 dbus_g_connection_unref (context->connection);
2989 dbus_g_message_unref (context->message);
2994 _dbus_gobject_get_path (GObject *obj)
2996 GSList *registrations;
2997 ObjectRegistration *o;
2999 registrations = g_object_get_data (obj, "dbus_glib_object_registrations");
3001 if (registrations == NULL)
3004 /* First one to have been registered wins */
3005 o = registrations->data;
3007 return o->object_path;
3010 #ifdef DBUS_BUILD_TESTS
3014 _dummy_function (void)
3018 /* Data structures copied from one generated by current dbus-binding-tool;
3019 * we need to support this layout forever
3021 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
3022 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
3023 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
3024 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
3025 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
3026 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
3027 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
3028 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
3029 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
3030 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
3031 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
3032 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
3033 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
3034 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
3035 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
3036 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
3037 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
3038 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
3039 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
3040 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
3041 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
3042 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
3043 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
3044 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
3045 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
3046 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
3047 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
3048 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
3049 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
3050 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
3051 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
3054 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
3056 dbus_glib_internal_test_methods,
3058 "org.freedesktop.DBus.Tests.MyObject\0DoNothing\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Increment\0S\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetval\0S\0x\0I\0u\0arg1\0O\0F\0R\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetvalError\0S\0x\0I\0u\0arg1\0O\0F\0E\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ThrowError\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Uppercase\0S\0arg0\0I\0s\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyArgs\0S\0x\0I\0u\0str\0I\0s\0trouble\0I\0d\0d_ret\0O\0F\0N\0d\0str_ret\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyReturn\0S\0arg0\0O\0F\0N\0u\0arg1\0O\0F\0N\0s\0arg2\0O\0F\0N\0i\0arg3\0O\0F\0N\0u\0arg4\0O\0F\0N\0u\0arg5\0O\0C\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Stringify\0S\0val\0I\0v\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Unstringify\0S\0val\0I\0s\0arg1\0O\0F\0N\0v\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive1\0S\0arg0\0I\0au\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive2\0S\0arg0\0I\0u\0arg1\0O\0F\0N\0au\0\0org.freedesktop.DBus.Tests.MyObject\0ManyUppercase\0S\0arg0\0I\0as\0arg1\0O\0F\0N\0as\0\0org.freedesktop.DBus.Tests.MyObject\0StrHashLen\0S\0arg0\0I\0a{ss}\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0SendCar\0S\0arg0\0I\0(suv)\0arg1\0O\0F\0N\0(uo)\0\0org.freedesktop.DBus.Tests.MyObject\0GetHash\0S\0arg0\0O\0F\0N\0a{ss}\0\0org.freedesktop.DBus.Tests.MyObject\0RecArrays\0S\0val\0I\0aas\0arg1\0O\0F\0N\0aau\0\0org.freedesktop.DBus.Tests.MyObject\0Objpath\0S\0arg0\0I\0o\0arg1\0O\0C\0N\0o\0\0org.freedesktop.DBus.Tests.MyObject\0GetObjs\0S\0arg0\0O\0F\0N\0ao\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementVal\0S\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncIncrement\0A\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncThrowError\0A\0\0org.freedesktop.DBus.Tests.MyObject\0GetVal\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ManyStringify\0S\0arg0\0I\0a{sv}\0arg1\0O\0F\0N\0a{sv}\0\0org.freedesktop.DBus.Tests.MyObject\0EmitFrobnicate\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Terminate\0S\0\0org.freedesktop.DBus.Tests.FooObject\0GetValue\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignals\0S\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignal2\0S\0\0org.freedesktop.DBus.Tests.FooObject\0Terminate\0S\0\0\0",
3059 "org.freedesktop.DBus.Tests.MyObject\0Frobnicate\0org.freedesktop.DBus.Tests.FooObject\0Sig0\0org.freedesktop.DBus.Tests.FooObject\0Sig1\0org.freedesktop.DBus.Tests.FooObject\0Sig2\0\0",
3065 * @ingroup DBusGLibInternals
3066 * Unit test for GLib GObject integration ("skeletons")
3067 * Returns: #TRUE on success.
3070 _dbus_gobject_test (const char *test_data_dir)
3074 const char *arg_name;
3078 const char *arg_signature;
3079 const char *sigdata;
3081 const char *signame;
3083 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
3084 { "SetFoo", "set_foo" },
3086 { "GetFooBar", "get_foo_bar" },
3087 { "Hello", "hello" }
3089 /* Impossible-to-handle cases */
3090 /* { "FrobateUIHandler", "frobate_ui_handler" } */
3093 /* Test lookup in our hardcoded object info; if these tests fail
3094 * then it likely means you changed the generated object info in an
3095 * incompatible way and broke the lookup functions. In that case
3096 * you need to bump the version and use a new structure instead. */
3098 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3099 &(dbus_glib_internal_test_methods[0]));
3100 g_assert (*arg == '\0');
3103 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3104 &(dbus_glib_internal_test_methods[1]));
3105 g_assert (*arg != '\0');
3106 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3107 g_assert (!strcmp (arg_name, "x"));
3108 g_assert (arg_in == TRUE);
3109 g_assert (!strcmp (arg_signature, "u"));
3110 g_assert (*arg != '\0');
3111 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3112 g_assert (arg_in == FALSE);
3113 g_assert (retval == RETVAL_NONE);
3114 g_assert (!strcmp (arg_signature, "u"));
3115 g_assert (*arg == '\0');
3117 /* IncrementRetval */
3118 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3119 &(dbus_glib_internal_test_methods[2]));
3120 g_assert (*arg != '\0');
3121 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3122 g_assert (!strcmp (arg_name, "x"));
3123 g_assert (arg_in == TRUE);
3124 g_assert (!strcmp (arg_signature, "u"));
3125 g_assert (*arg != '\0');
3126 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3127 g_assert (retval == RETVAL_NOERROR);
3128 g_assert (arg_in == FALSE);
3129 g_assert (!strcmp (arg_signature, "u"));
3130 g_assert (*arg == '\0');
3132 /* IncrementRetvalError */
3133 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3134 &(dbus_glib_internal_test_methods[3]));
3135 g_assert (*arg != '\0');
3136 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3137 g_assert (!strcmp (arg_name, "x"));
3138 g_assert (arg_in == TRUE);
3139 g_assert (!strcmp (arg_signature, "u"));
3140 g_assert (*arg != '\0');
3141 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3142 g_assert (retval == RETVAL_ERROR);
3143 g_assert (arg_in == FALSE);
3144 g_assert (!strcmp (arg_signature, "u"));
3145 g_assert (*arg == '\0');
3148 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3149 &(dbus_glib_internal_test_methods[8]));
3150 g_assert (*arg != '\0');
3151 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3152 g_assert (!strcmp (arg_name, "val"));
3153 g_assert (arg_in == TRUE);
3154 g_assert (!strcmp (arg_signature, "v"));
3155 g_assert (*arg != '\0');
3156 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3157 g_assert (retval == RETVAL_NONE);
3158 g_assert (arg_in == FALSE);
3159 g_assert (!strcmp (arg_signature, "s"));
3160 g_assert (*arg == '\0');
3162 sigdata = dbus_glib_internal_test_object_info.exported_signals;
3163 g_assert (*sigdata != '\0');
3164 sigdata = signal_iterate (sigdata, &iface, &signame);
3165 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
3166 g_assert (!strcmp (signame, "Frobnicate"));
3167 g_assert (*sigdata != '\0');
3168 sigdata = signal_iterate (sigdata, &iface, &signame);
3169 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3170 g_assert (!strcmp (signame, "Sig0"));
3171 g_assert (*sigdata != '\0');
3172 sigdata = signal_iterate (sigdata, &iface, &signame);
3173 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3174 g_assert (!strcmp (signame, "Sig1"));
3175 g_assert (*sigdata != '\0');
3176 sigdata = signal_iterate (sigdata, &iface, &signame);
3177 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3178 g_assert (!strcmp (signame, "Sig2"));
3179 g_assert (*sigdata == '\0');
3183 while (i < (int) G_N_ELEMENTS (name_pairs))
3188 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
3189 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
3191 if (strcmp (uscore, name_pairs[i].uscore) != 0)
3193 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3194 name_pairs[i].wincaps, name_pairs[i].uscore,
3199 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
3201 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3202 name_pairs[i].uscore, name_pairs[i].wincaps,
3216 #endif /* DBUS_BUILD_TESTS */