static void
on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data)
{
	on_get_connection_unix_process_id_args *args = user_data;
	DBusMessage *reply = NULL;
	DBusError error = DBUS_ERROR_INIT;
	dbus_uint32_t caller_pid = 0;
	GkdSecretService *self;
	ServiceClient *client;
	const gchar *caller;

	g_return_if_fail (GKD_SECRET_IS_SERVICE (args->self));
	self = args->self;

	/* Get the resulting process ID */
	reply = dbus_pending_call_steal_reply (pending);
	g_return_if_fail (reply);

	caller = dbus_message_get_sender (args->message);
	g_return_if_fail (caller);

	client = g_hash_table_lookup (self->clients, caller);
	if (client == NULL) {

		/* An error returned from GetConnectionUnixProcessID */
		if (dbus_set_error_from_message (&error, reply)) {
			g_message ("couldn't get the caller's unix process id: %s", error.message);
			caller_pid = 0;
			dbus_error_free (&error);

		/* A PID was returned from GetConnectionUnixProcessID */
		} else {
			if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &caller_pid, DBUS_TYPE_INVALID))
				g_return_if_reached ();
		}

		/* Initialize the client object */
		client = g_new0 (ServiceClient, 1);
		client->caller_peer = g_strdup (caller);
		client->caller_pid = caller_pid;
		if (caller_pid != 0)
			client->caller_exec = egg_unix_credentials_executable (caller_pid);
		client->app.applicationData = client;
		client->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
		client->prompts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);

		g_hash_table_replace (self->clients, client->caller_peer, client);

		/* Update default collection each time someone connects */
		update_default (self, TRUE);
	}

	dbus_message_unref (reply);

	/* Dispatch the original message again */
	service_dispatch_message (self, args->message);
}
static DBusHandlerResult
gkd_secret_service_filter_handler (DBusConnection *conn, DBusMessage *message, gpointer user_data)
{
	GkdSecretService *self = user_data;
	const gchar *object_name;
	const gchar *old_owner;
	const gchar *new_owner;
	const gchar *path;
	const gchar *interface;

	g_return_val_if_fail (conn && message, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
	g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);

	/* org.freedesktop.DBus.NameOwnerChanged(STRING name, STRING old_owner, STRING new_owner) */
	if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged") &&
	    dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &object_name,
	                           DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner,
	                           DBUS_TYPE_INVALID)) {

		/*
		 * A peer is connecting or disconnecting from the bus,
		 * remove any client info, when client gone.
		 */

		g_return_val_if_fail (object_name && new_owner, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
		if (g_str_equal (new_owner, "") && object_name[0] == ':')
			g_hash_table_remove (self->clients, object_name);

		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	/*
	 * If the path is a within our object tree, then we do our own dispatch.
	 */
	path = dbus_message_get_path (message);
	switch (dbus_message_get_type (message)) {

	/* Dispatch any method call on our interfaces, for our objects */
	case DBUS_MESSAGE_TYPE_METHOD_CALL:
		if (object_path_has_prefix (path, SECRET_SERVICE_PATH)) {
			interface = dbus_message_get_interface (message);
			if (interface == NULL ||
			    g_str_has_prefix (interface, SECRET_INTERFACE_PREFIX) ||
			    g_str_equal (interface, DBUS_INTERFACE_PROPERTIES) ||
			    g_str_equal (interface, INTERNAL_SERVICE_INTERFACE) ||
			    g_str_equal (interface, DBUS_INTERFACE_INTROSPECTABLE)) {
				service_dispatch_message (self, message);
				return DBUS_HANDLER_RESULT_HANDLED;
			}
		}
		break;

	/* Dispatch any signal for one of our objects */
	case DBUS_MESSAGE_TYPE_SIGNAL:
		if (object_path_has_prefix (path, SECRET_SERVICE_PATH)) {
			service_dispatch_message (self, message);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
		break;

	default:
		break;
	}

	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}