diff options
-rw-r--r-- | src/messages-service-dbus.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/messages-service-dbus.c b/src/messages-service-dbus.c index 1585ac0..2b72f2e 100644 --- a/src/messages-service-dbus.c +++ b/src/messages-service-dbus.c @@ -42,6 +42,8 @@ typedef struct _MessageServiceDbusPrivate MessageServiceDbusPrivate; struct _MessageServiceDbusPrivate { GDBusConnection * connection; + GCancellable * accounts_cancel; + GDBusProxy * accounts_user; gboolean dot; gboolean hidden; }; @@ -155,9 +157,199 @@ connection_cb (GObject * object, GAsyncResult * res, gpointer user_data) } static void +accounts_notify_cb (GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GError * error = NULL; + GVariant * answer = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; /* Must exit before accessing freed memory */ + } + + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); + + if (priv->accounts_cancel != NULL) { + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + if (error != NULL) { + g_warning("Unable to get notify accounts service of message status: %s", error->message); + g_error_free(error); + return; + } + + g_variant_unref (answer); +} + +static void +accounts_notify (MessageServiceDbus *self) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + + if (priv->accounts_user == NULL) + return; /* We're not able to talk to accounts service */ + + if (priv->accounts_cancel != NULL) { + /* Cancel old notify before starting new one */ + g_cancellable_cancel(priv->accounts_cancel); + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + priv->accounts_cancel = g_cancellable_new(); + g_dbus_proxy_call(priv->accounts_user, + "SetXHasMessages", + g_variant_new ("(b)", priv->dot), + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + priv->accounts_cancel, + accounts_notify_cb, + self); +} + +static void +get_accounts_user_proxy_cb (GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GError * error = NULL; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; /* Must exit before accessing freed memory */ + } + + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); + + if (priv->accounts_cancel != NULL) { + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + if (error != NULL) { + g_warning("Unable to get proxy of accountsservice: %s", error->message); + g_error_free(error); + return; + } + + priv->accounts_user = proxy; + accounts_notify (MESSAGE_SERVICE_DBUS (user_data)); +} + +static void +get_accounts_user_find_user_cb (GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GError * error = NULL; + GVariant * answer = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error); + + /* We're done with main accounts proxy now */ + g_object_unref (source_object); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; /* Must exit before accessing freed memory */ + } + + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); + + if (priv->accounts_cancel != NULL) { + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + if (error != NULL) { + g_warning("Unable to get object name of user from accountsservice: %s", error->message); + g_error_free(error); + return; + } + + if (!g_variant_is_of_type (answer, G_VARIANT_TYPE ("(o)"))) { + g_warning("Unexpected type from FindUserByName: %s", g_variant_get_type_string (answer)); + g_variant_unref(answer); + return; + } + + const gchar *path; + g_variant_get(answer, "(&o)", &path); + + priv->accounts_cancel = g_cancellable_new(); + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.Accounts", + path, + "org.freedesktop.Accounts.User", + priv->accounts_cancel, + get_accounts_user_proxy_cb, + user_data); + + g_variant_unref (answer); +} + +static void +get_accounts_proxy_cb (GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GError * error = NULL; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; /* Must exit before accessing freed memory */ + } + + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); + + if (priv->accounts_cancel != NULL) { + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + if (error != NULL) { + g_warning("Unable to get proxy of accountsservice: %s", error->message); + g_error_free(error); + return; + } + + priv->accounts_cancel = g_cancellable_new(); + g_dbus_proxy_call(proxy, + "FindUserByName", + g_variant_new ("(s)", g_get_user_name ()), + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + priv->accounts_cancel, + get_accounts_user_find_user_cb, + user_data); +} + +static void +get_accounts_proxy (MessageServiceDbus *self) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + + g_return_if_fail(priv->accounts_cancel == NULL); + + priv->accounts_cancel = g_cancellable_new(); + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + "org.freedesktop.Accounts", + priv->accounts_cancel, + get_accounts_proxy_cb, + self); +} + +static void message_service_dbus_init (MessageServiceDbus *self) { g_bus_get(G_BUS_TYPE_SESSION, NULL, connection_cb, self); + get_accounts_proxy (self); MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); @@ -177,6 +369,17 @@ message_service_dbus_dispose (GObject *object) priv->connection = NULL; } + if (priv->accounts_cancel != NULL) { + g_cancellable_cancel(priv->accounts_cancel); + g_object_unref(priv->accounts_cancel); + priv->accounts_cancel = NULL; + } + + if (priv->accounts_user != NULL) { + g_object_unref(priv->accounts_user); + priv->accounts_user = NULL; + } + G_OBJECT_CLASS (message_service_dbus_parent_class)->dispose (object); return; } @@ -240,6 +443,8 @@ message_service_dbus_set_attention (MessageServiceDbus * self, gboolean attentio g_variant_new("(b)", priv->dot), NULL); } + + accounts_notify (self); } return; } |