[gnome-keyring: 1/2] dbus: Implement <node> children in DBus introspection data



commit e337f08d3eaf17b65d739b791618da29ebefd25e
Author: Stef Walter <stefw collabora co uk>
Date:   Mon Sep 26 14:34:45 2011 +0200

    dbus: Implement <node> children in DBus introspection data
    
     * This allows tools like d-feet to see what's going on in
       the service.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=660127

 daemon/dbus/gkd-dbus-util.c         |   65 ++++++++-
 daemon/dbus/gkd-dbus-util.h         |    4 +-
 daemon/dbus/gkd-secret-introspect.c |    9 +
 daemon/dbus/gkd-secret-introspect.h |    1 +
 daemon/dbus/gkd-secret-objects.c    |  291 ++++++++++++++++++++++-------------
 daemon/dbus/gkd-secret-objects.h    |   16 ++
 daemon/dbus/gkd-secret-prompt.c     |    3 +-
 daemon/dbus/gkd-secret-service.c    |   72 +++++++++-
 daemon/dbus/gkd-secret-session.c    |    3 +-
 daemon/dbus/gkd-secret-unlock.c     |    3 +-
 10 files changed, 356 insertions(+), 111 deletions(-)
---
diff --git a/daemon/dbus/gkd-dbus-util.c b/daemon/dbus/gkd-dbus-util.c
index 4596ea5..3907c60 100644
--- a/daemon/dbus/gkd-dbus-util.c
+++ b/daemon/dbus/gkd-dbus-util.c
@@ -53,10 +53,59 @@ gkd_dbus_interface_match (const gchar *interface, const gchar *match)
 	return strcmp (interface, match) == 0;
 }
 
-DBusMessage*
-gkd_dbus_introspect_handle (DBusMessage *message, const gchar *data)
+static gchar *
+build_child_node_xml (const gchar *parent,
+                      const gchar **children)
+{
+	GString *result;
+	const gchar *child;
+	guint i;
+
+	result = g_string_new ("");
+	for (i = 0; children != NULL && children[i] != NULL; i++) {
+		if (children[i][0] == '/') {
+			if (!g_str_has_prefix (children[i], parent)) {
+				g_warning ("in introspection data child '%s' is not descendant of parent '%s'",
+				           children[i], parent);
+				continue;
+			}
+			child = children[i] + strlen (parent);
+			while (child[0] == '/')
+				child++;
+		} else {
+			child = children[i];
+		}
+
+		g_string_append_printf (result, "\t<node name=\"%s\"/>\n", child);
+	}
+
+	return g_string_free (result, FALSE);
+}
+
+static gboolean
+string_replace (GString *string,
+                const gchar *search,
+                const gchar *replace)
+{
+	const gchar *pos;
+
+	pos = strstr (string->str, search);
+	if (pos == NULL)
+		return FALSE;
+
+	g_string_erase (string, pos - string->str, strlen (search));
+	g_string_insert (string, pos - string->str, replace);
+	return TRUE;
+}
+
+DBusMessage *
+gkd_dbus_introspect_handle (DBusMessage *message,
+                            const gchar *data,
+                            const gchar **children)
 {
 	DBusMessage *reply;
+	GString *output = NULL;
+	gchar *nodes;
 
 	g_return_val_if_fail (message, NULL);
 	g_return_val_if_fail (data, NULL);
@@ -64,9 +113,21 @@ gkd_dbus_introspect_handle (DBusMessage *message, const gchar *data)
 	if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") &&
 	    dbus_message_get_args (message, NULL, DBUS_TYPE_INVALID)) {
 
+		if (children != NULL) {
+			output = g_string_new (data);
+			nodes = build_child_node_xml (dbus_message_get_path (message), children);
+			if (!string_replace (output, "<!-- children@-->", nodes))
+				g_warning ("introspection data contained no location for child nodes");
+			g_free (nodes);
+			data = output->str;
+		}
+
 		reply = dbus_message_new_method_return (message);
 		if (!dbus_message_append_args (reply, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID))
 			g_return_val_if_reached (NULL);
+
+		if (output)
+			g_string_free (output, TRUE);
 		return reply;
 	}
 
diff --git a/daemon/dbus/gkd-dbus-util.h b/daemon/dbus/gkd-dbus-util.h
index 44478db..c5506bb 100644
--- a/daemon/dbus/gkd-dbus-util.h
+++ b/daemon/dbus/gkd-dbus-util.h
@@ -34,6 +34,8 @@ GType         gkd_dbus_connection_get_boxed_type          (void) G_GNUC_CONST;
 
 gboolean      gkd_dbus_interface_match                    (const gchar *interface, const gchar *match);
 
-DBusMessage*  gkd_dbus_introspect_handle                  (DBusMessage *message, const gchar *data);
+DBusMessage*  gkd_dbus_introspect_handle                  (DBusMessage *message,
+                                                           const gchar *data,
+                                                           const gchar **children);
 
 #endif /* GKD_DBUS_H */
diff --git a/daemon/dbus/gkd-secret-introspect.c b/daemon/dbus/gkd-secret-introspect.c
index cb4aa31..816ea3e 100644
--- a/daemon/dbus/gkd-secret-introspect.c
+++ b/daemon/dbus/gkd-secret-introspect.c
@@ -25,6 +25,13 @@
 
 #include "gkd-secret-introspect.h"
 
+const gchar *gkd_secret_introspect_root =
+	"<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n"
+	"	'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n"
+	"<node>\n"
+	"	<node name='org/freedesktop/secrets'/>\n"
+	"</node>\n";
+
 const gchar *gkd_secret_introspect_collection =
 	"<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n"
 	"	'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n"
@@ -84,6 +91,7 @@ const gchar *gkd_secret_introspect_collection =
 	"		</signal>\n"
 	"	</interface>\n"
 	"\n"
+	"<!-- children@-->"
 	"</node>\n";
 
 const gchar *gkd_secret_introspect_item =
@@ -254,6 +262,7 @@ const gchar *gkd_secret_introspect_service =
 	"\n"
 	"	</interface>\n"
 	"\n"
+	"<!-- children@-->"
 	"</node>\n";
 
 const gchar *gkd_secret_introspect_session =
diff --git a/daemon/dbus/gkd-secret-introspect.h b/daemon/dbus/gkd-secret-introspect.h
index 6a3fcf7..ba7a228 100644
--- a/daemon/dbus/gkd-secret-introspect.h
+++ b/daemon/dbus/gkd-secret-introspect.h
@@ -26,6 +26,7 @@
 
 #include <glib.h>
 
+extern const gchar *gkd_secret_introspect_root;
 extern const gchar *gkd_secret_introspect_collection;
 extern const gchar *gkd_secret_introspect_item;
 extern const gchar *gkd_secret_introspect_prompt;
diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c
index 325ae04..28a278a 100644
--- a/daemon/dbus/gkd-secret-objects.c
+++ b/daemon/dbus/gkd-secret-objects.c
@@ -100,87 +100,6 @@ parse_object_path (GkdSecretObjects *self, const gchar *path, gchar **collection
 	return TRUE;
 }
 
-static void
-iter_append_item_path (const gchar *base, GckObject *object, DBusMessageIter *iter)
-{
-	GError *error = NULL;
-	gpointer identifier;
-	gsize n_identifier;
-	gchar *path;
-	gchar *alloc = NULL;
-
-	if (base == NULL) {
-		identifier = gck_object_get_data (object, CKA_G_COLLECTION, NULL, &n_identifier, &error);
-		if (!identifier) {
-			g_warning ("couldn't get item collection identifier: %s", egg_error_message (error));
-			g_clear_error (&error);
-			return;
-		}
-
-		base = alloc = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
-		g_free (identifier);
-	}
-
-	identifier = gck_object_get_data (object, CKA_ID, NULL, &n_identifier, &error);
-	if (identifier == NULL) {
-		g_warning ("couldn't get item identifier: %s", egg_error_message (error));
-		g_clear_error (&error);
-	} else {
-		path = gkd_secret_util_build_path (base, identifier, n_identifier);
-		g_free (identifier);
-		dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &path);
-		g_free (path);
-	}
-
-	g_free (alloc);
-}
-
-static void
-iter_append_item_paths (const gchar *base, GList *items, DBusMessageIter *iter)
-{
-	DBusMessageIter array;
-	GList *l;
-
-	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "o", &array);
-
-	for (l = items; l; l = g_list_next (l))
-		iter_append_item_path (base, l->data, &array);
-
-	dbus_message_iter_close_container (iter, &array);
-}
-
-static void
-iter_append_collection_paths (GList *collections, DBusMessageIter *iter)
-{
-	DBusMessageIter array;
-	gpointer identifier;
-	gsize n_identifier;
-	GError *error = NULL;
-	gchar *path;
-	GList *l;
-
-	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "o", &array);
-
-	for (l = collections; l; l = g_list_next (l)) {
-
-		identifier = gck_object_get_data (l->data, CKA_ID, NULL, &n_identifier, &error);
-		if (identifier == NULL) {
-			g_warning ("couldn't get collection identifier: %s", egg_error_message (error));
-			g_clear_error (&error);
-			continue;
-		}
-
-		path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
-		g_free (identifier);
-
-		dbus_message_iter_append_basic (&array, DBUS_TYPE_OBJECT_PATH, &path);
-		g_free (path);
-	}
-
-	dbus_message_iter_close_container (iter, &array);
-}
-
-
 static DBusMessage*
 object_property_get (GckObject *object, DBusMessage *message,
                      const gchar *prop_name)
@@ -455,7 +374,7 @@ item_message_handler (GkdSecretObjects *self, GckObject *object, DBusMessage *me
 		return item_property_getall (object, message);
 
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_item);
+		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_item, NULL);
 
 	return NULL;
 }
@@ -641,6 +560,43 @@ collection_find_matching_item (GkdSecretObjects *self, GckSession *session,
 	return result;
 }
 
+static gchar *
+object_path_for_item (const gchar *base,
+                      GckObject *object)
+{
+	GError *error = NULL;
+	gpointer identifier;
+	gsize n_identifier;
+	gchar *alloc = NULL;
+	gchar *path = NULL;
+
+	if (base == NULL) {
+		identifier = gck_object_get_data (object, CKA_G_COLLECTION, NULL, &n_identifier, &error);
+		if (!identifier) {
+			g_warning ("couldn't get item collection identifier: %s", egg_error_message (error));
+			g_clear_error (&error);
+			return NULL;
+		}
+
+		base = alloc = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
+		g_free (identifier);
+	}
+
+	identifier = gck_object_get_data (object, CKA_ID, NULL, &n_identifier, &error);
+	if (identifier == NULL) {
+		g_warning ("couldn't get item identifier: %s", egg_error_message (error));
+		g_clear_error (&error);
+		path = NULL;
+
+	} else {
+		path = gkd_secret_util_build_path (base, identifier, n_identifier);
+		g_free (identifier);
+	}
+
+	g_free (alloc);
+	return path;
+}
+
 static DBusMessage*
 collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMessage *message)
 {
@@ -720,7 +676,8 @@ collection_method_create_item (GkdSecretObjects *self, GckObject *object, DBusMe
 	/* Build up the item identifier */
 	reply = dbus_message_new_method_return (message);
 	dbus_message_iter_init_append (reply, &iter);
-	iter_append_item_path (base, item, &iter);
+	path = object_path_for_item (base, item);
+	dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &path);
 	prompt = "/";
 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &prompt);
 
@@ -778,6 +735,36 @@ collection_method_delete (GkdSecretObjects *self, GckObject *object, DBusMessage
 	return reply;
 }
 
+static void
+on_each_path_append_to_array (GkdSecretObjects *self,
+                              const gchar *path,
+                              GckObject *object,
+                              gpointer user_data)
+{
+	GPtrArray *array = user_data;
+	g_ptr_array_add (array, g_strdup (path));
+}
+
+static DBusMessage *
+collection_introspect (GkdSecretObjects *self,
+                       GckObject *object,
+                       DBusMessage *message)
+{
+	GPtrArray *names;
+	DBusMessage *reply;
+
+	names = g_ptr_array_new_with_free_func (g_free);
+	gkd_secret_objects_foreach_item (self, message, dbus_message_get_path (message),
+	                                 on_each_path_append_to_array, names);
+	g_ptr_array_add (names, NULL);
+
+	reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_collection,
+	                                    (const gchar **)names->pdata);
+
+	g_ptr_array_unref (names);
+	return reply;
+}
+
 static DBusMessage*
 collection_message_handler (GkdSecretObjects *self, GckObject *object, DBusMessage *message)
 {
@@ -805,8 +792,9 @@ collection_message_handler (GkdSecretObjects *self, GckObject *object, DBusMessa
 	else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "GetAll"))
 		return collection_property_getall (self, object, message);
 
+	/* org.freedesktop.DBus.Introspectable.Introspect() */
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_collection);
+		return collection_introspect (self, object, message);
 
 	return NULL;
 }
@@ -1089,11 +1077,30 @@ gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller,
 	return object;
 }
 
+static void
+objects_foreach_item (GkdSecretObjects *self,
+                      GList *items,
+                      const gchar *base,
+                      GkdSecretObjectsForeach callback,
+                      gpointer user_data)
+{
+	gchar *path;
+	GList *l;
+
+	for (l = items; l; l = g_list_next (l)) {
+		path = object_path_for_item (base, l->data);
+		(callback) (self, path, l->data, user_data);
+		g_free (path);
+	}
+}
+
 void
-gkd_secret_objects_append_item_paths (GkdSecretObjects *self, const gchar *base,
-                                      DBusMessageIter *iter, DBusMessage *message)
+gkd_secret_objects_foreach_item (GkdSecretObjects *self,
+                                 DBusMessage *message,
+                                 const gchar *base,
+                                 GkdSecretObjectsForeach callback,
+                                 gpointer user_data)
 {
-	DBusMessageIter variant;
 	GckSession *session;
 	GError *error = NULL;
 	gchar *identifier;
@@ -1101,9 +1108,8 @@ gkd_secret_objects_append_item_paths (GkdSecretObjects *self, const gchar *base,
 	GckAttributes *attrs;
 
 	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
-	g_return_if_fail (base);
-	g_return_if_fail (iter);
-	g_return_if_fail (message);
+	g_return_if_fail (base != NULL);
+	g_return_if_fail (callback != NULL);
 
 	/* The session we're using to access the object */
 	session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
@@ -1121,9 +1127,8 @@ gkd_secret_objects_append_item_paths (GkdSecretObjects *self, const gchar *base,
 	gck_attributes_unref (attrs);
 
 	if (error == NULL) {
-		dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant);
-		iter_append_item_paths (base, items, &variant);
-		dbus_message_iter_close_container (iter, &variant);
+		objects_foreach_item (self, items, base, callback, user_data);
+
 	} else {
 		g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error));
 		g_clear_error (&error);
@@ -1133,18 +1138,56 @@ gkd_secret_objects_append_item_paths (GkdSecretObjects *self, const gchar *base,
 	g_free (identifier);
 }
 
+static void
+on_object_path_append_to_iter (GkdSecretObjects *self,
+                               const gchar *path,
+                               GckObject *object,
+                               gpointer user_data)
+{
+	DBusMessageIter *array = user_data;
+	dbus_message_iter_append_basic (array, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
 void
-gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, DBusMessageIter *iter,
-                                            DBusMessage *message)
+gkd_secret_objects_append_item_paths (GkdSecretObjects *self,
+                                      const gchar *base,
+                                      DBusMessageIter *iter,
+                                      DBusMessage *message)
 {
 	DBusMessageIter variant;
-	GError *error = NULL;
-	GckAttributes *attrs;
+	DBusMessageIter array;
+
+	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
+	g_return_if_fail (base);
+	g_return_if_fail (iter);
+	g_return_if_fail (message);
+
+
+	dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant);
+	dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "o", &array);
+
+	gkd_secret_objects_foreach_item (self, message, base, on_object_path_append_to_iter, &array);
+
+	dbus_message_iter_close_container (&variant, &array);
+	dbus_message_iter_close_container (iter, &variant);
+}
+
+void
+gkd_secret_objects_foreach_collection (GkdSecretObjects *self,
+                                       DBusMessage *message,
+                                       GkdSecretObjectsForeach callback,
+                                       gpointer user_data)
+{
 	GckSession *session;
-	GList *colls;
+	GckAttributes *attrs;
+	GError *error = NULL;
+	GList *collections, *l;
+	gpointer identifier;
+	gsize n_identifier;
+	gchar *path;
 
 	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
-	g_return_if_fail (iter && message);
+	g_return_if_fail (callback);
 
 	/* The session we're using to access the object */
 	session = gkd_secret_service_get_pkcs11_session (self->service, dbus_message_get_sender (message));
@@ -1153,7 +1196,7 @@ gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, DBusMessageI
 	attrs = gck_attributes_new ();
 	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
 
-	colls = gck_session_find_objects (session, attrs, NULL, &error);
+	collections = gck_session_find_objects (session, attrs, NULL, &error);
 
 	gck_attributes_unref (attrs);
 
@@ -1163,10 +1206,43 @@ gkd_secret_objects_append_collection_paths (GkdSecretObjects *self, DBusMessageI
 		return;
 	}
 
+	for (l = collections; l; l = g_list_next (l)) {
+
+		identifier = gck_object_get_data (l->data, CKA_ID, NULL, &n_identifier, &error);
+		if (identifier == NULL) {
+			g_warning ("couldn't get collection identifier: %s", egg_error_message (error));
+			g_clear_error (&error);
+			continue;
+		}
+
+		path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
+		g_free (identifier);
+
+		(callback) (self, path, l->data, user_data);
+		g_free (path);
+	}
+
+	gck_list_unref_free (collections);
+}
+
+void
+gkd_secret_objects_append_collection_paths (GkdSecretObjects *self,
+                                            DBusMessageIter *iter,
+                                            DBusMessage *message)
+{
+	DBusMessageIter variant;
+	DBusMessageIter array;
+
+	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
+	g_return_if_fail (iter && message);
+
 	dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "ao", &variant);
-	iter_append_collection_paths (colls, &variant);
+	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "o", &array);
+
+	gkd_secret_objects_foreach_collection (self, message, on_object_path_append_to_iter, &array);
+
+	dbus_message_iter_close_container (iter, &array);
 	dbus_message_iter_close_container (iter, &variant);
-	gck_list_unref_free (colls);
 }
 
 DBusMessage*
@@ -1176,6 +1252,7 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
 	GckAttributes *attrs;
 	GckAttribute *attr;
 	DBusMessageIter iter;
+	DBusMessageIter array;
 	GckObject *search;
 	GckSession *session;
 	DBusMessage *reply;
@@ -1251,8 +1328,14 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
 	/* Prepare the reply message */
 	reply = dbus_message_new_method_return (message);
 	dbus_message_iter_init_append (reply, &iter);
-	iter_append_item_paths (NULL, unlocked, &iter);
-	iter_append_item_paths (NULL, locked, &iter);
+
+	dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &array);
+	objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_iter, &iter);
+	dbus_message_iter_close_container (&iter, &array);
+
+	dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &array);
+	objects_foreach_item (self, locked, NULL, on_object_path_append_to_iter, &iter);
+	dbus_message_iter_close_container (&iter, &array);
 
 	g_list_free (locked);
 	g_list_free (unlocked);
diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-objects.h
index 2d54509..9138856 100644
--- a/daemon/dbus/gkd-secret-objects.h
+++ b/daemon/dbus/gkd-secret-objects.h
@@ -43,6 +43,11 @@ struct _GkdSecretObjectsClass {
 	GObjectClass parent_class;
 };
 
+typedef void        (*GkdSecretObjectsForeach)                  (GkdSecretObjects *self,
+                                                                 const gchar *path,
+                                                                 GckObject *object,
+                                                                 gpointer user_data);
+
 GType               gkd_secret_objects_get_type                 (void);
 
 DBusMessage*        gkd_secret_objects_dispatch                  (GkdSecretObjects *self,
@@ -55,6 +60,17 @@ DBusMessage*        gkd_secret_objects_handle_search_items       (GkdSecretObjec
 DBusMessage*        gkd_secret_objects_handle_get_secrets        (GkdSecretObjects *self,
                                                                   DBusMessage *message);
 
+void                gkd_secret_objects_foreach_collection        (GkdSecretObjects *self,
+                                                                  DBusMessage *message,
+                                                                  GkdSecretObjectsForeach callback,
+                                                                  gpointer user_data);
+
+void                gkd_secret_objects_foreach_item              (GkdSecretObjects *self,
+                                                                  DBusMessage *message,
+                                                                  const gchar *base,
+                                                                  GkdSecretObjectsForeach callback,
+                                                                  gpointer user_data);
+
 void                gkd_secret_objects_append_collection_paths   (GkdSecretObjects *self,
                                                                   DBusMessageIter *iter,
                                                                   DBusMessage *message);
diff --git a/daemon/dbus/gkd-secret-prompt.c b/daemon/dbus/gkd-secret-prompt.c
index 9201ec5..c1edd4d 100644
--- a/daemon/dbus/gkd-secret-prompt.c
+++ b/daemon/dbus/gkd-secret-prompt.c
@@ -283,8 +283,9 @@ gkd_secret_prompt_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *m
 	else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Dismiss"))
 		reply = prompt_method_dismiss (self, message);
 
+	/* org.freedesktop.DBus.Introspectable.Introspect() */
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt);
+		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt, NULL);
 
 	return reply;
 }
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 599e2e5..0cd208a 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -805,6 +805,52 @@ service_method_unlock_with_master_password (GkdSecretService *self, DBusMessage
 	return reply;
 }
 
+static void
+on_each_path_append_to_array (GkdSecretObjects *self,
+                              const gchar *path,
+                              GckObject *object,
+                              gpointer user_data)
+{
+	GPtrArray *array = user_data;
+	g_ptr_array_add (array, g_strdup (path));
+}
+
+static DBusMessage *
+service_introspect (GkdSecretService *self,
+                    DBusMessage *message)
+{
+	GPtrArray *names;
+	DBusMessage *reply;
+	ServiceClient *client;
+	const gchar *caller;
+	const gchar *path;
+	GHashTableIter iter;
+
+	names = g_ptr_array_new_with_free_func (g_free);
+	gkd_secret_objects_foreach_collection (self->objects, message,
+	                                       on_each_path_append_to_array,
+	                                       names);
+
+	/* Lookup all sessions and prompts for this client */
+	caller = dbus_message_get_sender (message);
+	if (caller != NULL) {
+		client = g_hash_table_lookup (self->clients, caller);
+		if (client != NULL) {
+			g_hash_table_iter_init (&iter, client->dispatch);
+			while (g_hash_table_iter_next (&iter, (gpointer *)&path, NULL))
+				g_ptr_array_add (names, g_strdup (path));
+		}
+	}
+
+	g_ptr_array_add (names, NULL);
+
+	reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_collection,
+	                                    (const gchar **)names->pdata);
+
+	g_ptr_array_unref (names);
+	return reply;
+}
+
 static DBusMessage*
 service_message_handler (GkdSecretService *self, DBusMessage *message)
 {
@@ -875,12 +921,31 @@ service_message_handler (GkdSecretService *self, DBusMessage *message)
 	else if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "GetAll"))
 		return service_property_getall (self, message);
 
+	/* org.freedesktop.DBus.Introspectable.Introspect() */
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_service);
+		return service_introspect (self, message);
 
 	return NULL;
 }
 
+static gboolean
+root_dispatch_message (GkdSecretService *self,
+                       DBusMessage *message)
+{
+	DBusMessage *reply = NULL;
+
+	if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
+		reply = gkd_dbus_introspect_handle (message, gkd_secret_introspect_root, NULL);
+
+	if (reply != NULL) {
+		dbus_connection_send (self->connection, reply, NULL);
+		dbus_message_unref (reply);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 static void
 service_dispatch_message (GkdSecretService *self, DBusMessage *message)
 {
@@ -987,6 +1052,11 @@ gkd_secret_service_filter_handler (DBusConnection *conn, DBusMessage *message, g
 
 	/* Dispatch any method call on our interfaces, for our objects */
 	case DBUS_MESSAGE_TYPE_METHOD_CALL:
+		if (path != NULL && g_str_equal (path, "/")) {
+			if (root_dispatch_message (self, message))
+				return DBUS_HANDLER_RESULT_HANDLED;
+		}
+
 		if (object_path_has_prefix (path, SECRET_SERVICE_PATH)) {
 			interface = dbus_message_get_interface (message);
 			if (interface == NULL ||
diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c
index 483c79c..d59d8f2 100644
--- a/daemon/dbus/gkd-secret-session.c
+++ b/daemon/dbus/gkd-secret-session.c
@@ -314,8 +314,9 @@ gkd_secret_session_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *
 	else if (dbus_message_is_method_call (message, SECRET_SESSION_INTERFACE, "Close"))
 		return session_method_close (self, message);
 
+	/* org.freedesktop.DBus.Introspectable.Introspect() */
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_session);
+		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_session, NULL);
 
 	return NULL;
 }
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index 0c466e7..428c2d3 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -371,8 +371,9 @@ gkd_secret_unlock_real_dispatch_message (GkdSecretDispatch *base, DBusMessage *m
 	else if (dbus_message_is_method_call (message, SECRET_PROMPT_INTERFACE, "Dismiss"))
 		reply = prompt_method_dismiss (self, message);
 
+	/* org.freedesktop.DBus.Introspectable.Introspect() */
 	else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE))
-		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt);
+		return gkd_dbus_introspect_handle (message, gkd_secret_introspect_prompt, NULL);
 
 	return reply;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]