aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/application-service-appstore.c250
1 files changed, 176 insertions, 74 deletions
diff --git a/src/application-service-appstore.c b/src/application-service-appstore.c
index 9523fed..6bc82eb 100644
--- a/src/application-service-appstore.c
+++ b/src/application-service-appstore.c
@@ -34,6 +34,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
/* DBus Prototypes */
static GVariant * get_applications (ApplicationServiceAppstore * appstore);
static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data);
+static void props_cb (GObject * object, GAsyncResult * res, gpointer user_data);
#include "gen-application-service.xml.h"
@@ -91,6 +92,9 @@ struct _Application {
ApplicationServiceAppstore * appstore; /* not ref'd */
GCancellable * dbus_proxy_cancel;
GDBusProxy * dbus_proxy;
+ GCancellable * props_cancel;
+ gboolean queued_props;
+ GDBusProxy * props;
gboolean validated; /* Whether we've gotten all the parameters and they look good. */
AppIndicatorStatus status;
gchar * icon;
@@ -137,6 +141,7 @@ static void dbus_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_d
static void app_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
static void approver_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
static void approver_receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
+static void get_all_properties (Application * app);
G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
@@ -370,104 +375,133 @@ load_override_file (GHashTable * hash, const gchar * filename)
}
/* Return from getting the properties from the item. We're looking at those
- and making sure we have everythign that we need. If we do, then we'll
+ and making sure we have everything that we need. If we do, then we'll
move on up to sending this onto the indicator. */
static void
-get_all_properties (Application * app)
+got_all_properties (GObject * source_object, GAsyncResult * res,
+ gpointer user_data)
{
+ Application * app = (Application *)user_data;
+ g_return_if_fail(app != NULL);
+
+ GError * error = NULL;
ApplicationServiceAppstorePrivate * priv = app->appstore->priv;
- GVariant * menu, * id, * category, * status, * icon_name;
-
- menu = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_MENU);
- id = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_ID);
- category = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_CATEGORY);
- status = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_STATUS);
- icon_name = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_ICON_NAME);
+ GVariant * menu = NULL, * id = NULL, * category = NULL,
+ * status = NULL, * icon_name = NULL, * aicon_name = NULL,
+ * icon_theme_path = NULL, * index = NULL, * label = NULL,
+ * guide = NULL;
+
+ GVariant * properties = g_dbus_proxy_call_finish(app->props, res, &error);
+
+ if (app->props_cancel != NULL) {
+ g_object_unref(app->props_cancel);
+ app->props_cancel = NULL;
+ }
+
+ if (error != NULL) {
+ g_error("Could not grab DBus properties for %s: %s", app->dbus_name, error->message);
+ g_error_free(error);
+ return;
+ }
+
+ /* Grab all properties from variant */
+ GVariantIter * iter = NULL;
+ const gchar * name = NULL;
+ GVariant * value = NULL;
+ g_variant_get(properties, "(a{sv})", &iter);
+ while (g_variant_iter_loop (iter, "{&sv}", &name, &value)) {
+ if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_MENU) == 0) {
+ menu = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ID) == 0) {
+ id = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_CATEGORY) == 0) {
+ category = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_STATUS) == 0) {
+ status = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ICON_NAME) == 0) {
+ icon_name = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_AICON_NAME) == 0) {
+ aicon_name = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ICON_THEME_PATH) == 0) {
+ icon_theme_path = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_ORDERING_INDEX) == 0) {
+ index = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_LABEL) == 0) {
+ label = g_variant_ref(value);
+ } else if (g_strcmp0(name, NOTIFICATION_ITEM_PROP_LABEL_GUIDE) == 0) {
+ guide = g_variant_ref(value);
+ } /* else ignore */
+ }
+ g_variant_iter_free (iter);
if (menu == NULL || id == NULL || category == NULL || status == NULL ||
icon_name == NULL) {
g_warning("Notification Item on object %s of %s doesn't have enough properties.", app->dbus_object, app->dbus_name);
- if (menu) g_variant_unref (menu);
- if (id) g_variant_unref (id);
- if (category) g_variant_unref (category);
- if (status) g_variant_unref (status);
- if (icon_name) g_variant_unref (icon_name);
g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for.
- return;
}
+ else {
+ app->validated = TRUE;
- app->validated = TRUE;
+ app->id = g_variant_dup_string(id, NULL);
+ app->category = g_variant_dup_string(category, NULL);
+ app->status = string_to_status(g_variant_get_string(status, NULL));
+ app->icon = g_variant_dup_string(icon_name, NULL);
+ app->menu = g_variant_dup_string(menu, NULL);
- app->id = g_variant_dup_string(id, NULL);
- app->category = g_variant_dup_string(category, NULL);
- app->status = string_to_status(g_variant_get_string(status, NULL));
- app->icon = g_variant_dup_string(icon_name, NULL);
- app->menu = g_variant_dup_string(menu, NULL);
+ g_debug("Changing app '%s' icon from %s", app->id, app->icon);
- /* Now the optional properties */
+ /* Now the optional properties */
- GVariant * aicon_name, * icon_theme_path, * index, * label, * guide;
+ if (aicon_name != NULL) {
+ app->aicon = g_variant_dup_string(aicon_name, NULL);
+ }
- aicon_name = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_AICON_NAME);
- icon_theme_path = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_ICON_THEME_PATH);
- index = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_ORDERING_INDEX);
- label = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_LABEL);
- guide = g_dbus_proxy_get_cached_property(app->dbus_proxy,
- NOTIFICATION_ITEM_PROP_LABEL_GUIDE);
+ if (icon_theme_path != NULL) {
+ app->icon_theme_path = g_variant_dup_string(icon_theme_path, NULL);
+ } else {
+ app->icon_theme_path = g_strdup("");
+ }
- if (aicon_name != NULL) {
- app->aicon = g_variant_dup_string(aicon_name, NULL);
- }
+ gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
+ if (ordering_index_over == NULL) {
+ if (index == NULL || g_variant_get_uint32(index) == 0) {
+ app->ordering_index = generate_id(string_to_cat(app->category), app->id);
+ } else {
+ app->ordering_index = g_variant_get_uint32(index);
+ }
+ } else {
+ app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
+ }
+ g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
- if (icon_theme_path != NULL) {
- app->icon_theme_path = g_variant_dup_string(icon_theme_path, NULL);
- } else {
- app->icon_theme_path = g_strdup("");
- }
+ if (label != NULL) {
+ app->label = g_variant_dup_string(label, NULL);
+ } else {
+ app->label = g_strdup("");
+ }
- gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
- if (ordering_index_over == NULL) {
- if (index == NULL || g_variant_get_uint32(index) == 0) {
- app->ordering_index = generate_id(string_to_cat(app->category), app->id);
+ if (guide != NULL) {
+ app->guide = g_variant_dup_string(guide, NULL);
} else {
- app->ordering_index = g_variant_get_uint32(index);
+ app->guide = g_strdup("");
}
- } else {
- app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
- }
- g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
- if (label != NULL) {
- app->label = g_variant_dup_string(label, NULL);
- } else {
- app->label = g_strdup("");
- }
+ priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, NULL);
+ g_list_foreach(priv->approvers, check_with_old_approver, app);
- if (guide != NULL) {
- app->guide = g_variant_dup_string(guide, NULL);
- } else {
- app->guide = g_strdup("");
+ apply_status(app);
}
- priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, NULL);
- g_list_foreach(priv->approvers, check_with_old_approver, app);
-
- apply_status(app);
+ if (app->queued_props) {
+ get_all_properties(app);
+ app->queued_props = FALSE;
+ }
- g_variant_unref (menu);
- g_variant_unref (id);
- g_variant_unref (category);
- g_variant_unref (status);
- g_variant_unref (icon_name);
+ if (menu) g_variant_unref (menu);
+ if (id) g_variant_unref (id);
+ if (category) g_variant_unref (category);
+ if (status) g_variant_unref (status);
+ if (icon_name) g_variant_unref (icon_name);
if (aicon_name) g_variant_unref (aicon_name);
if (icon_theme_path) g_variant_unref (icon_theme_path);
if (index) g_variant_unref (index);
@@ -477,6 +511,21 @@ get_all_properties (Application * app)
return;
}
+static void
+get_all_properties (Application * app)
+{
+ if (app->props != NULL && app->props_cancel == NULL) {
+ g_dbus_proxy_call(app->props, "GetAll",
+ g_variant_new("(s)", NOTIFICATION_ITEM_DBUS_IFACE),
+ G_DBUS_CALL_FLAGS_NONE, -1, app->props_cancel,
+ got_all_properties, app);
+ }
+ else {
+ g_debug("Queuing a properties check");
+ app->queued_props = TRUE;
+ }
+}
+
/* Check the application against an approver */
static void
check_with_old_approver (gpointer papprove, gpointer papp)
@@ -579,6 +628,16 @@ application_free (Application * app)
app->name_watcher = 0;
}
+ if (app->props) {
+ g_object_unref(app->props);
+ }
+
+ if (app->props_cancel != NULL) {
+ g_cancellable_cancel(app->props_cancel);
+ g_object_unref(app->props_cancel);
+ app->props_cancel = NULL;
+ }
+
if (app->dbus_proxy) {
g_object_unref(app->dbus_proxy);
}
@@ -895,7 +954,7 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
Application * app = find_application(appstore, dbus_name, dbus_object);
if (app != NULL) {
- g_warning("Application already exists! Rerequesting properties.");
+ g_warning("Application already exists, re-requesting properties.");
get_all_properties(app);
return;
}
@@ -920,6 +979,9 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
app->approved_by = NULL;
app->visible_state = VISIBLE_STATE_HIDDEN;
app->name_watcher = 0;
+ app->props_cancel = NULL;
+ app->props = NULL;
+ app->queued_props = FALSE;
/* Get the DBus proxy for the NotificationItem interface */
app->dbus_proxy_cancel = g_cancellable_new();
@@ -994,6 +1056,46 @@ dbus_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
g_signal_connect(proxy, "g-signal", G_CALLBACK(app_receive_signal), app);
+ app->props_cancel = g_cancellable_new();
+ g_dbus_proxy_new(g_dbus_proxy_get_connection(proxy),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ app->dbus_name,
+ app->dbus_object,
+ "org.freedesktop.DBus.Properties",
+ app->props_cancel,
+ props_cb,
+ app);
+
+ return;
+}
+
+/* Callback from trying to create the proxy for the app. */
+static void
+props_cb (GObject * object, GAsyncResult * res, gpointer user_data)
+{
+ GError * error = NULL;
+
+ Application * app = (Application *)user_data;
+ g_return_if_fail(app != NULL);
+
+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
+
+ if (app->props_cancel != NULL) {
+ g_object_unref(app->props_cancel);
+ app->props_cancel = NULL;
+ }
+
+ if (error != NULL) {
+ g_error("Could not grab Properties DBus proxy for %s: %s", app->dbus_name, error->message);
+ g_error_free(error);
+ return;
+ }
+
+ /* Okay, we're good to grab the proxy at this point, we're
+ sure that it's ours. */
+ app->props = proxy;
+
get_all_properties(app);
return;