diff options
author | Andy Holmes <andrew.g.r.holmes@gmail.com> | 2020-08-13 05:01:54 +0000 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2020-08-13 05:01:54 +0000 |
commit | 07221d6df68ad74ffee6e4234ab02a2ef43a38b9 (patch) | |
tree | 86c3586f5903865d3578294519d926e798292b87 | |
parent | 97de40b7769ccfa98edd871fc7c10f4378a49e6f (diff) | |
download | gjs-07221d6df68ad74ffee6e4234ab02a2ef43a38b9.tar.gz |
gdbus-wrapper: support multiple bus connections
Originally GjsDBusImplementation was written to only support a single
bus connection. Refactor it to support multiple connections, which
becomes relevant as we try to fix GNOME/gjs#332.
-rw-r--r-- | libgjs-private/gjs-gdbus-wrapper.c | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/libgjs-private/gjs-gdbus-wrapper.c b/libgjs-private/gjs-gdbus-wrapper.c index d534d9b4..f7361366 100644 --- a/libgjs-private/gjs-gdbus-wrapper.c +++ b/libgjs-private/gjs-gdbus-wrapper.c @@ -231,7 +231,7 @@ gjs_dbus_implementation_get_properties (GDBusInterfaceSkeleton *skeleton) { static void gjs_dbus_implementation_flush (GDBusInterfaceSkeleton *skeleton) { - GjsDBusImplementation *self = GJS_DBUS_IMPLEMENTATION (skeleton); + GjsDBusImplementation *self = GJS_DBUS_IMPLEMENTATION(skeleton); GVariantBuilder changed_props; GVariantBuilder invalidated_props; @@ -250,16 +250,27 @@ gjs_dbus_implementation_flush (GDBusInterfaceSkeleton *skeleton) { g_variant_builder_add(&invalidated_props, "s", prop_name); } - g_dbus_connection_emit_signal(g_dbus_interface_skeleton_get_connection(skeleton), - NULL, /* bus name */ - g_dbus_interface_skeleton_get_object_path(skeleton), - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - g_variant_new("(s@a{sv}@as)", - self->priv->ifaceinfo->name, - g_variant_builder_end(&changed_props), - g_variant_builder_end(&invalidated_props)), - NULL /* error */); + GList *connections = g_dbus_interface_skeleton_get_connections(skeleton); + const char *object_path = g_dbus_interface_skeleton_get_object_path(skeleton); + GVariant *properties = g_variant_new("(s@a{sv}@as)", + self->priv->ifaceinfo->name, + g_variant_builder_end(&changed_props), + g_variant_builder_end(&invalidated_props)); + g_variant_ref_sink(properties); + + for (const GList *iter = connections; iter; iter = iter->next) { + g_dbus_connection_emit_signal(G_DBUS_CONNECTION(iter->data), + NULL, /* bus name */ + object_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + properties, + NULL /* error */); + + g_object_unref(iter->data); + } + g_variant_unref(properties); + g_list_free(connections); g_hash_table_remove_all(self->priv->outstanding_properties); g_clear_handle_id(&self->priv->idle_id, g_source_remove); @@ -366,13 +377,69 @@ gjs_dbus_implementation_emit_signal (GjsDBusImplementation *self, gchar *signal_name, GVariant *parameters) { - GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (self); - - g_dbus_connection_emit_signal(g_dbus_interface_skeleton_get_connection(skeleton), - NULL, - g_dbus_interface_skeleton_get_object_path(skeleton), - self->priv->ifaceinfo->name, - signal_name, - parameters, - NULL); + GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON(self); + GList *connections = g_dbus_interface_skeleton_get_connections(skeleton); + const char *object_path = g_dbus_interface_skeleton_get_object_path(skeleton); + + if (parameters != NULL) + g_variant_ref_sink(parameters); + + for (const GList *iter = connections; iter; iter = iter->next) { + g_dbus_connection_emit_signal(G_DBUS_CONNECTION(iter->data), + NULL, + object_path, + self->priv->ifaceinfo->name, + signal_name, + parameters, + NULL); + + g_object_unref(iter->data); + } + g_variant_unref(parameters); + g_list_free(connections); +} + +/** + * gjs_dbus_implementation_unexport: + * @self: a #GjsDBusImplementation + * + * Stops exporting @self on all connections it is exported on. + * + * To unexport @self from only a single connection, use + * gjs_dbus_implementation_skeleton_unexport_from_connection() + */ +void +gjs_dbus_implementation_unexport(GjsDBusImplementation *self) { + GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON(self); + + g_hash_table_remove_all(self->priv->outstanding_properties); + g_clear_handle_id(&self->priv->idle_id, g_source_remove); + + g_dbus_interface_skeleton_unexport(skeleton); +} + +/** + * gjs_dbus_implementation_unexport_from_connection: + * @self: a #GjsDBusImplementation + * @connection: a #GDBusConnection + * + * Stops exporting @self on @connection. + * + * To stop exporting on all connections the interface is exported on, + * use gjs_dbus_implementation_unexport(). + */ +void +gjs_dbus_implementation_unexport_from_connection(GjsDBusImplementation *self, + GDBusConnection *connection) { + GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON(self); + GList *connections = g_dbus_interface_skeleton_get_connections(skeleton); + + if (g_list_length(connections) <= 1) { + g_hash_table_remove_all(self->priv->outstanding_properties); + g_clear_handle_id(&self->priv->idle_id, g_source_remove); + } + + g_list_free_full(connections, g_object_unref); + + g_dbus_interface_skeleton_unexport_from_connection(skeleton, connection); } |