diff options
Diffstat (limited to 'src/application-service-appstore.c')
-rw-r--r-- | src/application-service-appstore.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/src/application-service-appstore.c b/src/application-service-appstore.c index 3e827d5..d2678fd 100644 --- a/src/application-service-appstore.c +++ b/src/application-service-appstore.c @@ -110,6 +110,7 @@ struct _Application { gchar * guide; gboolean currently_free; guint ordering_index; + GList * approver_cancels; GList * approved_by; visible_state_t visible_state; guint name_watcher; @@ -498,7 +499,8 @@ got_all_properties (GObject * source_object, GAsyncResult * res, 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); - g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for. + if (!app->validated) + application_free(app); } else { app->validated = TRUE; @@ -576,6 +578,7 @@ static void get_all_properties (Application * app) { if (app->props != NULL && app->props_cancel == NULL) { + app->props_cancel = g_cancellable_new(); g_dbus_proxy_call(app->props, "GetAll", g_variant_new("(s)", NOTIFICATION_ITEM_DBUS_IFACE), G_DBUS_CALL_FLAGS_NONE, -1, app->props_cancel, @@ -745,6 +748,11 @@ application_free (Application * app) if (app->guide != NULL) { g_free(app->guide); } + if (app->approver_cancels != NULL) { + g_list_foreach(app->approver_cancels, (GFunc)g_cancellable_cancel, NULL); + g_list_foreach(app->approver_cancels, (GFunc)g_object_unref, NULL); + g_list_free(app->approver_cancels); + } if (app->approved_by != NULL) { g_list_free(app->approved_by); } @@ -997,6 +1005,7 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst app->guide = NULL; app->currently_free = FALSE; app->ordering_index = 0; + app->approver_cancels = NULL; app->approved_by = NULL; app->visible_state = VISIBLE_STATE_HIDDEN; app->name_watcher = 0; @@ -1110,6 +1119,11 @@ props_cb (GObject * object, GAsyncResult * res, gpointer user_data) 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 + } + if (app->props_cancel != NULL) { g_object_unref(app->props_cancel); app->props_cancel = NULL; @@ -1283,6 +1297,24 @@ static void remove_approver (gpointer papp, gpointer pproxy) { Application * app = (Application *)papp; + + /* Check for any pending approvals and cancel them */ + GList * iter = app->approver_cancels; + while (iter != NULL) { + GCancellable * cancel = (GCancellable *)iter->data; + GDBusProxy * proxy = (GDBusProxy *)g_object_get_data(G_OBJECT(cancel), "proxy"); + if (proxy == pproxy) { + g_cancellable_cancel(cancel); + g_object_unref(cancel); + + GList * next = iter->next; + app->approver_cancels = g_list_delete_link(app->approver_cancels, iter); + iter = next; + } else { + iter = iter->next; + } + } + app->approved_by = g_list_remove(app->approved_by, pproxy); apply_status(app); return; @@ -1323,19 +1355,29 @@ static void approver_request_cb (GObject *object, GAsyncResult *res, gpointer user_data) { GDBusProxy * proxy = G_DBUS_PROXY(object); - Application * app = (Application *)user_data; + GCancellable * cancel = (GCancellable *)user_data; GError * error = NULL; gboolean approved = TRUE; /* default to approved */ GVariant * result; result = g_dbus_proxy_call_finish(proxy, 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 + } + + Application * app = (Application *)g_object_get_data(G_OBJECT(cancel), "app"); + app->approver_cancels = g_list_remove(app->approver_cancels, cancel); + g_object_unref(cancel); + if (error == NULL) { g_variant_get(result, "(b)", &approved); g_debug("Approver responded: %s", approved ? "approve" : "rejected"); } else { g_debug("Approver responded error: %s", error->message); + g_error_free (error); } if (approved) { @@ -1354,12 +1396,18 @@ check_with_new_approver (gpointer papp, gpointer papprove) { Application * app = (Application *)papp; Approver * approver = (Approver *)papprove; + GCancellable * cancel = NULL; + + cancel = g_cancellable_new(); + g_object_set_data(G_OBJECT(cancel), "app", app); + g_object_set_data(G_OBJECT(cancel), "proxy", approver->proxy); + app->approver_cancels = g_list_prepend(app->approver_cancels, cancel); g_dbus_proxy_call(approver->proxy, "ApproveItem", g_variant_new("(ssuso)", app->id, app->category, 0, app->dbus_name, app->dbus_object), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, - approver_request_cb, app); + G_DBUS_CALL_FLAGS_NONE, -1, cancel, + approver_request_cb, cancel); return; } |