summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-04-26 21:50:56 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-04-26 21:50:56 -0400
commit0980145e2b394eb884d27e43e7bc0838a95cb9b9 (patch)
tree45b453a58c94119983efcb7681676d53bcac3aaf
parentea25fb53d2f3da90b5b01086e8edcc380fe31d4e (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.c1
-rw-r--r--gdbus/example-watch-name.c8
-rw-r--r--gdbus/example-watch-proxy.c17
-rw-r--r--gdbus/gdbusenums.h24
-rw-r--r--gdbus/gdbusnamewatching.c106
-rw-r--r--gdbus/gdbusnamewatching.h1
-rw-r--r--gdbus/gdbusproxy.c14
-rw-r--r--gdbus/gdbusproxywatching.c3
-rw-r--r--gdbus/gdbusproxywatching.h1
-rw-r--r--gdbus/tests/introspection.c1
-rw-r--r--gdbus/tests/names.c3
-rw-r--r--gdbus/tests/proxy.c1
-rw-r--r--gdbus/tests/threading.c1
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,