aboutsummaryrefslogtreecommitdiff
path: root/src/notifier.c
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2014-07-24 22:51:03 -0500
committerCharles Kerr <charles.kerr@canonical.com>2014-07-24 22:51:03 -0500
commite9ba47b83251f40234059b1bd2bc25e30b5aa9b2 (patch)
tree7360e76ec4be3e968e95cdc6de1aa1a69c733916 /src/notifier.c
parentb715352603062a4a4dbb5bc69388b1db632c34ae (diff)
downloadayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.tar.gz
ayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.tar.bz2
ayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.zip
in notifier.c, fix potential callchain loop when closing a notification
Diffstat (limited to 'src/notifier.c')
-rw-r--r--src/notifier.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/src/notifier.c b/src/notifier.c
index 1ac7e32..dc3a186 100644
--- a/src/notifier.c
+++ b/src/notifier.c
@@ -90,55 +90,71 @@ static void set_power_level_property (IndicatorPowerNotifier*,
***/
static void
+on_notify_notification_finalized (gpointer gself, GObject * dead)
+{
+ IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(gself);
+ priv_t * const p = get_priv(self);
+ g_return_if_fail ((void*)(p->notify_notification) == (void*)dead);
+ p->notify_notification = NULL;
+ set_is_warning_property (self, FALSE);
+}
+
+static void
notification_clear (IndicatorPowerNotifier * self)
{
priv_t * const p = get_priv(self);
+ NotifyNotification * nn;
- if (p->notify_notification != NULL)
+ if ((nn = p->notify_notification))
{
- set_is_warning_property (self, FALSE);
+ GError * error = NULL;
+
+ g_object_weak_unref(G_OBJECT(nn), on_notify_notification_finalized, self);
- notify_notification_clear_actions(p->notify_notification);
- g_signal_handlers_disconnect_by_data(p->notify_notification, self);
- g_clear_object(&p->notify_notification);
+ if (!notify_notification_close(nn, &error))
+ {
+ g_warning("Unable to close notification: %s", error->message);
+ g_error_free(error);
+ }
+
+ p->notify_notification = NULL;
+ set_is_warning_property(self, FALSE);
}
}
static void
notification_show(IndicatorPowerNotifier * self)
{
- priv_t * p;
+ priv_t * const p = get_priv(self);
+ gdouble pct;
char * body;
+ NotifyNotification * nn;
GError * error;
- notification_clear (self);
-
- p = get_priv (self);
+ notification_clear(self);
/* create the notification */
- body = g_strdup_printf(_("%.0f%% charge remaining"),
- indicator_power_device_get_percentage(p->battery));
- p->notify_notification = notify_notification_new(_("Battery Low"), body, NULL);
- notify_notification_set_hint(p->notify_notification,
- HINT_INTERACTIVE,
- g_variant_new_boolean(TRUE));
- g_signal_connect_swapped(p->notify_notification, "closed",
- G_CALLBACK(notification_clear), self);
-
- /* show the notification */
+ pct = indicator_power_device_get_percentage(p->battery);
+ body = g_strdup_printf(_("%.0f%% charge remaining"), pct);
+ nn = notify_notification_new(_("Battery Low"), body, NULL);
+ g_free (body);
+ notify_notification_set_hint(nn, HINT_INTERACTIVE, g_variant_new_boolean(TRUE));
+
+ /* if we can show it, keep it */
error = NULL;
- notify_notification_show(p->notify_notification, &error);
- if (error != NULL)
+ if (notify_notification_show(nn, &error))
{
- g_critical("Unable to show snap decision for '%s': %s", body, error->message);
- g_error_free(error);
+ p->notify_notification = nn;
+ g_signal_connect(nn, "closed", G_CALLBACK(g_object_unref), NULL);
+ g_object_weak_ref(G_OBJECT(nn), on_notify_notification_finalized, self);
+ set_is_warning_property(self, TRUE);
}
else
{
- set_is_warning_property (self, TRUE);
+ g_critical("Unable to show snap decision for '%s': %s", body, error->message);
+ g_error_free(error);
+ g_object_unref(nn);
}
-
- g_free (body);
}
/***