diff options
-rw-r--r-- | bin/dconf.c | 2 | ||||
-rw-r--r-- | client/dconf-client.c | 139 | ||||
-rw-r--r-- | client/dconf-client.h | 21 | ||||
-rw-r--r-- | engine/dconf-engine.c | 45 | ||||
-rw-r--r-- | engine/dconf-engine.h | 10 | ||||
-rw-r--r-- | gsettings/dconfsettingsbackend.c | 36 |
6 files changed, 195 insertions, 58 deletions
diff --git a/bin/dconf.c b/bin/dconf.c index 4cdde3e..5702d9b 100644 --- a/bin/dconf.c +++ b/bin/dconf.c @@ -233,7 +233,7 @@ main (int argc, char **argv) g_type_init (); g_set_prgname (shift (&argc, &argv)); - client = dconf_client_new (NULL, NULL, NULL, NULL); + client = dconf_client_new (NULL, FALSE, NULL, NULL, NULL); if (!do_sync_command (client, argc, argv, &error)) g_error ("%s\n", error->message); diff --git a/client/dconf-client.c b/client/dconf-client.c index c6e50c1..97e6ab7 100644 --- a/client/dconf-client.c +++ b/client/dconf-client.c @@ -6,7 +6,11 @@ struct _DConfClient { GObject parent_instance; + GDBusConnection *session_bus; + GDBusConnection *system_bus; + DConfEngine *engine; + gboolean will_write; DConfWatchFunc watch_func; gpointer user_data; @@ -92,18 +96,49 @@ dconf_client_async_op_complete (DConfClientAsyncOp *op, g_slice_free (DConfClientAsyncOp, op); } +static gboolean +dconf_client_interpret_reply (DConfEngineMessage *dcem, + GDBusMessage *reply, + gchar **tag, + GError **error) +{ + gboolean success; + + if (reply == NULL) + /* error will already have been set */ + return FALSE; + + + success = dconf_engine_interpret_reply (dcem, + g_dbus_message_get_sender (reply), + g_dbus_message_get_body (reply), + tag, error); + g_object_unref (reply); + + return success; +} + + static void dconf_client_async_op_call_done (GObject *object, GAsyncResult *result, gpointer user_data) { DConfClientAsyncOp *op = user_data; - GVariant *reply; + GDBusMessage *reply; - if ((reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), - result, &op->error))) - g_simple_async_result_set_op_res_gpointer (op->simple, reply, - (GDestroyNotify) g_variant_unref); + reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (object), + result, &op->error); + + if (reply != NULL) + { + gchar *tag; + + if (dconf_client_interpret_reply (&op->dcem, reply, &tag, &op->error)) + g_simple_async_result_set_op_res_gpointer (op->simple, tag, g_free); + + g_object_unref (reply); + } dconf_client_async_op_complete (op, FALSE); } @@ -141,7 +176,7 @@ static gboolean dconf_client_async_op_finish (gpointer client, GAsyncResult *result, gpointer source_tag, - guint64 *sequence, + gchar **tag, GError **error) { GSimpleAsyncResult *simple; @@ -154,9 +189,8 @@ dconf_client_async_op_finish (gpointer client, if (g_simple_async_result_propagate_error (simple, error)) return FALSE; - if (sequence) - g_variant_get (g_simple_async_result_get_op_res_gpointer (simple), - "(t)", sequence); + if (tag) + *tag = g_strdup (g_simple_async_result_get_op_res_gpointer (simple)); return TRUE; } @@ -198,6 +232,7 @@ dconf_client_class_init (DConfClientClass *class) **/ DConfClient * dconf_client_new (const gchar *context, + gboolean will_write, DConfWatchFunc watch_func, gpointer user_data, GDestroyNotify notify) @@ -205,6 +240,7 @@ dconf_client_new (const gchar *context, DConfClient *client = g_object_new (DCONF_TYPE_CLIENT, NULL); client->engine = dconf_engine_new (context); + client->will_write = will_write; client->watch_func = watch_func; client->user_data = user_data; client->notify = notify; @@ -272,10 +308,24 @@ dconf_client_read_no_default (DConfClient *client, return dconf_engine_read (client->engine, key, DCONF_READ_SET); } +static GDBusMessage * +dconf_client_create_call (DConfEngineMessage *dcem) +{ + GDBusMessage *message; + + message = g_dbus_message_new_method_call (dcem->destination, + dcem->object_path, + dcem->interface, + dcem->method); + g_dbus_message_set_body (message, dcem->body); + + return message; +} + static gboolean dconf_client_call_sync (DConfClient *client, DConfEngineMessage *dcem, - guint64 *sequence, + gchar **tag, GCancellable *cancellable, GError **error) { @@ -289,22 +339,17 @@ dconf_client_call_sync (DConfClient *client, if (dcem->body) { - GVariant *reply; + GDBusMessage *message, *reply; - reply = g_dbus_connection_call_sync (connection, dcem->destination, - dcem->object_path, dcem->interface, - dcem->method, dcem->body, - dcem->reply_type, - G_DBUS_CALL_FLAGS_NONE, -1, - cancellable, error); + message = dconf_client_create_call (dcem); + reply = g_dbus_connection_send_message_with_reply_sync (connection, + message, + -1, NULL, + cancellable, + error); + g_object_unref (message); - if (reply == NULL) - return FALSE; - - if (sequence) - g_variant_get (reply, "(t)", sequence); - - g_variant_unref (reply); + return dconf_client_interpret_reply (dcem, reply, tag, error); } return TRUE; @@ -313,6 +358,7 @@ dconf_client_call_sync (DConfClient *client, /** * dconf_client_write: * @client: a #DConfClient + * @key: a dconf key * @value (allow-none): a #GVariant, or %NULL * @sequence: (out) (allow-none): the sequence number of this write * @cancellable: a #GCancellable, or %NULL @@ -323,12 +369,15 @@ dconf_client_call_sync (DConfClient *client, * * If @value is %NULL then @key is reset to its default value (which may * be completely unset), otherwise @value becomes the new value. + * + * If @sequence is non-%NULL then it is set to the sequence number of + * this write. The sequence number is unique to this process. **/ gboolean dconf_client_write (DConfClient *client, const gchar *key, GVariant *value, - guint64 *sequence, + gchar **tag, GCancellable *cancellable, GError **error) { @@ -337,9 +386,24 @@ dconf_client_write (DConfClient *client, if (!dconf_engine_write (client->engine, &dcem, key, value, error)) return FALSE; - return dconf_client_call_sync (client, &dcem, sequence, cancellable, error); + return dconf_client_call_sync (client, &dcem, tag, cancellable, error); } +/** + * dconf_client_write_async: + * @client: a #DConfClient + * @key: a dconf key + * @value (allow-none): a #GVariant, or %NULL + * @cancellable: a #GCancellable, or %NULL + * @callback: the function to call when complete + * @user_data: the user data for @callback + * + * Writes a value to the given @key, or reset @key to its default value. + * + * This is the asynchronous version of dconf_client_write(). You should + * call dconf_client_write_finish() from @callback to collect the + * result. + **/ void dconf_client_write_async (DConfClient *client, const gchar *key, @@ -356,15 +420,23 @@ dconf_client_write_async (DConfClient *client, dconf_client_async_op_run (op); } +/** + * dconf_client_write_finish: + * @client: a #DConfClient + * @sequence: (out) (allow-none): the sequence number of this write + * @error: a pointer to a #GError, or %NULL + * + * Collects the result from a prior call to dconf_client_write_async(). + **/ gboolean dconf_client_write_finish (DConfClient *client, GAsyncResult *result, - guint64 *sequence, + gchar **tag, GError **error) { return dconf_client_async_op_finish (client, result, dconf_client_write_async, - sequence, error); + tag, error); } /** @@ -414,14 +486,12 @@ dconf_client_is_writable (DConfClient *client, return dconf_client_call_sync (client, &dcem, NULL, NULL, error); } - - gboolean dconf_client_write_many (DConfClient *client, const gchar *prefix, const gchar * const *rels, GVariant **values, - guint64 *sequence, + gchar **tag, GCancellable *cancellable, GError **error) { @@ -430,7 +500,7 @@ dconf_client_write_many (DConfClient *client, if (!dconf_engine_write_many (client->engine, &dcem, prefix, rels, values, error)) return FALSE; - return dconf_client_call_sync (client, &dcem, sequence, cancellable, error); + return dconf_client_call_sync (client, &dcem, tag, cancellable, error); } void @@ -454,12 +524,12 @@ dconf_client_write_many_async (DConfClient *client, gboolean dconf_client_write_many_finish (DConfClient *client, GAsyncResult *result, - guint64 *sequence, + gchar **tag, GError **error) { return dconf_client_async_op_finish (client, result, dconf_client_write_many_async, - sequence, error); + tag, error); } #if 0 @@ -485,4 +555,3 @@ gboolean dconf_client_unwatch_finish (DConfCl gpointer user_data); #endif - diff --git a/client/dconf-client.h b/client/dconf-client.h index 4f79cc2..989ad3c 100644 --- a/client/dconf-client.h +++ b/client/dconf-client.h @@ -13,16 +13,29 @@ typedef GObjectClass DConfClientClass; typedef struct _DConfClient DConfClient; typedef void (*DConfWatchFunc) (DConfClient *client, + const gchar *tag, const gchar *path, const gchar * const *items, gpointer user_data); GType dconf_client_get_type (void); + DConfClient * dconf_client_new (const gchar *context, + gboolean will_write, DConfWatchFunc watch_func, gpointer user_data, GDestroyNotify notify); +void dconf_client_new_async (const gchar *context, + gboolean will_write, + DConfWatchFunc watch_func, + gpointer watch_func_data, + GDestroyNotify notify, + GAsyncReadyCallback callback, + gpointer user_data); + +DConfClient * dconf_client_new_finish (GAsyncResult *result); + GVariant * dconf_client_read (DConfClient *client, const gchar *key); GVariant * dconf_client_read_default (DConfClient *client, @@ -41,7 +54,7 @@ gboolean dconf_client_is_writable (DConfCl gboolean dconf_client_write (DConfClient *client, const gchar *key, GVariant *value, - guint64 *sequence, + gchar **sequence, GCancellable *cancellable, GError **error); void dconf_client_write_async (DConfClient *client, @@ -52,7 +65,7 @@ void dconf_client_write_async (DConfCl gpointer user_data); gboolean dconf_client_write_finish (DConfClient *client, GAsyncResult *result, - guint64 *sequence, + gchar **sequence, GError **error); gboolean dconf_client_set_locked (DConfClient *client, @@ -74,7 +87,7 @@ gboolean dconf_client_write_many (DConfCl const gchar *prefix, const gchar * const *keys, GVariant **values, - guint64 *sequence, + gchar **sequence, GCancellable *cancellable, GError **error); void dconf_client_write_many_async (DConfClient *client, @@ -86,7 +99,7 @@ void dconf_client_write_many_async (DConfCl gpointer user_data); gboolean dconf_client_write_many_finish (DConfClient *client, GAsyncResult *result, - guint64 *sequence, + gchar **sequence, GError **error); gboolean dconf_client_watch (DConfClient *client, diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c index 14054c9..1e36126 100644 --- a/engine/dconf-engine.c +++ b/engine/dconf-engine.c @@ -221,16 +221,28 @@ dconf_engine_list (DConfEngine *engine, return list; } +static gchar * +dconf_engine_make_tag (guint bus_type, + const gchar *sender, + guint64 seqno) +{ + return g_strdup_printf ("%c/%s/%"G_GUINT64_FORMAT, bus_type, sender, seqno); +} + gboolean dconf_engine_decode_notify (DConfEngine *engine, - guint64 anti_expose, + const gchar *anti_expose, const gchar **path, const gchar ***rels, + guint bus_type, + const gchar *sender, const gchar *iface, const gchar *method, GVariant *body) { - guint64 ae; + gboolean matched; + guint64 seqno; + gchar *ae; if (strcmp (iface, "ca.desrt.dconf.Writer") || strcmp (method, "Notify")) return FALSE; @@ -238,12 +250,37 @@ dconf_engine_decode_notify (DConfEngine *engine, if (!g_variant_is_of_type (body, G_VARIANT_TYPE ("(tsas)"))) return FALSE; - g_variant_get_child (body, 0, "t", &ae); + g_variant_get_child (body, 0, "t", &seqno); + + ae = dconf_engine_make_tag (bus_type, sender, seqno); + matched = strcmp (ae, anti_expose) == 0; + g_free (ae); - if (ae == anti_expose) + if (matched) return FALSE; g_variant_get (body, "(t&s^a&s)", NULL, path, rels); return TRUE; } + +gboolean +dconf_engine_interpret_reply (DConfEngineMessage *dcem, + const gchar *sender, + GVariant *body, + gchar **tag, + GError **error) +{ + /* typecheck and so on... */ + + if (tag != NULL) + { + guint64 sequence; + + g_variant_get_child (body, 0, "t", &sequence); + + *tag = dconf_engine_make_tag (dcem->bus_type, sender, sequence); + } + + return TRUE; +} diff --git a/engine/dconf-engine.h b/engine/dconf-engine.h index 2cf72c8..af9547c 100644 --- a/engine/dconf-engine.h +++ b/engine/dconf-engine.h @@ -61,9 +61,11 @@ void dconf_engine_unwatch (DConfEn DConfEngineMessage *message, const gchar *name); gboolean dconf_engine_decode_notify (DConfEngine *engine, - guint64 anti_expose, + const gchar *anti_expose, const gchar **prefix, const gchar ***keys, + guint bus_type, + const gchar *sender, const gchar *interface, const gchar *member, GVariant *body); @@ -72,4 +74,10 @@ void dconf_engine_set_locked (DConfEn const gchar *path, gboolean locked); +gboolean dconf_engine_interpret_reply (DConfEngineMessage *message, + const gchar *sender, + GVariant *body, + gchar **tag, + GError **error); + #endif /* _dconf_engine_h_ */ diff --git a/gsettings/dconfsettingsbackend.c b/gsettings/dconfsettingsbackend.c index 878409d..f3a549a 100644 --- a/gsettings/dconfsettingsbackend.c +++ b/gsettings/dconfsettingsbackend.c @@ -37,9 +37,9 @@ typedef struct DConfEngine *engine; GDBusConnection *session_bus; - guint64 session_anti_expose; + gchar *session_anti_expose; GDBusConnection *system_bus; - guint64 system_anti_expose; + gchar *system_anti_expose; Outstanding *outstanding; } DConfSettingsBackend; @@ -103,9 +103,10 @@ dconf_settings_backend_new_outstanding (DConfSettingsBackend *dcsb, } static gboolean -dconf_settings_backend_remove_outstanding (DConfSettingsBackend *dcsb, - GDBusMessage *message, - guint64 *anti_expose) +dconf_settings_backend_remove_outstanding (DConfSettingsBackend *dcsb, + guint bus_type, + GDBusMessage *message, + gchar **anti_expose) { gboolean found = FALSE; Outstanding **node; @@ -247,13 +248,15 @@ dconf_settings_backend_scan_outstanding (DConfSettingsBackend *backend, static void dconf_settings_backend_incoming_signal (DConfSettingsBackend *dcsb, + guint bt, GDBusMessage *message, - const guint64 *anti_expose) + const gchar *anti_expose) { const gchar **rels; const gchar *path; - if (dconf_engine_decode_notify (dcsb->engine, *anti_expose, &path, &rels, + if (dconf_engine_decode_notify (dcsb->engine, anti_expose, &path, &rels, bt, + g_dbus_message_get_sender (message), g_dbus_message_get_interface (message), g_dbus_message_get_member (message), g_dbus_message_get_body (message))) @@ -279,13 +282,19 @@ dconf_settings_backend_filter (GDBusConnection *connection, gpointer user_data) { DConfSettingsBackend *dcsb = user_data; - guint64 *ae; + guint bus_type; + gchar **ae; if (connection == dcsb->session_bus) - ae = &dcsb->session_anti_expose; - + { + ae = &dcsb->session_anti_expose; + bus_type = 'e'; + } else if (connection == dcsb->system_bus) - ae = &dcsb->system_anti_expose; + { + ae = &dcsb->system_anti_expose; + bus_type = 'y'; + } else g_assert_not_reached (); @@ -293,10 +302,11 @@ dconf_settings_backend_filter (GDBusConnection *connection, switch (g_dbus_message_get_message_type (message)) { case G_DBUS_MESSAGE_TYPE_METHOD_RETURN: - return dconf_settings_backend_remove_outstanding (dcsb, message, ae); + return dconf_settings_backend_remove_outstanding (dcsb, bus_type, + message, ae); case G_DBUS_MESSAGE_TYPE_SIGNAL: - dconf_settings_backend_incoming_signal (dcsb, message, ae); + dconf_settings_backend_incoming_signal (dcsb, bus_type, message, *ae); default: return FALSE; |