diff options
author | David Zeuthen <davidz@redhat.com> | 2010-04-26 21:50:56 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-04-26 21:50:56 -0400 |
commit | 0980145e2b394eb884d27e43e7bc0838a95cb9b9 (patch) | |
tree | 45b453a58c94119983efcb7681676d53bcac3aaf | |
parent | ea25fb53d2f3da90b5b01086e8edcc380fe31d4e (diff) |
Add GBusNameWatcherFlags enumeration
This is mostly so it's easy to automatically launch services. E.g.
$ ./example-watch-proxy -n com.redhat.virt.manager \
-o /com/redhat/virt/manager \
-i com.redhat.virt.manager \
-p -a
+++ Acquired proxy object for remote object owned by :1.444
bus: Session Bus
name: com.redhat.virt.manager
object path: /com/redhat/virt/manager
interface: com.redhat.virt.manager
properties:
will actually make the bus launch Virt Manager and wait for it to take
the name com.redhat.virt.manage before on_proxy_appeared() is called.
Also fix a bug where proxies weren't constructed if properties are
unwanted and the object has no properties.
-rw-r--r-- | gdbus/example-unix-fd-client.c | 1 | ||||
-rw-r--r-- | gdbus/example-watch-name.c | 8 | ||||
-rw-r--r-- | gdbus/example-watch-proxy.c | 17 | ||||
-rw-r--r-- | gdbus/gdbusenums.h | 24 | ||||
-rw-r--r-- | gdbus/gdbusnamewatching.c | 106 | ||||
-rw-r--r-- | gdbus/gdbusnamewatching.h | 1 | ||||
-rw-r--r-- | gdbus/gdbusproxy.c | 14 | ||||
-rw-r--r-- | gdbus/gdbusproxywatching.c | 3 | ||||
-rw-r--r-- | gdbus/gdbusproxywatching.h | 1 | ||||
-rw-r--r-- | gdbus/tests/introspection.c | 1 | ||||
-rw-r--r-- | gdbus/tests/names.c | 3 | ||||
-rw-r--r-- | gdbus/tests/proxy.c | 1 | ||||
-rw-r--r-- | gdbus/tests/threading.c | 1 |
13 files changed, 160 insertions, 21 deletions
diff --git a/gdbus/example-unix-fd-client.c b/gdbus/example-unix-fd-client.c index 6729913..9e9678d 100644 --- a/gdbus/example-unix-fd-client.c +++ b/gdbus/example-unix-fd-client.c @@ -119,6 +119,7 @@ main (int argc, char *argv[]) watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gtk.GDBus.TestServer", + G_BUS_NAME_WATCHER_FLAGS_NONE, on_name_appeared, on_name_vanished, NULL, diff --git a/gdbus/example-watch-name.c b/gdbus/example-watch-name.c index 24e4df9..c907484 100644 --- a/gdbus/example-watch-name.c +++ b/gdbus/example-watch-name.c @@ -2,11 +2,13 @@ static gchar *opt_name = NULL; static gboolean opt_system_bus = FALSE; +static gboolean opt_auto_start = FALSE; static GOptionEntry opt_entries[] = { { "name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Name to watch", NULL }, { "system-bus", 's', 0, G_OPTION_ARG_NONE, &opt_system_bus, "Use the system-bus instead of the session-bus", NULL }, + { "auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_auto_start, "Instruct the bus to launch an owner for the name", NULL}, { NULL} }; @@ -39,6 +41,7 @@ main (int argc, char *argv[]) GMainLoop *loop; GOptionContext *opt_context; GError *error; + GBusNameWatcherFlags flags; g_type_init (); @@ -60,8 +63,13 @@ main (int argc, char *argv[]) goto out; } + flags = G_BUS_NAME_WATCHER_FLAGS_NONE; + if (opt_auto_start) + flags |= G_BUS_NAME_WATCHER_FLAGS_AUTO_START; + watcher_id = g_bus_watch_name (opt_system_bus ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION, opt_name, + flags, on_name_appeared, on_name_vanished, NULL, diff --git a/gdbus/example-watch-proxy.c b/gdbus/example-watch-proxy.c index c768f58..8528e78 100644 --- a/gdbus/example-watch-proxy.c +++ b/gdbus/example-watch-proxy.c @@ -4,6 +4,8 @@ static gchar *opt_name = NULL; static gchar *opt_object_path = NULL; static gchar *opt_interface = NULL; static gboolean opt_system_bus = FALSE; +static gboolean opt_auto_start = FALSE; +static gboolean opt_no_properties = FALSE; static GOptionEntry opt_entries[] = { @@ -11,6 +13,8 @@ static GOptionEntry opt_entries[] = { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_object_path, "Object path of the remote object", NULL }, { "interface", 'i', 0, G_OPTION_ARG_STRING, &opt_interface, "D-Bus interface of remote object", NULL }, { "system-bus", 's', 0, G_OPTION_ARG_NONE, &opt_system_bus, "Use the system-bus instead of the session-bus", NULL }, + { "auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_auto_start, "Instruct the bus to launch an owner for the name", NULL}, + { "no-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_no_properties, "Do not load properties", NULL}, { NULL} }; @@ -128,6 +132,8 @@ main (int argc, char *argv[]) GMainLoop *loop; GOptionContext *opt_context; GError *error; + GBusNameWatcherFlags flags; + GDBusProxyFlags proxy_flags; g_type_init (); @@ -151,12 +157,21 @@ main (int argc, char *argv[]) goto out; } + flags = G_BUS_NAME_WATCHER_FLAGS_NONE; + if (opt_auto_start) + flags |= G_BUS_NAME_WATCHER_FLAGS_AUTO_START; + + proxy_flags = G_DBUS_PROXY_FLAGS_NONE; + if (opt_no_properties) + proxy_flags |= G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES; + watcher_id = g_bus_watch_proxy (opt_system_bus ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION, opt_name, + flags, opt_object_path, opt_interface, G_TYPE_DBUS_PROXY, - G_DBUS_PROXY_FLAGS_NONE, + proxy_flags, on_proxy_appeared, on_proxy_vanished, NULL, diff --git a/gdbus/gdbusenums.h b/gdbus/gdbusenums.h index 64a080e..c40d658 100644 --- a/gdbus/gdbusenums.h +++ b/gdbus/gdbusenums.h @@ -61,12 +61,11 @@ typedef enum /** * GBusNameOwnerFlags: * @G_BUS_NAME_OWNER_FLAGS_NONE: No flags set. - * @G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT: Allow another message connection to take the name. - * @G_BUS_NAME_OWNER_FLAGS_REPLACE: If another message bus connection - * owns the name and have specified #G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, then - * take the name from the other connection. + * @G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT: Allow another message bus connection to claim the the name. + * @G_BUS_NAME_OWNER_FLAGS_REPLACE: If another message bus connection owns the name and have + * specified #G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, then take the name from the other connection. * - * Flags used when constructing a #GBusNameOwner. + * Flags used in g_bus_own_name(). */ typedef enum { @@ -76,6 +75,21 @@ typedef enum } GBusNameOwnerFlags; /** + * GBusNameWatcherFlags: + * @G_BUS_NAME_WATCHER_FLAGS_NONE: No flags set. + * @G_BUS_NAME_WATCHER_FLAGS_AUTO_START: If no-one owns the name when + * beginning to watch the name, ask the bus to launch an owner for the + * name. + * + * Flags used in g_bus_watch_name(). + */ +typedef enum +{ + G_BUS_NAME_WATCHER_FLAGS_NONE = 0, + G_BUS_NAME_WATCHER_FLAGS_AUTO_START = (1<<0) +} GBusNameWatcherFlags; + +/** * GDBusProxyFlags: * @G_DBUS_PROXY_FLAGS_NONE: No flags set. * @G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES: Don't load properties. diff --git a/gdbus/gdbusnamewatching.c b/gdbus/gdbusnamewatching.c index ef030f2..fe6cc41 100644 --- a/gdbus/gdbusnamewatching.c +++ b/gdbus/gdbusnamewatching.c @@ -58,6 +58,7 @@ typedef struct volatile gint ref_count; guint id; gchar *name; + GBusNameWatcherFlags flags; gchar *name_owner; GBusNameAppearedCallback name_appeared_handler; GBusNameVanishedCallback name_vanished_handler; @@ -356,6 +357,77 @@ get_name_owner_cb (GObject *source_object, /* ---------------------------------------------------------------------------------------------------- */ static void +invoke_get_name_owner (Client *client) +{ + g_dbus_connection_invoke_method (client->connection, + "org.freedesktop.DBus", /* bus name */ + "/org/freedesktop/DBus", /* object path */ + "org.freedesktop.DBus", /* interface name */ + "GetNameOwner", /* method name */ + g_variant_new ("(s)", client->name), + G_DBUS_INVOKE_METHOD_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) get_name_owner_cb, + client_ref (client)); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +start_service_by_name_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + Client *client = user_data; + GVariant *result; + + result = NULL; + + result = g_dbus_connection_invoke_method_finish (client->connection, + res, + NULL); + if (result != NULL) + { + guint32 start_service_result; + g_variant_get (result, "(u)", &start_service_result); + + if (start_service_result == 1) /* DBUS_START_REPLY_SUCCESS */ + { + invoke_get_name_owner (client); + } + else if (start_service_result == 2) /* DBUS_START_REPLY_ALREADY_RUNNING */ + { + invoke_get_name_owner (client); + } + else + { + g_warning ("Unexpected reply %d from StartServiceByName() method", start_service_result); + call_vanished_handler (client, FALSE); + client->initialized = TRUE; + } + } + else + { + /* Errors are not unexpected; the bus will reply e.g. + * + * org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.Epiphany2 + * was not provided by any .service files + * + * so just report vanished. + */ + call_vanished_handler (client, FALSE); + client->initialized = TRUE; + } + + if (result != NULL) + g_variant_unref (result); + client_unref (client); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void has_connection (Client *client) { /* listen for disconnection */ @@ -375,18 +447,25 @@ has_connection (Client *client) client, NULL); - /* check owner */ - g_dbus_connection_invoke_method (client->connection, - "org.freedesktop.DBus", /* bus name */ - "/org/freedesktop/DBus", /* object path */ - "org.freedesktop.DBus", /* interface name */ - "GetNameOwner", /* method name */ - g_variant_new ("(s)", client->name), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) get_name_owner_cb, - client_ref (client)); + if (client->flags & G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + g_dbus_connection_invoke_method (client->connection, + "org.freedesktop.DBus", /* bus name */ + "/org/freedesktop/DBus", /* object path */ + "org.freedesktop.DBus", /* interface name */ + "StartServiceByName", /* method name */ + g_variant_new ("(su)", client->name, 0), + G_DBUS_INVOKE_METHOD_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) start_service_by_name_cb, + client_ref (client)); + } + else + { + /* check owner */ + invoke_get_name_owner (client); + } } @@ -416,6 +495,7 @@ connection_get_cb (GObject *source_object, * g_bus_watch_name: * @bus_type: The type of bus to watch a name on (can't be #G_BUS_TYPE_NONE). * @name: The name (well-known or unique) to watch. + * @flags: Flags from the #GBusNameWatcherFlags enumeration. * @name_appeared_handler: Handler to invoke when @name is known to exist. * @name_vanished_handler: Handler to invoke when @name is known to not exist. * @user_data: User data to pass to handlers. @@ -457,6 +537,7 @@ connection_get_cb (GObject *source_object, guint g_bus_watch_name (GBusType bus_type, const gchar *name, + GBusNameWatcherFlags flags, GBusNameAppearedCallback name_appeared_handler, GBusNameVanishedCallback name_vanished_handler, gpointer user_data, @@ -475,6 +556,7 @@ g_bus_watch_name (GBusType bus_type, client->ref_count = 1; client->id = next_global_id++; /* TODO: uh oh, handle overflow */ client->name = g_strdup (name); + client->flags = flags; client->name_appeared_handler = name_appeared_handler; client->name_vanished_handler = name_vanished_handler; client->user_data = user_data; diff --git a/gdbus/gdbusnamewatching.h b/gdbus/gdbusnamewatching.h index 1f74e26..2692c66 100644 --- a/gdbus/gdbusnamewatching.h +++ b/gdbus/gdbusnamewatching.h @@ -60,6 +60,7 @@ typedef void (*GBusNameVanishedCallback) (GDBusConnection *connection, guint g_bus_watch_name (GBusType bus_type, const gchar *name, + GBusNameWatcherFlags flags, GBusNameAppearedCallback name_appeared_handler, GBusNameVanishedCallback name_vanished_handler, gpointer user_data, diff --git a/gdbus/gdbusproxy.c b/gdbus/gdbusproxy.c index cbdd5e4..e248e99 100644 --- a/gdbus/gdbusproxy.c +++ b/gdbus/gdbusproxy.c @@ -839,9 +839,17 @@ async_initable_init_finish (GAsyncInitable *initable, result = g_simple_async_result_get_op_res_gpointer (simple); if (result == NULL) - goto out; - - process_get_all_reply (proxy, result); + { + if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)) + { + g_simple_async_result_propagate_error (simple, error); + goto out; + } + } + else + { + process_get_all_reply (proxy, result); + } subscribe_to_signals (proxy); diff --git a/gdbus/gdbusproxywatching.c b/gdbus/gdbusproxywatching.c index 24390ff..185b347 100644 --- a/gdbus/gdbusproxywatching.c +++ b/gdbus/gdbusproxywatching.c @@ -263,6 +263,7 @@ on_name_vanished (GDBusConnection *connection, * g_bus_watch_proxy: * @bus_type: The type of bus to watch a name on (can't be #G_BUS_TYPE_NONE). * @name: The name (well-known or unique) to watch. + * @flags: Flags from the #GBusNameWatcherFlags enumeration. * @object_path: The object path of the remote object to watch. * @interface_name: The D-Bus interface name for the proxy. * @interface_type: The #GType for the kind of proxy to create. This must be a #GDBusProxy derived type. @@ -309,6 +310,7 @@ on_name_vanished (GDBusConnection *connection, guint g_bus_watch_proxy (GBusType bus_type, const gchar *name, + GBusNameWatcherFlags flags, const gchar *object_path, const gchar *interface_name, GType interface_type, @@ -342,6 +344,7 @@ g_bus_watch_proxy (GBusType bus_type, g_main_context_ref (client->main_context); client->name_watcher_id = g_bus_watch_name (bus_type, name, + flags, on_name_appeared, on_name_vanished, client, diff --git a/gdbus/gdbusproxywatching.h b/gdbus/gdbusproxywatching.h index 2349af9..b63e09f 100644 --- a/gdbus/gdbusproxywatching.h +++ b/gdbus/gdbusproxywatching.h @@ -65,6 +65,7 @@ typedef void (*GBusProxyVanishedCallback) (GDBusConnection *connection, guint g_bus_watch_proxy (GBusType bus_type, const gchar *name, + GBusNameWatcherFlags flags, const gchar *object_path, const gchar *interface_name, GType interface_type, diff --git a/gdbus/tests/introspection.c b/gdbus/tests/introspection.c index cde1eab..19b500f 100644 --- a/gdbus/tests/introspection.c +++ b/gdbus/tests/introspection.c @@ -116,6 +116,7 @@ test_introspection_parser (void) watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION, "com.example.TestService", + G_BUS_NAME_WATCHER_FLAGS_NONE, "/com/example/TestObject", "com.example.Frob", G_TYPE_DBUS_PROXY, diff --git a/gdbus/tests/names.c b/gdbus/tests/names.c index b66200f..161dc1a 100644 --- a/gdbus/tests/names.c +++ b/gdbus/tests/names.c @@ -548,6 +548,7 @@ test_bus_watch_name (void) data.expect_null_connection = TRUE; id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gtk.GDBus.Name1", + G_BUS_NAME_WATCHER_FLAGS_NONE, name_appeared_handler, name_vanished_handler, &data, @@ -587,6 +588,7 @@ test_bus_watch_name (void) data.num_vanished = 0; id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gtk.GDBus.Name1", + G_BUS_NAME_WATCHER_FLAGS_NONE, name_appeared_handler, name_vanished_handler, &data, @@ -619,6 +621,7 @@ test_bus_watch_name (void) data.num_free_func = 0; id = g_bus_watch_name (G_BUS_TYPE_SESSION, "org.gtk.GDBus.Name1", + G_BUS_NAME_WATCHER_FLAGS_NONE, name_appeared_handler, name_vanished_handler, &data, diff --git a/gdbus/tests/proxy.c b/gdbus/tests/proxy.c index 13647d0..5172276 100644 --- a/gdbus/tests/proxy.c +++ b/gdbus/tests/proxy.c @@ -450,6 +450,7 @@ test_proxy (void) watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION, "com.example.TestService", + G_BUS_NAME_WATCHER_FLAGS_NONE, "/com/example/TestObject", "com.example.Frob", G_TYPE_DBUS_PROXY, diff --git a/gdbus/tests/threading.c b/gdbus/tests/threading.c index 00e7ca7..f575ab8 100644 --- a/gdbus/tests/threading.c +++ b/gdbus/tests/threading.c @@ -462,6 +462,7 @@ test_method_calls_in_thread (void) watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION, "com.example.TestService", + G_BUS_NAME_WATCHER_FLAGS_NONE, "/com/example/TestObject", "com.example.Frob", G_TYPE_DBUS_PROXY, |