mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 19:06:15 +01:00
Bug 621213 – GDBusProxy and well-known names
Allow constructing a GDBusProxy for well-known names as discussed here http://mail.gnome.org/archives/gtk-devel-list/2009-October/msg00075.html including test cases. Make it possible to create a GDBusProxy for a GBusType instead of a GDBusConnection. This requires G_BUS_TYPE_NONE so add that too. Nuke g_bus_watch_proxy() since one can now more or less use GDBusProxy for this. Port gdbus-example-watch-proxy to this new API and include this example in the GDBusProxy doc page. Also nuke the GType parameter from the GDBusProxy constructors as requested here: https://bugzilla.gnome.org/show_bug.cgi?id=621229 Also update the porting guide and other API docs for this change. Also fix a bug in the signal dispatching code so each subscriber only get notified once, not N times, for the same signal. Also add a test case for this. https://bugzilla.gnome.org/show_bug.cgi?id=621213 Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
parent
e0f8d30dea
commit
32f2e9a85b
@ -143,7 +143,6 @@
|
||||
<title>Highlevel D-Bus Support</title>
|
||||
<xi:include href="xml/gdbusnameowning.xml"/>
|
||||
<xi:include href="xml/gdbusnamewatching.xml"/>
|
||||
<xi:include href="xml/gdbusproxywatching.xml"/>
|
||||
<xi:include href="xml/gdbusproxy.xml"/>
|
||||
</chapter>
|
||||
<chapter id="utils">
|
||||
|
@ -2482,17 +2482,6 @@ g_bus_watch_name_with_closures
|
||||
g_bus_watch_name_on_connection_with_closures
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gdbusproxywatching</FILE>
|
||||
GBusProxyAppearedCallback
|
||||
GBusProxyVanishedCallback
|
||||
g_bus_watch_proxy
|
||||
g_bus_watch_proxy_on_connection
|
||||
g_bus_unwatch_proxy
|
||||
g_bus_watch_proxy_with_closures
|
||||
g_bus_watch_proxy_on_connection_with_closures
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gdbuserror</FILE>
|
||||
GDBusError
|
||||
@ -2521,9 +2510,13 @@ GDBusProxyClass
|
||||
g_dbus_proxy_new
|
||||
g_dbus_proxy_new_finish
|
||||
g_dbus_proxy_new_sync
|
||||
g_dbus_proxy_new_for_bus
|
||||
g_dbus_proxy_new_for_bus_finish
|
||||
g_dbus_proxy_new_for_bus_sync
|
||||
g_dbus_proxy_get_flags
|
||||
g_dbus_proxy_get_connection
|
||||
g_dbus_proxy_get_unique_bus_name
|
||||
g_dbus_proxy_get_name
|
||||
g_dbus_proxy_get_name_owner
|
||||
g_dbus_proxy_get_object_path
|
||||
g_dbus_proxy_get_interface_name
|
||||
g_dbus_proxy_get_default_timeout
|
||||
|
@ -1,5 +1,5 @@
|
||||
<chapter>
|
||||
<title>Migrating from dbus-glib to GDBus</title>
|
||||
<title>Migrating to GDBus</title>
|
||||
|
||||
<section>
|
||||
<title>Conceptual differences</title>
|
||||
@ -47,8 +47,8 @@
|
||||
<row><entry>#DBusGMethodInvocation</entry><entry>#GDBusMethodInvocation</entry></row>
|
||||
<row><entry>dbus_g_bus_get()</entry><entry>g_bus_get_sync(), also see
|
||||
g_bus_get()</entry></row>
|
||||
<row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync(), also see
|
||||
g_dbus_proxy_new()</entry></row>
|
||||
<row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync() and
|
||||
g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()</entry></row>
|
||||
<row><entry>dbus_g_proxy_add_signal()</entry><entry>not needed, use the generic #GDBusProxy::g-signal</entry></row>
|
||||
<row><entry>dbus_g_proxy_connect_signal()</entry><entry>use g_signal_connect() with #GDBusProxy::g-signal</entry></row>
|
||||
<row><entry>dbus_g_connection_register_g_object()</entry><entry>g_dbus_connection_register_object()</entry></row>
|
||||
@ -177,46 +177,28 @@ on_name_acquired (GDBusConnection *connection,
|
||||
the current owner of the name, and that owner can change over time.
|
||||
</para>
|
||||
<para>
|
||||
In contrast, #GDBusProxy instances are always bound to a unique name.
|
||||
To get a proxy for a well-known name, you either have to call
|
||||
GetNameOwner yourself and construct a proxy for the unique name
|
||||
of the current name owner, or use the high-level API. The latter
|
||||
option is highly recommended:
|
||||
The same can be achieved with #GDBusProxy:
|
||||
<informalexample><programlisting><![CDATA[
|
||||
static void
|
||||
on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* start to use proxy */
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SYSTEM,
|
||||
"org.freedesktop.Accounts",
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
"/org/freedesktop/Accounts",
|
||||
"org.freedesktop.Accounts",
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_BUS_PROXY_FLAGS_NONE,
|
||||
on_proxy_appeared,
|
||||
on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
"org.freedesktop.Accounts",
|
||||
"/org/freedesktop/Accounts",
|
||||
"org.freedesktop.Accounts",
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
]]>
|
||||
</programlisting></informalexample>
|
||||
Like g_bus_own_name(), g_bus_watch_proxy() is asynchronous and
|
||||
you are expected to enter your mainloop to await the on_proxy_appeared()
|
||||
callback. Note that GDBus also does all the setup operations for the
|
||||
proxy asynchronously, and only calls your callback when the proxy
|
||||
is ready for use.
|
||||
For an added layer of safety, you can specify what D-Bus
|
||||
interface the proxy is expected to conform to by using the
|
||||
#GDBusInterfaceInfo type.
|
||||
</para>
|
||||
<para>
|
||||
Additionally, #GDBusProxy loads, caches and tracks changes to
|
||||
the D-Bus properties on the remote object. It also sets up match
|
||||
rules so D-Bus signals from the remote object are delivered
|
||||
locally.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -89,7 +89,6 @@ gdbus_headers = \
|
||||
gdbusmessage.h \
|
||||
gdbusnameowning.h \
|
||||
gdbusnamewatching.h \
|
||||
gdbusproxywatching.h \
|
||||
gdbusproxy.h \
|
||||
gdbusintrospection.h \
|
||||
gdbusmethodinvocation.h \
|
||||
@ -110,7 +109,6 @@ gdbus_sources = \
|
||||
gdbusmessage.h gdbusmessage.c \
|
||||
gdbusnameowning.h gdbusnameowning.c \
|
||||
gdbusnamewatching.h gdbusnamewatching.c \
|
||||
gdbusproxywatching.h gdbusproxywatching.c \
|
||||
gdbusproxy.h gdbusproxy.c \
|
||||
gdbusprivate.h gdbusprivate.c \
|
||||
gdbusintrospection.h gdbusintrospection.c \
|
||||
|
@ -144,7 +144,7 @@
|
||||
*
|
||||
* This class is rarely used directly in D-Bus clients. If you are writing
|
||||
* an D-Bus client, it is often easier to use the g_bus_own_name(),
|
||||
* g_bus_watch_name() or g_bus_watch_proxy() APIs.
|
||||
* g_bus_watch_name() or g_dbus_proxy_new_for_bus() APIs.
|
||||
*
|
||||
* <example id="gdbus-server"><title>D-Bus server example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
|
||||
*
|
||||
@ -265,9 +265,9 @@ struct _GDBusConnectionPrivate
|
||||
GHashTable *map_method_serial_to_send_message_data; /* guint32 -> SendMessageData* */
|
||||
|
||||
/* Maps used for managing signal subscription */
|
||||
GHashTable *map_rule_to_signal_data; /* gchar* -> SignalData */
|
||||
GHashTable *map_id_to_signal_data; /* guint -> SignalData */
|
||||
GHashTable *map_sender_to_signal_data_array; /* gchar* -> GPtrArray* of SignalData */
|
||||
GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */
|
||||
GHashTable *map_id_to_signal_data; /* id (guint) -> SignalData */
|
||||
GHashTable *map_sender_unique_name_to_signal_data_array; /* unique sender (gchar*) -> GPtrArray* of SignalData */
|
||||
|
||||
/* Maps used for managing exported objects and subtrees */
|
||||
GHashTable *map_object_path_to_eo; /* gchar* -> ExportedObject* */
|
||||
@ -408,7 +408,7 @@ g_dbus_connection_finalize (GObject *object)
|
||||
purge_all_signal_subscriptions (connection);
|
||||
g_hash_table_unref (connection->priv->map_rule_to_signal_data);
|
||||
g_hash_table_unref (connection->priv->map_id_to_signal_data);
|
||||
g_hash_table_unref (connection->priv->map_sender_to_signal_data_array);
|
||||
g_hash_table_unref (connection->priv->map_sender_unique_name_to_signal_data_array);
|
||||
|
||||
g_hash_table_unref (connection->priv->map_id_to_ei);
|
||||
g_hash_table_unref (connection->priv->map_object_path_to_eo);
|
||||
@ -785,10 +785,10 @@ g_dbus_connection_init (GDBusConnection *connection)
|
||||
g_str_equal);
|
||||
connection->priv->map_id_to_signal_data = g_hash_table_new (g_direct_hash,
|
||||
g_direct_equal);
|
||||
connection->priv->map_sender_to_signal_data_array = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL);
|
||||
connection->priv->map_sender_unique_name_to_signal_data_array = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL);
|
||||
|
||||
connection->priv->map_object_path_to_eo = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
@ -2372,6 +2372,7 @@ typedef struct
|
||||
{
|
||||
gchar *rule;
|
||||
gchar *sender;
|
||||
gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
|
||||
gchar *interface_name;
|
||||
gchar *member;
|
||||
gchar *object_path;
|
||||
@ -2389,16 +2390,17 @@ typedef struct
|
||||
} SignalSubscriber;
|
||||
|
||||
static void
|
||||
signal_data_free (SignalData *data)
|
||||
signal_data_free (SignalData *signal_data)
|
||||
{
|
||||
g_free (data->rule);
|
||||
g_free (data->sender);
|
||||
g_free (data->interface_name);
|
||||
g_free (data->member);
|
||||
g_free (data->object_path);
|
||||
g_free (data->arg0);
|
||||
g_array_free (data->subscribers, TRUE);
|
||||
g_free (data);
|
||||
g_free (signal_data->rule);
|
||||
g_free (signal_data->sender);
|
||||
g_free (signal_data->sender_unique_name);
|
||||
g_free (signal_data->interface_name);
|
||||
g_free (signal_data->member);
|
||||
g_free (signal_data->object_path);
|
||||
g_free (signal_data->arg0);
|
||||
g_array_free (signal_data->subscribers, TRUE);
|
||||
g_free (signal_data);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
@ -2444,7 +2446,6 @@ add_match_rule (GDBusConnection *connection,
|
||||
"org.freedesktop.DBus", /* interface */
|
||||
"AddMatch");
|
||||
g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
|
||||
|
||||
error = NULL;
|
||||
if (!g_dbus_connection_send_message_unlocked (connection,
|
||||
message,
|
||||
@ -2490,7 +2491,7 @@ remove_match_rule (GDBusConnection *connection,
|
||||
static gboolean
|
||||
is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
|
||||
{
|
||||
return g_strcmp0 (signal_data->sender, "org.freedesktop.DBus") == 0 &&
|
||||
return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
|
||||
g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
|
||||
g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
|
||||
(g_strcmp0 (signal_data->member, "NameLost") == 0 ||
|
||||
@ -2502,7 +2503,7 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
|
||||
/**
|
||||
* g_dbus_connection_signal_subscribe:
|
||||
* @connection: A #GDBusConnection.
|
||||
* @sender: Sender name to match on. Must be either <literal>org.freedesktop.DBus</literal> (for listening to signals from the message bus daemon) or a unique name or %NULL to listen from all senders.
|
||||
* @sender: Sender name to match on (unique or well-known name) or %NULL to listen from all senders.
|
||||
* @interface_name: D-Bus interface name to match on or %NULL to match on all interfaces.
|
||||
* @member: D-Bus signal name to match on or %NULL to match on all signals.
|
||||
* @object_path: Object path to match on or %NULL to match on all object paths.
|
||||
@ -2517,14 +2518,18 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
|
||||
* linkend="g-main-context-push-thread-default">thread-default main
|
||||
* loop</link> of the thread you are calling this method from.
|
||||
*
|
||||
* It is considered a programming error to use this function if @connection is closed.
|
||||
* It is considered a programming error to use this function if
|
||||
* @connection is closed.
|
||||
*
|
||||
* Note that if @sender is not <literal>org.freedesktop.DBus</literal> (for listening to signals from the
|
||||
* message bus daemon), then it needs to be a unique bus name or %NULL (for listening to signals from any
|
||||
* name) - you cannot pass a name like <literal>com.example.MyApp</literal>.
|
||||
* Use e.g. g_bus_watch_name() to find the unique name for the owner of the name you are interested in. Also note
|
||||
* that this function does not remove a subscription if @sender vanishes from the bus. You have to manually
|
||||
* call g_dbus_connection_signal_unsubscribe() to remove a subscription.
|
||||
* If @connection is not a message bus connection, @sender must be
|
||||
* %NULL.
|
||||
*
|
||||
* If @sender is a well-known name note that @callback is invoked with
|
||||
* the unique name for the owner of @sender, not the well-known name
|
||||
* as one would expect. This is because the message bus rewrites the
|
||||
* name. As such, to avoid certain race conditions, users should be
|
||||
* tracking the name owner of the well-known name and use that when
|
||||
* processing the received signal.
|
||||
*
|
||||
* Returns: A subscription identifier that can be used with g_dbus_connection_signal_unsubscribe().
|
||||
*
|
||||
@ -2545,6 +2550,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
SignalData *signal_data;
|
||||
SignalSubscriber subscriber;
|
||||
GPtrArray *signal_data_array;
|
||||
const gchar *sender_unique_name;
|
||||
|
||||
/* Right now we abort if AddMatch() fails since it can only fail with the bus being in
|
||||
* an OOM condition. We might want to change that but that would involve making
|
||||
@ -2558,8 +2564,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
|
||||
g_return_val_if_fail (!g_dbus_connection_is_closed (connection), 0);
|
||||
g_return_val_if_fail (sender == NULL || ((strcmp (sender, "org.freedesktop.DBus") == 0 || sender[0] == ':') &&
|
||||
(connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)), 0);
|
||||
g_return_val_if_fail (sender == NULL || (g_dbus_is_name (sender) && (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)), 0);
|
||||
g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), 0);
|
||||
g_return_val_if_fail (member == NULL || g_dbus_is_member_name (member), 0);
|
||||
g_return_val_if_fail (object_path == NULL || g_variant_is_object_path (object_path), 0);
|
||||
@ -2569,8 +2574,10 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
|
||||
rule = args_to_rule (sender, interface_name, member, object_path, arg0);
|
||||
|
||||
if (sender == NULL)
|
||||
sender = "";
|
||||
if (sender != NULL && (g_dbus_is_unique_name (sender) || g_strcmp0 (sender, "org.freedesktop.DBus") == 0))
|
||||
sender_unique_name = sender;
|
||||
else
|
||||
sender_unique_name = "";
|
||||
|
||||
subscriber.callback = callback;
|
||||
subscriber.user_data = user_data;
|
||||
@ -2590,13 +2597,14 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
}
|
||||
|
||||
signal_data = g_new0 (SignalData, 1);
|
||||
signal_data->rule = rule;
|
||||
signal_data->sender = g_strdup (sender);
|
||||
signal_data->interface_name = g_strdup (interface_name);
|
||||
signal_data->member = g_strdup (member);
|
||||
signal_data->object_path = g_strdup (object_path);
|
||||
signal_data->arg0 = g_strdup (arg0);
|
||||
signal_data->subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
||||
signal_data->rule = rule;
|
||||
signal_data->sender = g_strdup (sender);
|
||||
signal_data->sender_unique_name = g_strdup (sender_unique_name);
|
||||
signal_data->interface_name = g_strdup (interface_name);
|
||||
signal_data->member = g_strdup (member);
|
||||
signal_data->object_path = g_strdup (object_path);
|
||||
signal_data->arg0 = g_strdup (arg0);
|
||||
signal_data->subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
||||
g_array_append_val (signal_data->subscribers, subscriber);
|
||||
|
||||
g_hash_table_insert (connection->priv->map_rule_to_signal_data,
|
||||
@ -2614,22 +2622,22 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
||||
add_match_rule (connection, signal_data->rule);
|
||||
}
|
||||
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_unique_name_to_signal_data_array,
|
||||
signal_data->sender_unique_name);
|
||||
if (signal_data_array == NULL)
|
||||
{
|
||||
signal_data_array = g_ptr_array_new ();
|
||||
g_hash_table_insert (connection->priv->map_sender_unique_name_to_signal_data_array,
|
||||
g_strdup (signal_data->sender_unique_name),
|
||||
signal_data_array);
|
||||
}
|
||||
g_ptr_array_add (signal_data_array, signal_data);
|
||||
|
||||
out:
|
||||
g_hash_table_insert (connection->priv->map_id_to_signal_data,
|
||||
GUINT_TO_POINTER (subscriber.id),
|
||||
signal_data);
|
||||
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array,
|
||||
signal_data->sender);
|
||||
if (signal_data_array == NULL)
|
||||
{
|
||||
signal_data_array = g_ptr_array_new ();
|
||||
g_hash_table_insert (connection->priv->map_sender_to_signal_data_array,
|
||||
g_strdup (signal_data->sender),
|
||||
signal_data_array);
|
||||
}
|
||||
g_ptr_array_add (signal_data_array, signal_data);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
return subscriber.id;
|
||||
@ -2669,24 +2677,27 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
||||
g_array_remove_index (signal_data->subscribers, n);
|
||||
|
||||
if (signal_data->subscribers->len == 0)
|
||||
g_warn_if_fail (g_hash_table_remove (connection->priv->map_rule_to_signal_data, signal_data->rule));
|
||||
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array,
|
||||
signal_data->sender);
|
||||
g_warn_if_fail (signal_data_array != NULL);
|
||||
g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
|
||||
|
||||
if (signal_data_array->len == 0)
|
||||
{
|
||||
g_warn_if_fail (g_hash_table_remove (connection->priv->map_sender_to_signal_data_array, signal_data->sender));
|
||||
g_warn_if_fail (g_hash_table_remove (connection->priv->map_rule_to_signal_data, signal_data->rule));
|
||||
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_unique_name_to_signal_data_array,
|
||||
signal_data->sender_unique_name);
|
||||
g_warn_if_fail (signal_data_array != NULL);
|
||||
g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
|
||||
|
||||
if (signal_data_array->len == 0)
|
||||
{
|
||||
g_warn_if_fail (g_hash_table_remove (connection->priv->map_sender_unique_name_to_signal_data_array,
|
||||
signal_data->sender_unique_name));
|
||||
}
|
||||
|
||||
/* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
|
||||
if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
|
||||
{
|
||||
if (!is_signal_data_for_name_lost_or_acquired (signal_data))
|
||||
remove_match_rule (connection, signal_data->rule);
|
||||
if (!connection->priv->closed)
|
||||
remove_match_rule (connection, signal_data->rule);
|
||||
}
|
||||
|
||||
signal_data_free (signal_data);
|
||||
}
|
||||
|
||||
@ -2779,7 +2790,8 @@ emit_signal_instance_in_idle_cb (gpointer data)
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_debug ("in emit_signal_instance_in_idle_cb (sender=%s path=%s interface=%s member=%s params=%s)",
|
||||
g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
|
||||
signal_instance->subscription_id,
|
||||
signal_instance->sender,
|
||||
signal_instance->path,
|
||||
signal_instance->interface,
|
||||
@ -2842,11 +2854,17 @@ schedule_callbacks (GDBusConnection *connection,
|
||||
arg0 = g_dbus_message_get_arg0 (message);
|
||||
|
||||
#if 0
|
||||
g_debug ("sender = `%s'", sender);
|
||||
g_debug ("interface = `%s'", interface);
|
||||
g_debug ("member = `%s'", member);
|
||||
g_debug ("path = `%s'", path);
|
||||
g_debug ("arg0 = `%s'", arg0);
|
||||
g_print ("In schedule_callbacks:\n"
|
||||
" sender = `%s'\n"
|
||||
" interface = `%s'\n"
|
||||
" member = `%s'\n"
|
||||
" path = `%s'\n"
|
||||
" arg0 = `%s'\n",
|
||||
sender,
|
||||
interface,
|
||||
member,
|
||||
path,
|
||||
arg0);
|
||||
#endif
|
||||
|
||||
/* TODO: if this is slow, then we can change signal_data_array into
|
||||
@ -2912,13 +2930,13 @@ distribute_signals (GDBusConnection *connection,
|
||||
/* collect subscribers that match on sender */
|
||||
if (sender != NULL)
|
||||
{
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array, sender);
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_unique_name_to_signal_data_array, sender);
|
||||
if (signal_data_array != NULL)
|
||||
schedule_callbacks (connection, signal_data_array, message, sender);
|
||||
}
|
||||
|
||||
/* collect subscribers not matching on sender */
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array, "");
|
||||
signal_data_array = g_hash_table_lookup (connection->priv->map_sender_unique_name_to_signal_data_array, "");
|
||||
if (signal_data_array != NULL)
|
||||
schedule_callbacks (connection, signal_data_array, message, sender);
|
||||
}
|
||||
|
1081
gio/gdbusproxy.c
1081
gio/gdbusproxy.c
File diff suppressed because it is too large
Load Diff
@ -95,10 +95,9 @@ struct _GDBusProxyClass
|
||||
|
||||
GType g_dbus_proxy_get_type (void) G_GNUC_CONST;
|
||||
void g_dbus_proxy_new (GDBusConnection *connection,
|
||||
GType object_type,
|
||||
GDBusProxyFlags flags,
|
||||
GDBusInterfaceInfo *info,
|
||||
const gchar *unique_bus_name,
|
||||
const gchar *name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GCancellable *cancellable,
|
||||
@ -107,17 +106,36 @@ void g_dbus_proxy_new (GDBusConnection *co
|
||||
GDBusProxy *g_dbus_proxy_new_finish (GAsyncResult *res,
|
||||
GError **error);
|
||||
GDBusProxy *g_dbus_proxy_new_sync (GDBusConnection *connection,
|
||||
GType object_type,
|
||||
GDBusProxyFlags flags,
|
||||
GDBusInterfaceInfo *info,
|
||||
const gchar *unique_bus_name,
|
||||
const gchar *name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void g_dbus_proxy_new_for_bus (GBusType bus_type,
|
||||
GDBusProxyFlags flags,
|
||||
GDBusInterfaceInfo *info,
|
||||
const gchar *name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDBusProxy *g_dbus_proxy_new_for_bus_finish (GAsyncResult *res,
|
||||
GError **error);
|
||||
GDBusProxy *g_dbus_proxy_new_for_bus_sync (GBusType bus_type,
|
||||
GDBusProxyFlags flags,
|
||||
GDBusInterfaceInfo *info,
|
||||
const gchar *name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GDBusConnection *g_dbus_proxy_get_connection (GDBusProxy *proxy);
|
||||
GDBusProxyFlags g_dbus_proxy_get_flags (GDBusProxy *proxy);
|
||||
const gchar *g_dbus_proxy_get_unique_bus_name (GDBusProxy *proxy);
|
||||
const gchar *g_dbus_proxy_get_name (GDBusProxy *proxy);
|
||||
gchar *g_dbus_proxy_get_name_owner (GDBusProxy *proxy);
|
||||
const gchar *g_dbus_proxy_get_object_path (GDBusProxy *proxy);
|
||||
const gchar *g_dbus_proxy_get_interface_name (GDBusProxy *proxy);
|
||||
gint g_dbus_proxy_get_default_timeout (GDBusProxy *proxy);
|
||||
|
@ -1,666 +0,0 @@
|
||||
/* GDBus - GLib D-Bus Library
|
||||
*
|
||||
* Copyright (C) 2008-2010 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: David Zeuthen <davidz@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gdbusutils.h"
|
||||
#include "gdbusconnection.h"
|
||||
#include "gdbusnamewatching.h"
|
||||
#include "gdbusproxywatching.h"
|
||||
#include "gdbuserror.h"
|
||||
#include "gdbusprivate.h"
|
||||
#include "gdbusproxy.h"
|
||||
#include "gcancellable.h"
|
||||
|
||||
#include "glibintl.h"
|
||||
#include "gioalias.h"
|
||||
|
||||
/**
|
||||
* SECTION:gdbusproxywatching
|
||||
* @title: Watching Proxies
|
||||
* @short_description: Simple API for watching proxies
|
||||
* @include: gio/gio.h
|
||||
*
|
||||
* Convenience API for watching bus proxies.
|
||||
*
|
||||
* <example id="gdbus-watching-proxy"><title>Simple application watching a proxy</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-watch-proxy.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
G_LOCK_DEFINE_STATIC (lock);
|
||||
|
||||
static guint next_global_id = 1;
|
||||
static GHashTable *map_id_to_client = NULL;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint id;
|
||||
GBusProxyAppearedCallback proxy_appeared_handler;
|
||||
GBusProxyVanishedCallback proxy_vanished_handler;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_data_free_func;
|
||||
GMainContext *main_context;
|
||||
|
||||
gchar *name;
|
||||
gchar *name_owner;
|
||||
GDBusConnection *connection;
|
||||
guint name_watcher_id;
|
||||
|
||||
GCancellable *cancellable;
|
||||
|
||||
gchar *object_path;
|
||||
gchar *interface_name;
|
||||
GType interface_type;
|
||||
GDBusProxyFlags proxy_flags;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
gboolean initial_construction;
|
||||
} Client;
|
||||
|
||||
static void
|
||||
client_unref (Client *client)
|
||||
{
|
||||
/* ensure we're only called from g_bus_unwatch_proxy */
|
||||
g_assert (client->name_watcher_id == 0);
|
||||
|
||||
g_free (client->name_owner);
|
||||
if (client->connection != NULL)
|
||||
g_object_unref (client->connection);
|
||||
if (client->proxy != NULL)
|
||||
g_object_unref (client->proxy);
|
||||
|
||||
g_free (client->name);
|
||||
g_free (client->object_path);
|
||||
g_free (client->interface_name);
|
||||
|
||||
if (client->main_context != NULL)
|
||||
g_main_context_unref (client->main_context);
|
||||
|
||||
if (client->user_data_free_func != NULL)
|
||||
client->user_data_free_func (client->user_data);
|
||||
g_free (client);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
proxy_constructed_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
Client *client = user_data;
|
||||
GDBusProxy *proxy;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_finish (res, &error);
|
||||
if (proxy == NULL)
|
||||
{
|
||||
/* g_warning ("error while constructing proxy: %s", error->message); */
|
||||
g_error_free (error);
|
||||
|
||||
/* handle initial construction, send out vanished if the name
|
||||
* is there but we constructing a proxy fails
|
||||
*/
|
||||
if (client->initial_construction)
|
||||
{
|
||||
if (client->proxy_vanished_handler != NULL)
|
||||
{
|
||||
client->proxy_vanished_handler (client->connection,
|
||||
client->name,
|
||||
client->user_data);
|
||||
}
|
||||
client->initial_construction = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (client->proxy == NULL);
|
||||
g_assert (client->cancellable != NULL);
|
||||
client->proxy = G_DBUS_PROXY (proxy);
|
||||
|
||||
g_object_unref (client->cancellable);
|
||||
client->cancellable = NULL;
|
||||
|
||||
/* perform callback */
|
||||
if (client->proxy_appeared_handler != NULL)
|
||||
{
|
||||
client->proxy_appeared_handler (client->connection,
|
||||
client->name,
|
||||
client->name_owner,
|
||||
client->proxy,
|
||||
client->user_data);
|
||||
}
|
||||
client->initial_construction = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
Client *client = user_data;
|
||||
|
||||
//g_debug ("\n\nname appeared (owner `%s')", name_owner);
|
||||
|
||||
/* invariants */
|
||||
g_assert (client->name_owner == NULL);
|
||||
g_assert (client->connection == NULL);
|
||||
g_assert (client->cancellable == NULL);
|
||||
|
||||
client->name_owner = g_strdup (name_owner);
|
||||
client->connection = g_object_ref (connection);
|
||||
client->cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_new (client->connection,
|
||||
client->interface_type,
|
||||
client->proxy_flags,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
client->name_owner,
|
||||
client->object_path,
|
||||
client->interface_name,
|
||||
client->cancellable,
|
||||
proxy_constructed_cb,
|
||||
client);
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
Client *client = user_data;
|
||||
|
||||
/*g_debug ("\n\nname vanished");*/
|
||||
|
||||
g_free (client->name_owner);
|
||||
if (client->connection != NULL)
|
||||
g_object_unref (client->connection);
|
||||
client->name_owner = NULL;
|
||||
client->connection = NULL;
|
||||
|
||||
/* free the proxy if we have it */
|
||||
if (client->proxy != NULL)
|
||||
{
|
||||
g_assert (client->cancellable == NULL);
|
||||
|
||||
g_object_unref (client->proxy);
|
||||
client->proxy = NULL;
|
||||
|
||||
/* if we have the proxy, it means we last sent out a 'appeared'
|
||||
* callback - so send out a 'vanished' callback
|
||||
*/
|
||||
if (client->proxy_vanished_handler != NULL)
|
||||
{
|
||||
client->proxy_vanished_handler (client->connection,
|
||||
client->name,
|
||||
client->user_data);
|
||||
}
|
||||
client->initial_construction = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise cancel construction of the proxy if applicable */
|
||||
if (client->cancellable != NULL)
|
||||
{
|
||||
g_cancellable_cancel (client->cancellable);
|
||||
g_object_unref (client->cancellable);
|
||||
client->cancellable = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* handle initial construction, send out vanished if
|
||||
* the name isn't there
|
||||
*/
|
||||
if (client->initial_construction)
|
||||
{
|
||||
if (client->proxy_vanished_handler != NULL)
|
||||
{
|
||||
client->proxy_vanished_handler (client->connection,
|
||||
client->name,
|
||||
client->user_data);
|
||||
}
|
||||
client->initial_construction = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bus_watch_proxy:
|
||||
* @bus_type: The type of bus to watch a name on.
|
||||
* @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.
|
||||
* @proxy_flags: Flags from #GDBusProxyFlags to use when constructing the proxy.
|
||||
* @proxy_appeared_handler: Handler to invoke when @name is known to exist and the
|
||||
* requested proxy is available.
|
||||
* @proxy_vanished_handler: Handler to invoke when @name is known to not exist
|
||||
* and the previously created proxy is no longer available.
|
||||
* @user_data: User data to pass to handlers.
|
||||
* @user_data_free_func: Function for freeing @user_data or %NULL.
|
||||
*
|
||||
* Starts watching a remote object at @object_path owned by @name on
|
||||
* the bus specified by @bus_type. When the object is available, a
|
||||
* #GDBusProxy (or derived class cf. @interface_type) instance is
|
||||
* constructed for the @interface_name D-Bus interface and then
|
||||
* @proxy_appeared_handler will be called when the proxy is ready and
|
||||
* all properties have been loaded. When @name vanishes,
|
||||
* @proxy_vanished_handler is called.
|
||||
*
|
||||
* This function makes it very simple to write applications that wants
|
||||
* to watch a well-known remote object on a well-known name, see <xref
|
||||
* linkend="gdbus-watching-proxy"/>. Basically, the application simply
|
||||
* starts using the proxy when @proxy_appeared_handler is called and
|
||||
* stops using it when @proxy_vanished_handler is called. Callbacks
|
||||
* will be invoked in the <link
|
||||
* linkend="g-main-context-push-thread-default">thread-default main
|
||||
* loop</link> of the thread you are calling this function from.
|
||||
*
|
||||
* Applications typically use this function to watch the
|
||||
* <quote>manager</quote> object of a well-known name. Upon acquiring
|
||||
* a proxy for the manager object, applications typically construct
|
||||
* additional proxies in response to the result of enumeration methods
|
||||
* on the manager object.
|
||||
*
|
||||
* Many of the comments that apply to g_bus_watch_name() also apply
|
||||
* here. For example, you are guaranteed that one of the handlers will
|
||||
* be invoked (on the main thread) after calling this function and
|
||||
* also that the two handlers alternate. When you are done watching the
|
||||
* proxy, just call g_bus_unwatch_proxy().
|
||||
*
|
||||
* Returns: An identifier (never 0) that can be used with
|
||||
* g_bus_unwatch_proxy() to stop watching the remote object.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
guint
|
||||
g_bus_watch_proxy (GBusType bus_type,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GBusProxyAppearedCallback proxy_appeared_handler,
|
||||
GBusProxyVanishedCallback proxy_vanished_handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_free_func)
|
||||
{
|
||||
Client *client;
|
||||
|
||||
g_return_val_if_fail (g_dbus_is_name (name), 0);
|
||||
g_return_val_if_fail (g_variant_is_object_path (object_path), 0);
|
||||
g_return_val_if_fail (g_dbus_is_interface_name (interface_name), 0);
|
||||
g_return_val_if_fail (g_type_is_a (interface_type, G_TYPE_DBUS_PROXY), 0);
|
||||
|
||||
G_LOCK (lock);
|
||||
|
||||
client = g_new0 (Client, 1);
|
||||
client->id = next_global_id++; /* TODO: uh oh, handle overflow */
|
||||
client->name = g_strdup (name);
|
||||
client->proxy_appeared_handler = proxy_appeared_handler;
|
||||
client->proxy_vanished_handler = proxy_vanished_handler;
|
||||
client->user_data = user_data;
|
||||
client->user_data_free_func = user_data_free_func;
|
||||
client->main_context = g_main_context_get_thread_default ();
|
||||
if (client->main_context != NULL)
|
||||
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,
|
||||
NULL);
|
||||
|
||||
client->object_path = g_strdup (object_path);
|
||||
client->interface_name = g_strdup (interface_name);
|
||||
client->interface_type = interface_type;
|
||||
client->proxy_flags = proxy_flags;
|
||||
client->initial_construction = TRUE;
|
||||
|
||||
if (map_id_to_client == NULL)
|
||||
{
|
||||
map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
}
|
||||
g_hash_table_insert (map_id_to_client,
|
||||
GUINT_TO_POINTER (client->id),
|
||||
client);
|
||||
|
||||
G_UNLOCK (lock);
|
||||
|
||||
return client->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bus_watch_proxy_on_connection:
|
||||
* @connection: A #GDBusConnection that is not closed.
|
||||
* @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.
|
||||
* @proxy_flags: Flags from #GDBusProxyFlags to use when constructing the proxy.
|
||||
* @proxy_appeared_handler: Handler to invoke when @name is known to exist and the
|
||||
* requested proxy is available.
|
||||
* @proxy_vanished_handler: Handler to invoke when @name is known to not exist
|
||||
* and the previously created proxy is no longer available.
|
||||
* @user_data: User data to pass to handlers.
|
||||
* @user_data_free_func: Function for freeing @user_data or %NULL.
|
||||
*
|
||||
* Like g_bus_watch_proxy() but takes a #GDBusConnection instead of a
|
||||
* #GBusType.
|
||||
*
|
||||
* Returns: An identifier (never 0) that can be used with
|
||||
* g_bus_unwatch_proxy() to stop watching the remote object.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
guint
|
||||
g_bus_watch_proxy_on_connection (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GBusProxyAppearedCallback proxy_appeared_handler,
|
||||
GBusProxyVanishedCallback proxy_vanished_handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_free_func)
|
||||
{
|
||||
Client *client;
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
|
||||
g_return_val_if_fail (g_dbus_is_name (name), 0);
|
||||
g_return_val_if_fail (g_variant_is_object_path (object_path), 0);
|
||||
g_return_val_if_fail (g_dbus_is_interface_name (interface_name), 0);
|
||||
g_return_val_if_fail (g_type_is_a (interface_type, G_TYPE_DBUS_PROXY), 0);
|
||||
|
||||
G_LOCK (lock);
|
||||
|
||||
client = g_new0 (Client, 1);
|
||||
client->id = next_global_id++; /* TODO: uh oh, handle overflow */
|
||||
client->name = g_strdup (name);
|
||||
client->proxy_appeared_handler = proxy_appeared_handler;
|
||||
client->proxy_vanished_handler = proxy_vanished_handler;
|
||||
client->user_data = user_data;
|
||||
client->user_data_free_func = user_data_free_func;
|
||||
client->main_context = g_main_context_get_thread_default ();
|
||||
if (client->main_context != NULL)
|
||||
g_main_context_ref (client->main_context);
|
||||
client->name_watcher_id = g_bus_watch_name_on_connection (connection,
|
||||
name,
|
||||
flags,
|
||||
on_name_appeared,
|
||||
on_name_vanished,
|
||||
client,
|
||||
NULL);
|
||||
|
||||
client->object_path = g_strdup (object_path);
|
||||
client->interface_name = g_strdup (interface_name);
|
||||
client->interface_type = interface_type;
|
||||
client->proxy_flags = proxy_flags;
|
||||
client->initial_construction = TRUE;
|
||||
|
||||
if (map_id_to_client == NULL)
|
||||
{
|
||||
map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
}
|
||||
g_hash_table_insert (map_id_to_client,
|
||||
GUINT_TO_POINTER (client->id),
|
||||
client);
|
||||
|
||||
G_UNLOCK (lock);
|
||||
|
||||
return client->id;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GClosure *proxy_appeared_closure;
|
||||
GClosure *proxy_vanished_closure;
|
||||
} WatchProxyData;
|
||||
|
||||
static void
|
||||
watch_with_closures_on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
{
|
||||
WatchProxyData *data = user_data;
|
||||
GValue params[4] = { { 0, }, { 0, }, { 0, }, { 0, } };
|
||||
|
||||
g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
|
||||
g_value_set_object (¶ms[0], connection);
|
||||
|
||||
g_value_init (¶ms[1], G_TYPE_STRING);
|
||||
g_value_set_string (¶ms[1], name);
|
||||
|
||||
g_value_init (¶ms[2], G_TYPE_STRING);
|
||||
g_value_set_string (¶ms[2], name_owner);
|
||||
|
||||
g_value_init (¶ms[3], G_TYPE_DBUS_PROXY);
|
||||
g_value_set_object (¶ms[3], proxy);
|
||||
|
||||
g_closure_invoke (data->proxy_appeared_closure, NULL, 4, params, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
watch_with_closures_on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
WatchProxyData *data = user_data;
|
||||
GValue params[2] = { { 0, }, { 0, } };
|
||||
|
||||
g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
|
||||
g_value_set_object (¶ms[0], connection);
|
||||
|
||||
g_value_init (¶ms[1], G_TYPE_STRING);
|
||||
g_value_set_string (¶ms[1], name);
|
||||
|
||||
g_closure_invoke (data->proxy_vanished_closure, NULL, 2, params, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
bus_watch_proxy_free_func (gpointer user_data)
|
||||
{
|
||||
WatchProxyData *data = user_data;
|
||||
|
||||
if (data->proxy_appeared_closure != NULL)
|
||||
g_closure_unref (data->proxy_appeared_closure);
|
||||
|
||||
if (data->proxy_vanished_closure != NULL)
|
||||
g_closure_unref (data->proxy_vanished_closure);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bus_watch_proxy_with_closures:
|
||||
* @bus_type: The type of bus to watch a name on.
|
||||
* @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.
|
||||
* @proxy_flags: Flags from #GDBusProxyFlags to use when constructing the proxy.
|
||||
* @proxy_appeared_closure: (allow-none): #GClosure to invoke when @name is
|
||||
* known to exist and the requested proxy is available.
|
||||
* @proxy_vanished_closure: (allow-none): #GClosure to invoke when @name is
|
||||
* known to not exist and the previously created proxy is no longer available.
|
||||
*
|
||||
* Version of g_bus_watch_proxy() using closures instead of callbacks for
|
||||
* easier binding in other languages.
|
||||
*
|
||||
* Returns: An identifier (never 0) that can be used with
|
||||
* g_bus_unwatch_proxy() to stop watching the remote object.
|
||||
*
|
||||
* Rename to: g_bus_watch_proxy
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
guint
|
||||
g_bus_watch_proxy_with_closures (GBusType bus_type,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GClosure *proxy_appeared_closure,
|
||||
GClosure *proxy_vanished_closure)
|
||||
{
|
||||
WatchProxyData *data;
|
||||
|
||||
data = g_new0 (WatchProxyData, 1);
|
||||
|
||||
if (proxy_appeared_closure != NULL)
|
||||
data->proxy_appeared_closure = g_closure_ref (proxy_appeared_closure);
|
||||
|
||||
if (proxy_vanished_closure != NULL)
|
||||
data->proxy_vanished_closure = g_closure_ref (proxy_vanished_closure);
|
||||
|
||||
return g_bus_watch_proxy (bus_type,
|
||||
name,
|
||||
flags,
|
||||
object_path,
|
||||
interface_name,
|
||||
interface_type,
|
||||
proxy_flags,
|
||||
proxy_appeared_closure != NULL ? watch_with_closures_on_proxy_appeared : NULL,
|
||||
proxy_vanished_closure != NULL ? watch_with_closures_on_proxy_vanished : NULL,
|
||||
data,
|
||||
bus_watch_proxy_free_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bus_watch_proxy_on_connection_with_closures:
|
||||
* @connection: A #GDBusConnection that is not closed.
|
||||
* @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.
|
||||
* @proxy_flags: Flags from #GDBusProxyFlags to use when constructing the proxy.
|
||||
* @proxy_appeared_closure: (allow-none): #GClosure to invoke when @name is
|
||||
* known to exist and the requested proxy is available.
|
||||
* @proxy_vanished_closure: (allow-none): #GClosure to invoke when @name is
|
||||
* known to not exist and the previously created proxy is no longer available.
|
||||
*
|
||||
* Version of g_bus_watch_proxy_on_connection() using closures instead of
|
||||
* callbacks for easier binding in other languages.
|
||||
*
|
||||
* Returns: An identifier (never 0) that can be used with
|
||||
* g_bus_unwatch_proxy() to stop watching the remote object.
|
||||
*
|
||||
* Rename to: g_bus_watch_proxy_on_connection
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
guint
|
||||
g_bus_watch_proxy_on_connection_with_closures (
|
||||
GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GClosure *proxy_appeared_closure,
|
||||
GClosure *proxy_vanished_closure)
|
||||
{
|
||||
WatchProxyData *data;
|
||||
|
||||
data = g_new0 (WatchProxyData, 1);
|
||||
|
||||
if (proxy_appeared_closure != NULL)
|
||||
data->proxy_appeared_closure = g_closure_ref (proxy_appeared_closure);
|
||||
|
||||
if (proxy_vanished_closure != NULL)
|
||||
data->proxy_vanished_closure = g_closure_ref (proxy_vanished_closure);
|
||||
|
||||
return g_bus_watch_proxy_on_connection (connection,
|
||||
name,
|
||||
flags,
|
||||
object_path,
|
||||
interface_name,
|
||||
interface_type,
|
||||
proxy_flags,
|
||||
proxy_appeared_closure != NULL ? watch_with_closures_on_proxy_appeared : NULL,
|
||||
proxy_vanished_closure != NULL ? watch_with_closures_on_proxy_vanished : NULL,
|
||||
data,
|
||||
bus_watch_proxy_free_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bus_unwatch_proxy:
|
||||
* @watcher_id: An identifier obtained from g_bus_watch_proxy()
|
||||
*
|
||||
* Stops watching proxy.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
void
|
||||
g_bus_unwatch_proxy (guint watcher_id)
|
||||
{
|
||||
Client *client;
|
||||
|
||||
g_return_if_fail (watcher_id > 0);
|
||||
|
||||
client = NULL;
|
||||
|
||||
G_LOCK (lock);
|
||||
if (watcher_id == 0 ||
|
||||
map_id_to_client == NULL ||
|
||||
(client = g_hash_table_lookup (map_id_to_client, GUINT_TO_POINTER (watcher_id))) == NULL)
|
||||
{
|
||||
g_warning ("Invalid id %d passed to g_bus_unwatch_proxy()", watcher_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_warn_if_fail (g_hash_table_remove (map_id_to_client, GUINT_TO_POINTER (watcher_id)));
|
||||
|
||||
out:
|
||||
G_UNLOCK (lock);
|
||||
|
||||
if (client != NULL)
|
||||
{
|
||||
g_bus_unwatch_name (client->name_watcher_id);
|
||||
client->name_watcher_id = 0;
|
||||
client_unref (client);
|
||||
}
|
||||
}
|
||||
|
||||
#define __G_DBUS_PROXY_WATCHING_C__
|
||||
#include "gioaliasdef.c"
|
@ -1,115 +0,0 @@
|
||||
/* GDBus - GLib D-Bus Library
|
||||
*
|
||||
* Copyright (C) 2008-2010 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: David Zeuthen <davidz@redhat.com>
|
||||
*/
|
||||
|
||||
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
|
||||
#error "Only <gio/gio.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DBUS_PROXY_WATCHING_H__
|
||||
#define __G_DBUS_PROXY_WATCHING_H__
|
||||
|
||||
#include <gio/giotypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GBusProxyAppearedCallback:
|
||||
* @connection: The #GDBusConnection the proxy is being watched on.
|
||||
* @name: The name being watched.
|
||||
* @name_owner: Unique name of the owner of the name being watched.
|
||||
* @proxy: A #GDBusProxy (or derived) instance with all properties loaded.
|
||||
* @user_data: User data passed to g_bus_watch_proxy().
|
||||
*
|
||||
* Invoked when the proxy being watched is ready for use - the passed
|
||||
* @proxy object is valid until the #GBusProxyVanishedCallback
|
||||
* callback is invoked.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
typedef void (*GBusProxyAppearedCallback) (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* GBusProxyVanishedCallback:
|
||||
* @connection: The #GDBusConnection the proxy is being watched on.
|
||||
* @name: The name being watched.
|
||||
* @user_data: User data passed to g_bus_watch_proxy().
|
||||
*
|
||||
* Invoked when the proxy being watched has vanished. The #GDBusProxy
|
||||
* object passed in the #GBusProxyAppearedCallback callback is no
|
||||
* longer valid.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
typedef void (*GBusProxyVanishedCallback) (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data);
|
||||
|
||||
guint g_bus_watch_proxy (GBusType bus_type,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GBusProxyAppearedCallback proxy_appeared_handler,
|
||||
GBusProxyVanishedCallback proxy_vanished_handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_free_func);
|
||||
guint g_bus_watch_proxy_on_connection (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GBusProxyAppearedCallback proxy_appeared_handler,
|
||||
GBusProxyVanishedCallback proxy_vanished_handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_free_func);
|
||||
guint g_bus_watch_proxy_with_closures (GBusType bus_type,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GClosure *proxy_appeared_closure,
|
||||
GClosure *proxy_vanished_closure);
|
||||
guint g_bus_watch_proxy_on_connection_with_closures (
|
||||
GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
GBusNameWatcherFlags flags,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
GType interface_type,
|
||||
GDBusProxyFlags proxy_flags,
|
||||
GClosure *proxy_appeared_closure,
|
||||
GClosure *proxy_vanished_closure);
|
||||
void g_bus_unwatch_proxy (guint watcher_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DBUS_PROXY_WATCHING_H__ */
|
@ -52,7 +52,6 @@
|
||||
#include <gio/gdbusnameowning.h>
|
||||
#include <gio/gdbusnamewatching.h>
|
||||
#include <gio/gdbusproxy.h>
|
||||
#include <gio/gdbusproxywatching.h>
|
||||
#include <gio/gdbusserver.h>
|
||||
#include <gio/gdbusutils.h>
|
||||
#include <gio/gdrive.h>
|
||||
|
@ -1695,6 +1695,9 @@ g_dbus_proxy_get_type G_GNUC_CONST
|
||||
g_dbus_proxy_new
|
||||
g_dbus_proxy_new_finish
|
||||
g_dbus_proxy_new_sync
|
||||
g_dbus_proxy_new_for_bus
|
||||
g_dbus_proxy_new_for_bus_finish
|
||||
g_dbus_proxy_new_for_bus_sync
|
||||
g_dbus_proxy_get_cached_property
|
||||
g_dbus_proxy_set_cached_property
|
||||
g_dbus_proxy_get_cached_property_names
|
||||
@ -1704,7 +1707,8 @@ g_dbus_proxy_get_flags
|
||||
g_dbus_proxy_get_interface_info
|
||||
g_dbus_proxy_get_interface_name
|
||||
g_dbus_proxy_get_object_path
|
||||
g_dbus_proxy_get_unique_bus_name
|
||||
g_dbus_proxy_get_name
|
||||
g_dbus_proxy_get_name_owner
|
||||
g_dbus_proxy_set_default_timeout
|
||||
g_dbus_proxy_set_interface_info
|
||||
g_dbus_proxy_call
|
||||
@ -1713,16 +1717,6 @@ g_dbus_proxy_call_sync
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if IN_HEADER(__G_DBUS_PROXY_WATCHING_H__)
|
||||
#if IN_FILE(__G_DBUS_PROXY_WATCHING_C__)
|
||||
g_bus_watch_proxy
|
||||
g_bus_watch_proxy_on_connection
|
||||
g_bus_unwatch_proxy
|
||||
g_bus_watch_proxy_with_closures
|
||||
g_bus_watch_proxy_on_connection_with_closures
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if IN_HEADER(__G_DBUS_SERVER_H__)
|
||||
#if IN_FILE(__G_DBUS_SERVER_C__)
|
||||
g_dbus_server_get_type G_GNUC_CONST
|
||||
|
@ -741,6 +741,7 @@ typedef enum {
|
||||
/**
|
||||
* GBusType:
|
||||
* @G_BUS_TYPE_STARTER: An alias for the message bus that activated the process, if any.
|
||||
* @G_BUS_TYPE_NONE: Not a message bus.
|
||||
* @G_BUS_TYPE_SYSTEM: The system-wide message bus.
|
||||
* @G_BUS_TYPE_SESSION: The login session message bus.
|
||||
*
|
||||
@ -750,7 +751,8 @@ typedef enum {
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_BUS_TYPE_STARTER = 0,
|
||||
G_BUS_TYPE_STARTER = -1,
|
||||
G_BUS_TYPE_NONE = 0,
|
||||
G_BUS_TYPE_SYSTEM = 1,
|
||||
G_BUS_TYPE_SESSION = 2
|
||||
} GBusType;
|
||||
@ -795,6 +797,9 @@ typedef enum
|
||||
* @G_DBUS_PROXY_FLAGS_NONE: No flags set.
|
||||
* @G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES: Don't load properties.
|
||||
* @G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS: Don't connect to signals on the remote object.
|
||||
* @G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START: If not set and the proxy if for a well-known name,
|
||||
* then request the bus to launch an owner for the name if no-one owns the name. This flag can
|
||||
* only be used in proxies for well-known names.
|
||||
*
|
||||
* Flags used when constructing an instance of a #GDBusProxy derived class.
|
||||
*
|
||||
@ -802,9 +807,10 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_DBUS_PROXY_FLAGS_NONE = 0, /*< nick=none >*/
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES = (1<<0), /*< nick=do-not-load-properties >*/
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = (1<<1) /*< nick=do-not-connect-signals >*/
|
||||
G_DBUS_PROXY_FLAGS_NONE = 0,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES = (1<<0),
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = (1<<1),
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = (1<<2)
|
||||
} GDBusProxyFlags;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@ TEST_PROGS += \
|
||||
gdbus-connection \
|
||||
gdbus-names \
|
||||
gdbus-proxy \
|
||||
gdbus-proxy-well-known-name \
|
||||
gdbus-introspection \
|
||||
gdbus-threading \
|
||||
gdbus-export \
|
||||
@ -208,6 +209,9 @@ gdbus_names_LDADD = $(progs_ldadd)
|
||||
gdbus_proxy_SOURCES = gdbus-proxy.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c
|
||||
gdbus_proxy_LDADD = $(progs_ldadd)
|
||||
|
||||
gdbus_proxy_well_known_name_SOURCES = gdbus-proxy-well-known-name.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c
|
||||
gdbus_proxy_well_known_name_LDADD = $(progs_ldadd)
|
||||
|
||||
gdbus_introspection_SOURCES = gdbus-introspection.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c
|
||||
gdbus_introspection_LDADD = $(progs_ldadd)
|
||||
|
||||
|
@ -360,9 +360,11 @@ test_connection_signals (void)
|
||||
GDBusConnection *c2;
|
||||
GDBusConnection *c3;
|
||||
guint s1;
|
||||
guint s1b;
|
||||
guint s2;
|
||||
guint s3;
|
||||
gint count_s1;
|
||||
gint count_s1b;
|
||||
gint count_s2;
|
||||
gint count_name_owner_changed;
|
||||
GError *error;
|
||||
@ -425,11 +427,26 @@ test_connection_signals (void)
|
||||
test_connection_signal_handler,
|
||||
&count_name_owner_changed,
|
||||
NULL);
|
||||
/* Note that s1b is *just like* s1 - this is to catch a bug where N
|
||||
* subscriptions of the same rule causes N calls to each of the N
|
||||
* subscriptions instead of just 1 call to each of the N subscriptions.
|
||||
*/
|
||||
s1b = g_dbus_connection_signal_subscribe (c1,
|
||||
":1.2",
|
||||
"org.gtk.GDBus.ExampleInterface",
|
||||
"Foo",
|
||||
"/org/gtk/GDBus/ExampleInterface",
|
||||
NULL,
|
||||
test_connection_signal_handler,
|
||||
&count_s1b,
|
||||
NULL);
|
||||
g_assert (s1 != 0);
|
||||
g_assert (s1b != 0);
|
||||
g_assert (s2 != 0);
|
||||
g_assert (s3 != 0);
|
||||
|
||||
count_s1 = 0;
|
||||
count_s1b = 0;
|
||||
count_s2 = 0;
|
||||
count_name_owner_changed = 0;
|
||||
|
||||
@ -480,7 +497,7 @@ test_connection_signals (void)
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
while (!(count_s1 == 1 && count_s2 == 1))
|
||||
while (!(count_s1 >= 1 && count_s2 >= 1))
|
||||
g_main_loop_run (loop);
|
||||
g_assert_cmpint (count_s1, ==, 1);
|
||||
g_assert_cmpint (count_s2, ==, 1);
|
||||
@ -510,7 +527,7 @@ test_connection_signals (void)
|
||||
guint quit_mainloop_id;
|
||||
quit_mainloop_fired = FALSE;
|
||||
quit_mainloop_id = g_timeout_add (5000, test_connection_signal_quit_mainloop, &quit_mainloop_fired);
|
||||
while (count_name_owner_changed != 2 && !quit_mainloop_fired)
|
||||
while (count_name_owner_changed < 2 && !quit_mainloop_fired)
|
||||
g_main_loop_run (loop);
|
||||
g_source_remove (quit_mainloop_id);
|
||||
g_assert_cmpint (count_s1, ==, 1);
|
||||
@ -520,6 +537,7 @@ test_connection_signals (void)
|
||||
g_dbus_connection_signal_unsubscribe (c1, s1);
|
||||
g_dbus_connection_signal_unsubscribe (c1, s2);
|
||||
g_dbus_connection_signal_unsubscribe (c1, s3);
|
||||
g_dbus_connection_signal_unsubscribe (c1, s1b);
|
||||
|
||||
_g_object_wait_for_single_ref (c1);
|
||||
_g_object_wait_for_single_ref (c2);
|
||||
|
@ -349,93 +349,10 @@ accounts_user_frobnicate_finish (AccountsUser *user,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
/* Example usage of the AccountsUser type */
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
print_user (AccountsUser *user)
|
||||
{
|
||||
g_print (" user-name = `%s'\n", accounts_user_get_user_name (user));
|
||||
g_print (" real-name = `%s'\n", accounts_user_get_real_name (user));
|
||||
g_print (" automatic-login = %s\n", accounts_user_get_automatic_login (user) ? "true" : "false");
|
||||
}
|
||||
|
||||
static void
|
||||
on_changed (AccountsUser *user,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("+++ Received the AccountsUser::changed signal\n");
|
||||
print_user (user);
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
AccountsUser *user = ACCOUNTS_USER (object);
|
||||
g_print ("+++ Received the GObject::notify signal for property `%s'\n",
|
||||
pspec->name);
|
||||
print_user (user);
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
{
|
||||
AccountsUser *user = ACCOUNTS_USER (proxy);
|
||||
|
||||
g_print ("+++ Acquired proxy for user\n");
|
||||
print_user (user);
|
||||
|
||||
g_signal_connect (proxy,
|
||||
"notify",
|
||||
G_CALLBACK (on_notify),
|
||||
NULL);
|
||||
g_signal_connect (user,
|
||||
"changed",
|
||||
G_CALLBACK (on_changed),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("--- Cannot create proxy for user: no remote object\n");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
guint watcher_id;
|
||||
GMainLoop *loop;
|
||||
|
||||
g_type_init ();
|
||||
|
||||
watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SYSTEM,
|
||||
"org.freedesktop.Accounts",
|
||||
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
|
||||
"/org/freedesktop/Accounts/User500",
|
||||
"org.freedesktop.Accounts.User",
|
||||
ACCOUNTS_TYPE_USER,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
on_proxy_appeared,
|
||||
on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ 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_auto_start = FALSE;
|
||||
static gboolean opt_no_properties = FALSE;
|
||||
|
||||
static GOptionEntry opt_entries[] =
|
||||
@ -13,11 +13,13 @@ 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-auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_no_auto_start, "Don't 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}
|
||||
};
|
||||
|
||||
static GMainLoop *loop = NULL;
|
||||
|
||||
static void
|
||||
print_properties (GDBusProxy *proxy)
|
||||
{
|
||||
@ -100,64 +102,62 @@ on_signal (GDBusProxy *proxy,
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
print_proxy (GDBusProxy *proxy)
|
||||
{
|
||||
g_print ("+++ Acquired proxy object for remote object owned by %s\n"
|
||||
" bus: %s\n"
|
||||
" name: %s\n"
|
||||
" object path: %s\n"
|
||||
" interface: %s\n",
|
||||
name_owner,
|
||||
opt_system_bus ? "System Bus" : "Session Bus",
|
||||
opt_name,
|
||||
opt_object_path,
|
||||
opt_interface);
|
||||
gchar *name_owner;
|
||||
|
||||
print_properties (proxy);
|
||||
|
||||
g_signal_connect (proxy,
|
||||
"g-properties-changed",
|
||||
G_CALLBACK (on_properties_changed),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (proxy,
|
||||
"g-signal",
|
||||
G_CALLBACK (on_signal),
|
||||
NULL);
|
||||
name_owner = g_dbus_proxy_get_name_owner (proxy);
|
||||
if (name_owner != NULL)
|
||||
{
|
||||
g_print ("+++ Proxy object points to remote object owned by %s\n"
|
||||
" bus: %s\n"
|
||||
" name: %s\n"
|
||||
" object path: %s\n"
|
||||
" interface: %s\n",
|
||||
name_owner,
|
||||
opt_system_bus ? "System Bus" : "Session Bus",
|
||||
opt_name,
|
||||
opt_object_path,
|
||||
opt_interface);
|
||||
print_properties (proxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("--- Proxy object is inert - there is no name owner for the name\n"
|
||||
" bus: %s\n"
|
||||
" name: %s\n"
|
||||
" object path: %s\n"
|
||||
" interface: %s\n",
|
||||
opt_system_bus ? "System Bus" : "Session Bus",
|
||||
opt_name,
|
||||
opt_object_path,
|
||||
opt_interface);
|
||||
}
|
||||
g_free (name_owner);
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
on_name_owner_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("--- Cannot create proxy object for\n"
|
||||
" bus: %s\n"
|
||||
" name: %s\n"
|
||||
" object path: %s\n"
|
||||
" interface: %s\n",
|
||||
opt_system_bus ? "System Bus" : "Session Bus",
|
||||
opt_name,
|
||||
opt_object_path,
|
||||
opt_interface);
|
||||
GDBusProxy *proxy = G_DBUS_PROXY (object);
|
||||
print_proxy (proxy);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
guint watcher_id;
|
||||
GMainLoop *loop;
|
||||
GOptionContext *opt_context;
|
||||
GError *error;
|
||||
GBusNameWatcherFlags flags;
|
||||
GDBusProxyFlags proxy_flags;
|
||||
GDBusProxyFlags flags;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
g_type_init ();
|
||||
|
||||
loop = NULL;
|
||||
proxy = NULL;
|
||||
|
||||
opt_context = g_option_context_new ("g_bus_watch_proxy() example");
|
||||
g_option_context_set_summary (opt_context,
|
||||
"Example: to watch the object of gdbus-example-server, use:\n"
|
||||
@ -169,7 +169,7 @@ main (int argc, char *argv[])
|
||||
error = NULL;
|
||||
if (!g_option_context_parse (opt_context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("Error parsing options: %s", error->message);
|
||||
g_printerr ("Error parsing options: %s\n", error->message);
|
||||
goto out;
|
||||
}
|
||||
if (opt_name == NULL || opt_object_path == NULL || opt_interface == NULL)
|
||||
@ -178,32 +178,51 @@ 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;
|
||||
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,
|
||||
proxy_flags,
|
||||
on_proxy_appeared,
|
||||
on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
flags |= G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
|
||||
if (opt_no_auto_start)
|
||||
flags |= G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_for_bus_sync (opt_system_bus ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION,
|
||||
flags,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
opt_name,
|
||||
opt_object_path,
|
||||
opt_interface,
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
if (proxy == NULL)
|
||||
{
|
||||
g_printerr ("Error creating proxy: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_signal_connect (proxy,
|
||||
"g-properties-changed",
|
||||
G_CALLBACK (on_properties_changed),
|
||||
NULL);
|
||||
g_signal_connect (proxy,
|
||||
"g-signal",
|
||||
G_CALLBACK (on_signal),
|
||||
NULL);
|
||||
g_signal_connect (proxy,
|
||||
"notify::g-name-owner",
|
||||
G_CALLBACK (on_name_owner_notify),
|
||||
NULL);
|
||||
print_proxy (proxy);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
|
||||
out:
|
||||
if (proxy != NULL)
|
||||
g_object_unref (proxy);
|
||||
if (loop != NULL)
|
||||
g_main_loop_unref (loop);
|
||||
g_option_context_free (opt_context);
|
||||
g_free (opt_name);
|
||||
g_free (opt_object_path);
|
||||
|
@ -343,7 +343,6 @@ get_nodes_at (GDBusConnection *c,
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
NULL,
|
||||
@ -400,7 +399,6 @@ has_interface (GDBusConnection *c,
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
NULL,
|
||||
@ -450,7 +448,6 @@ count_interfaces (GDBusConnection *c,
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
NULL,
|
||||
@ -522,7 +519,6 @@ dyna_create (GDBusConnection *c,
|
||||
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
NULL,
|
||||
@ -745,7 +741,6 @@ test_dispatch_thread_func (gpointer user_data)
|
||||
const gchar *value_str;
|
||||
|
||||
foo_proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
|
@ -34,11 +34,7 @@ static GMainLoop *loop = NULL;
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
introspection_on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
test_introspection (GDBusProxy *proxy)
|
||||
{
|
||||
GError *error;
|
||||
const gchar *xml_data;
|
||||
@ -104,48 +100,47 @@ introspection_on_proxy_appeared (GDBusConnection *connection,
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
introspection_on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_introspection_parser (void)
|
||||
{
|
||||
guint watcher_id;
|
||||
GDBusProxy *proxy;
|
||||
GDBusConnection *connection;
|
||||
GError *error;
|
||||
|
||||
session_bus_up ();
|
||||
|
||||
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,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
introspection_on_proxy_appeared,
|
||||
introspection_on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* TODO: wait a bit for the bus to come up.. ideally session_bus_up() won't return
|
||||
* until one can connect to the bus but that's not how things work right now
|
||||
*/
|
||||
usleep (500 * 1000);
|
||||
|
||||
error = NULL;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
|
||||
NULL,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface */
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* this is safe; testserver will exit once the bus goes away */
|
||||
g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
|
||||
|
||||
g_main_loop_run (loop);
|
||||
_g_assert_property_notify (proxy, "g-name-owner");
|
||||
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
test_introspection (proxy);
|
||||
|
||||
/* tear down bus */
|
||||
session_bus_down ();
|
||||
g_object_unref (proxy);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
|
@ -526,7 +526,6 @@ test_peer (void)
|
||||
*/
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (c,
|
||||
G_TYPE_DBUS_PROXY,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL,
|
||||
NULL, /* bus_name */
|
||||
|
283
gio/tests/gdbus-proxy-well-known-name.c
Normal file
283
gio/tests/gdbus-proxy-well-known-name.c
Normal file
@ -0,0 +1,283 @@
|
||||
/* GLib testing framework examples and tests
|
||||
*
|
||||
* Copyright (C) 2008-2010 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: David Zeuthen <davidz@redhat.com>
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gdbus-tests.h"
|
||||
|
||||
/* all tests rely on a shared mainloop */
|
||||
static GMainLoop *loop = NULL;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
proxy_new_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDBusProxy **ret = user_data;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
*ret = g_dbus_proxy_new_finish (res, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret != NULL);
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_proxy_well_known_name (void)
|
||||
{
|
||||
GDBusProxy *p;
|
||||
GDBusProxy *p2;
|
||||
GDBusProxy *ap;
|
||||
GDBusProxy *ap2;
|
||||
GDBusConnection *c;
|
||||
GError *error;
|
||||
gchar *name_owner;
|
||||
gchar **property_names;
|
||||
GVariant *variant;
|
||||
GVariant *result;
|
||||
|
||||
session_bus_up ();
|
||||
|
||||
/* TODO: wait a bit for the bus to come up.. ideally session_bus_up() won't return
|
||||
* until one can connect to the bus but that's not how things work right now
|
||||
*/
|
||||
usleep (500 * 1000);
|
||||
|
||||
error = NULL;
|
||||
c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (c != NULL);
|
||||
|
||||
error = NULL;
|
||||
p = g_dbus_proxy_new_sync (c,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo* */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface name */
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* we shouldn't have a name owner nor any cached properties */
|
||||
g_assert_cmpstr (g_dbus_proxy_get_name_owner (p), ==, NULL);
|
||||
g_assert (g_dbus_proxy_get_cached_property_names (p) == NULL);
|
||||
|
||||
/* also for async: we shouldn't have a name owner nor any cached properties */
|
||||
g_dbus_proxy_new (c,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo* */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface name */
|
||||
NULL, /* GCancellable */
|
||||
(GAsyncReadyCallback) proxy_new_cb,
|
||||
&ap);
|
||||
g_main_loop_run (loop);
|
||||
g_assert_cmpstr (g_dbus_proxy_get_name_owner (ap), ==, NULL);
|
||||
g_assert (g_dbus_proxy_get_cached_property_names (ap) == NULL);
|
||||
|
||||
/* this is safe; testserver will exit once the bus goes away */
|
||||
g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
|
||||
|
||||
/* check that we get the notify::g-name-owner signal */
|
||||
_g_assert_property_notify (p, "g-name-owner");
|
||||
|
||||
/* Now we should have a name owner as well as properties */
|
||||
name_owner = g_dbus_proxy_get_name_owner (p);
|
||||
property_names = g_dbus_proxy_get_cached_property_names (p);
|
||||
g_assert (g_dbus_is_unique_name (name_owner));
|
||||
g_assert (property_names != NULL && g_strv_length (property_names) > 0);
|
||||
g_free (name_owner);
|
||||
g_strfreev (property_names);
|
||||
|
||||
/* if we create another proxy with the service being available, check that
|
||||
* it has a name owner and properties
|
||||
*/
|
||||
error = NULL;
|
||||
p2 = g_dbus_proxy_new_sync (c,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo* */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface name */
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
name_owner = g_dbus_proxy_get_name_owner (p2);
|
||||
property_names = g_dbus_proxy_get_cached_property_names (p2);
|
||||
g_assert (g_dbus_is_unique_name (name_owner));
|
||||
g_assert (property_names != NULL && g_strv_length (property_names) > 0);
|
||||
g_free (name_owner);
|
||||
g_strfreev (property_names);
|
||||
|
||||
/* also for async: we should have a name owner and cached properties */
|
||||
g_dbus_proxy_new (c,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo* */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface name */
|
||||
NULL, /* GCancellable */
|
||||
(GAsyncReadyCallback) proxy_new_cb,
|
||||
&ap2);
|
||||
g_main_loop_run (loop);
|
||||
name_owner = g_dbus_proxy_get_name_owner (ap2);
|
||||
property_names = g_dbus_proxy_get_cached_property_names (ap2);
|
||||
g_assert (g_dbus_is_unique_name (name_owner));
|
||||
g_assert (property_names != NULL && g_strv_length (property_names) > 0);
|
||||
g_free (name_owner);
|
||||
g_strfreev (property_names);
|
||||
|
||||
/* Check property value is the initial value */
|
||||
variant = g_dbus_proxy_get_cached_property (p, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (p2, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (ap, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (ap2, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
|
||||
g_variant_unref (variant);
|
||||
|
||||
/* Check that properties are updated on both p and p2 */
|
||||
result = g_dbus_proxy_call_sync (p,
|
||||
"FrobSetProperty",
|
||||
g_variant_new ("(sv)",
|
||||
"y",
|
||||
g_variant_new_byte (42)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (result != NULL);
|
||||
g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
|
||||
g_variant_unref (result);
|
||||
_g_assert_signal_received (p, "g-properties-changed");
|
||||
variant = g_dbus_proxy_get_cached_property (p, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (p2, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (ap, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
|
||||
g_variant_unref (variant);
|
||||
variant = g_dbus_proxy_get_cached_property (ap2, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
|
||||
g_variant_unref (variant);
|
||||
|
||||
/* Nuke the service and check that we get the signal and then don't
|
||||
* have a name owner nor any cached properties
|
||||
*/
|
||||
result = g_dbus_proxy_call_sync (p,
|
||||
"Quit",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (result != NULL);
|
||||
g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
|
||||
g_variant_unref (result);
|
||||
/* and wait... */
|
||||
_g_assert_property_notify (p, "g-name-owner");
|
||||
/* now we shouldn't have a name owner nor any cached properties */
|
||||
g_assert_cmpstr (g_dbus_proxy_get_name_owner (p), ==, NULL);
|
||||
g_assert (g_dbus_proxy_get_cached_property_names (p) == NULL);
|
||||
g_assert (g_dbus_proxy_get_cached_property (p, "y") == NULL);
|
||||
|
||||
/* now bring back the server and wait for the proxy to be updated.. now
|
||||
* the 'y' property should be back at 1...
|
||||
*/
|
||||
/* this is safe; testserver will exit once the bus goes away */
|
||||
g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
|
||||
/* check that we get the notify::g-name-owner signal */
|
||||
_g_assert_property_notify (p, "g-name-owner");
|
||||
/* Now we should have a name owner as well as properties */
|
||||
name_owner = g_dbus_proxy_get_name_owner (p);
|
||||
property_names = g_dbus_proxy_get_cached_property_names (p);
|
||||
g_assert (g_dbus_is_unique_name (name_owner));
|
||||
g_assert (property_names != NULL && g_strv_length (property_names) > 0);
|
||||
g_free (name_owner);
|
||||
g_strfreev (property_names);
|
||||
/* and finally check the 'y' property */
|
||||
variant = g_dbus_proxy_get_cached_property (p, "y");
|
||||
g_assert (variant != NULL);
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
|
||||
g_variant_unref (variant);
|
||||
|
||||
g_object_unref (p2);
|
||||
g_object_unref (p);
|
||||
g_object_unref (ap2);
|
||||
g_object_unref (ap);
|
||||
|
||||
g_object_unref (c);
|
||||
|
||||
/* tear down bus */
|
||||
session_bus_down ();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gint ret;
|
||||
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
/* all the tests rely on a shared main loop */
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* all the tests use a session bus with a well-known address that we can bring up and down
|
||||
* using session_bus_up() and session_bus_down().
|
||||
*/
|
||||
g_unsetenv ("DISPLAY");
|
||||
g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
|
||||
|
||||
g_test_add_func ("/gdbus/proxy-well-known-name", test_proxy_well_known_name);
|
||||
|
||||
ret = g_test_run();
|
||||
return ret;
|
||||
}
|
@ -34,10 +34,7 @@ static GMainLoop *loop = NULL;
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
test_methods (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy)
|
||||
test_methods (GDBusProxy *proxy)
|
||||
{
|
||||
GVariant *result;
|
||||
GError *error;
|
||||
@ -133,10 +130,7 @@ test_methods (GDBusConnection *connection,
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
test_properties (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy)
|
||||
test_properties (GDBusProxy *proxy)
|
||||
{
|
||||
GError *error;
|
||||
GVariant *variant;
|
||||
@ -281,10 +275,7 @@ test_proxy_signals_on_emit_signal_cb (GDBusProxy *proxy,
|
||||
}
|
||||
|
||||
static void
|
||||
test_signals (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy)
|
||||
test_signals (GDBusProxy *proxy)
|
||||
{
|
||||
GError *error;
|
||||
GString *s;
|
||||
@ -359,10 +350,7 @@ test_signals (GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void
|
||||
test_bogus_method_return (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy)
|
||||
test_bogus_method_return (GDBusProxy *proxy)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
@ -401,16 +389,8 @@ static const gchar *frob_dbus_interface_xml =
|
||||
static GDBusInterfaceInfo *frob_dbus_interface_info;
|
||||
|
||||
static void
|
||||
on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
test_expected_interface (GDBusProxy *proxy)
|
||||
{
|
||||
test_methods (connection, name, name_owner, proxy);
|
||||
test_properties (connection, name, name_owner, proxy);
|
||||
test_signals (connection, name, name_owner, proxy);
|
||||
|
||||
/* This is obviously wrong but expected interface is not set so we don't fail... */
|
||||
g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
|
||||
g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
|
||||
@ -419,12 +399,12 @@ on_proxy_appeared (GDBusConnection *connection,
|
||||
|
||||
/* Now repeat the method tests, with an expected interface set */
|
||||
g_dbus_proxy_set_interface_info (proxy, frob_dbus_interface_info);
|
||||
test_methods (connection, name, name_owner, proxy);
|
||||
test_methods (proxy);
|
||||
|
||||
/* And now one more test where we deliberately set the expected
|
||||
* interface definition incorrectly
|
||||
*/
|
||||
test_bogus_method_return (connection, name, name_owner, proxy);
|
||||
test_bogus_method_return (proxy);
|
||||
|
||||
/* Also check that we complain if setting a cached property of the wrong type */
|
||||
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
|
||||
@ -443,21 +423,14 @@ on_proxy_appeared (GDBusConnection *connection,
|
||||
|
||||
/* this should work, however (since the type is correct) */
|
||||
g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_proxy (void)
|
||||
{
|
||||
guint watcher_id;
|
||||
GDBusProxy *proxy;
|
||||
GDBusConnection *connection;
|
||||
GError *error;
|
||||
|
||||
session_bus_up ();
|
||||
|
||||
@ -466,27 +439,34 @@ test_proxy (void)
|
||||
*/
|
||||
usleep (500 * 1000);
|
||||
|
||||
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,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
on_proxy_appeared,
|
||||
on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
error = NULL;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
|
||||
NULL,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface */
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* this is safe; testserver will exit once the bus goes away */
|
||||
g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
|
||||
|
||||
g_main_loop_run (loop);
|
||||
_g_assert_property_notify (proxy, "g-name-owner");
|
||||
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
test_methods (proxy);
|
||||
test_properties (proxy);
|
||||
test_signals (proxy);
|
||||
test_expected_interface (proxy);
|
||||
|
||||
/* tear down bus */
|
||||
session_bus_down ();
|
||||
g_object_unref (proxy);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
@ -348,11 +348,7 @@ test_sleep_in_thread_func (gpointer _data)
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
GDBusProxy *proxy,
|
||||
gpointer user_data)
|
||||
test_method_calls_on_proxy (GDBusProxy *proxy)
|
||||
{
|
||||
guint n;
|
||||
|
||||
@ -453,33 +449,38 @@ on_proxy_appeared (GDBusConnection *connection,
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_proxy_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_method_calls_in_thread (void)
|
||||
{
|
||||
guint watcher_id;
|
||||
GDBusProxy *proxy;
|
||||
GDBusConnection *connection;
|
||||
GError *error;
|
||||
gchar *name_owner;
|
||||
|
||||
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,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
on_proxy_appeared,
|
||||
on_proxy_vanished,
|
||||
NULL,
|
||||
NULL);
|
||||
error = NULL;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
|
||||
NULL,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
error = NULL;
|
||||
proxy = g_dbus_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
"com.example.TestService", /* name */
|
||||
"/com/example/TestObject", /* object path */
|
||||
"com.example.Frob", /* interface */
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
name_owner = g_dbus_proxy_get_name_owner (proxy);
|
||||
g_assert_cmpstr (name_owner, !=, NULL);
|
||||
g_free (name_owner);
|
||||
|
||||
g_bus_unwatch_proxy (watcher_id);
|
||||
test_method_calls_on_proxy (proxy);
|
||||
|
||||
g_object_unref (proxy);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
Loading…
Reference in New Issue
Block a user