Merge branch 'snap-fixes' into 'master'
snap: fix handling of pathless desktop files and support fallback desktop files See merge request GNOME/libnotify!23
This commit is contained in:
commit
642ba007ca
|
@ -69,6 +69,10 @@ struct _NotifyNotificationPrivate
|
||||||
char *summary;
|
char *summary;
|
||||||
char *body;
|
char *body;
|
||||||
|
|
||||||
|
const char *snap_path;
|
||||||
|
const char *snap_name;
|
||||||
|
char *snap_app;
|
||||||
|
|
||||||
/* NULL to use icon data. Anything else to have server lookup icon */
|
/* NULL to use icon data. Anything else to have server lookup icon */
|
||||||
char *icon_name;
|
char *icon_name;
|
||||||
|
|
||||||
|
@ -350,6 +354,104 @@ destroy_pair (CallbackPair *pair)
|
||||||
g_free (pair);
|
g_free (pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_initialize_snap (NotifyNotification *obj)
|
||||||
|
{
|
||||||
|
NotifyNotificationPrivate *priv = obj->priv;
|
||||||
|
gchar *cgroup_contents = NULL;
|
||||||
|
|
||||||
|
priv->snap_path = g_getenv ("SNAP");
|
||||||
|
if (priv->snap_path == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*priv->snap_path == '\0' ||
|
||||||
|
!strchr (priv->snap_path, G_DIR_SEPARATOR)) {
|
||||||
|
priv->snap_path = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->snap_name = g_getenv ("SNAP_NAME");
|
||||||
|
if (priv->snap_name && *priv->snap_name == '\0') {
|
||||||
|
priv->snap_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_file_get_contents ("/proc/self/cgroup", &cgroup_contents,
|
||||||
|
NULL, NULL)) {
|
||||||
|
gchar **lines = g_strsplit (cgroup_contents, "\n", -1);
|
||||||
|
gchar *found_snap_name = NULL;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; lines[i]; ++i) {
|
||||||
|
gchar **parts = g_strsplit (lines[i], ":", 3);
|
||||||
|
gchar *basename;
|
||||||
|
gchar **ns;
|
||||||
|
guint ns_length;
|
||||||
|
|
||||||
|
if (g_strv_length (parts) != 3) {
|
||||||
|
g_strfreev (parts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
basename = g_path_get_basename (parts[2]);
|
||||||
|
g_strfreev (parts);
|
||||||
|
|
||||||
|
if (!basename) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ns = g_strsplit (basename, ".", -1);
|
||||||
|
ns_length = g_strv_length (ns);
|
||||||
|
g_free (basename);
|
||||||
|
|
||||||
|
if (ns_length < 2 || !g_str_equal (ns[0], "snap")) {
|
||||||
|
g_strfreev (ns);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->snap_name == NULL) {
|
||||||
|
g_free (found_snap_name);
|
||||||
|
found_snap_name = g_strdup (ns[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ns_length < 3) {
|
||||||
|
g_strfreev (ns);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->snap_name == NULL) {
|
||||||
|
priv->snap_name = found_snap_name;
|
||||||
|
found_snap_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_str_equal (ns[1], priv->snap_name)) {
|
||||||
|
priv->snap_app = g_strdup (ns[2]);
|
||||||
|
g_strfreev (ns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->snap_name == NULL && found_snap_name != NULL) {
|
||||||
|
priv->snap_name = found_snap_name;
|
||||||
|
found_snap_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (lines);
|
||||||
|
g_free (found_snap_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->snap_app == NULL) {
|
||||||
|
priv->snap_app = g_strdup (priv->snap_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("SNAP path: %s", priv->snap_path);
|
||||||
|
g_debug ("SNAP name: %s", priv->snap_name);
|
||||||
|
g_debug ("SNAP app: %s", priv->snap_app);
|
||||||
|
|
||||||
|
g_free (cgroup_contents);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_notification_init (NotifyNotification *obj)
|
notify_notification_init (NotifyNotification *obj)
|
||||||
{
|
{
|
||||||
|
@ -365,6 +467,8 @@ notify_notification_init (NotifyNotification *obj)
|
||||||
g_str_equal,
|
g_str_equal,
|
||||||
g_free,
|
g_free,
|
||||||
(GDestroyNotify) destroy_pair);
|
(GDestroyNotify) destroy_pair);
|
||||||
|
|
||||||
|
maybe_initialize_snap (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -380,6 +484,7 @@ notify_notification_finalize (GObject *object)
|
||||||
g_free (priv->summary);
|
g_free (priv->summary);
|
||||||
g_free (priv->body);
|
g_free (priv->body);
|
||||||
g_free (priv->icon_name);
|
g_free (priv->icon_name);
|
||||||
|
g_free (priv->snap_app);
|
||||||
|
|
||||||
if (priv->actions != NULL) {
|
if (priv->actions != NULL) {
|
||||||
g_slist_foreach (priv->actions, (GFunc) g_free, NULL);
|
g_slist_foreach (priv->actions, (GFunc) g_free, NULL);
|
||||||
|
@ -431,30 +536,52 @@ try_prepend_path (const char *base_path,
|
||||||
{
|
{
|
||||||
gchar *path_filename;
|
gchar *path_filename;
|
||||||
gchar *path_ret;
|
gchar *path_ret;
|
||||||
|
gboolean was_uri;
|
||||||
|
|
||||||
if (!path || *path == '\0')
|
if (!path || *path == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
was_uri = TRUE;
|
||||||
path_ret = NULL;
|
path_ret = NULL;
|
||||||
path_filename = g_filename_from_uri (base_path, NULL, NULL);
|
path_filename = g_filename_from_uri (base_path, NULL, NULL);
|
||||||
|
|
||||||
if (path_filename == NULL) {
|
if (path_filename == NULL) {
|
||||||
|
was_uri = FALSE;
|
||||||
|
|
||||||
if (base_path && base_path[0] == G_DIR_SEPARATOR) {
|
if (base_path && base_path[0] == G_DIR_SEPARATOR) {
|
||||||
path_filename = g_strdup (base_path);
|
path_filename = g_strdup (base_path);
|
||||||
} else {
|
} else {
|
||||||
path_filename = realpath (base_path, NULL);
|
path_filename = realpath (base_path, NULL);
|
||||||
|
|
||||||
|
if (path_filename == NULL) {
|
||||||
|
/* File path is not existing, but let's check
|
||||||
|
* if it's under the base path before giving up
|
||||||
|
*/
|
||||||
|
path_filename = g_strdup (base_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debug ("Trying to look at file '%s' in the '%s' prefix.",
|
if (g_str_has_prefix (path_filename, path)) {
|
||||||
base_path,
|
path_ret = g_strdup (path_filename);
|
||||||
path);
|
} else {
|
||||||
|
g_debug ("Trying to look at file '%s' in the '%s' prefix.",
|
||||||
path_ret = g_build_filename (path, path_filename, NULL);
|
base_path,
|
||||||
|
path);
|
||||||
|
path_ret = g_build_filename (path, path_filename, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!g_file_test (path_ret, G_FILE_TEST_EXISTS)) {
|
if (!g_file_test (path_ret, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_debug ("Nothing found at %s", path_ret);
|
||||||
g_free (path_ret);
|
g_free (path_ret);
|
||||||
path_ret = NULL;
|
path_ret = NULL;
|
||||||
|
} else if (was_uri) {
|
||||||
|
gchar *uri = g_filename_to_uri (path_ret, NULL, NULL);
|
||||||
|
|
||||||
|
if (uri != NULL) {
|
||||||
|
g_free (path_ret);
|
||||||
|
path_ret = uri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (path_filename);
|
g_free (path_filename);
|
||||||
|
@ -463,33 +590,33 @@ try_prepend_path (const char *base_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
try_prepend_desktop (const gchar *desktop)
|
try_prepend_snap_desktop (NotifyNotification *notification,
|
||||||
|
const gchar *desktop)
|
||||||
{
|
{
|
||||||
gchar *ret;
|
NotifyNotificationPrivate *priv = notification->priv;
|
||||||
|
gchar *ret = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if it's an absolute path, try prepending $SNAP, otherwise try
|
* if it's an absolute path, try prepending $SNAP, otherwise try
|
||||||
* $SNAP_NAME_; snap .desktop files are in the format
|
* ${SNAP_NAME}_; snap .desktop files are in the format
|
||||||
* ${SNAP_NAME}_desktop_file_name
|
* ${SNAP_NAME}_desktop_file_name
|
||||||
*/
|
*/
|
||||||
ret = try_prepend_path (desktop, g_getenv ("SNAP"));
|
ret = try_prepend_path (desktop, priv->snap_path);
|
||||||
|
|
||||||
if (ret == NULL) {
|
if (ret == NULL && priv->snap_name != NULL &&
|
||||||
const gchar *snap_name = g_getenv ("SNAP_NAME");
|
strchr (desktop, G_DIR_SEPARATOR) == NULL) {
|
||||||
|
ret = g_strdup_printf ("%s_%s", priv->snap_name, desktop);
|
||||||
if (snap_name != NULL && snap_name[0] != '\0') {
|
|
||||||
ret = g_strdup_printf ("%s_%s", snap_name, desktop);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
try_prepend_snap (const gchar *value)
|
try_prepend_snap (NotifyNotification *notification,
|
||||||
|
const gchar *value)
|
||||||
{
|
{
|
||||||
/* hardcoded paths to icons might be relocated under $SNAP */
|
/* hardcoded paths to icons might be relocated under $SNAP */
|
||||||
return try_prepend_path (value, g_getenv ("SNAP"));
|
return try_prepend_path (value, notification->priv->snap_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -524,7 +651,8 @@ notify_notification_update_internal (NotifyNotification *notification,
|
||||||
g_free (notification->priv->icon_name);
|
g_free (notification->priv->icon_name);
|
||||||
notification->priv->icon_name = (icon != NULL
|
notification->priv->icon_name = (icon != NULL
|
||||||
&& *icon != '\0' ? g_strdup (icon) : NULL);
|
&& *icon != '\0' ? g_strdup (icon) : NULL);
|
||||||
snapped_icon = try_prepend_desktop (notification->priv->icon_name);
|
snapped_icon = try_prepend_snap_desktop (notification,
|
||||||
|
notification->priv->icon_name);
|
||||||
if (snapped_icon != NULL) {
|
if (snapped_icon != NULL) {
|
||||||
g_debug ("Icon updated in snap environment: '%s' -> '%s'\n",
|
g_debug ("Icon updated in snap environment: '%s' -> '%s'\n",
|
||||||
notification->priv->icon_name, snapped_icon);
|
notification->priv->icon_name, snapped_icon);
|
||||||
|
@ -635,7 +763,7 @@ notify_notification_show (NotifyNotification *notification,
|
||||||
gpointer key, data;
|
gpointer key, data;
|
||||||
GVariant *result;
|
GVariant *result;
|
||||||
#ifdef GLIB_VERSION_2_32
|
#ifdef GLIB_VERSION_2_32
|
||||||
GApplication *application;
|
GApplication *application = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_return_val_if_fail (notification != NULL, FALSE);
|
g_return_val_if_fail (notification != NULL, FALSE);
|
||||||
|
@ -671,8 +799,24 @@ notify_notification_show (NotifyNotification *notification,
|
||||||
g_variant_builder_add (&hints_builder, "{sv}", key, data);
|
g_variant_builder_add (&hints_builder, "{sv}", key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->snap_app &&
|
||||||
|
g_hash_table_lookup (priv->hints, "desktop-entry") == NULL) {
|
||||||
|
gchar *snap_desktop;
|
||||||
|
|
||||||
|
snap_desktop = g_strdup_printf ("%s_%s",
|
||||||
|
priv->snap_name,
|
||||||
|
priv->snap_app);
|
||||||
|
|
||||||
|
g_debug ("Using desktop entry: %s", snap_desktop);
|
||||||
|
g_variant_builder_add (&hints_builder, "{sv}",
|
||||||
|
"desktop-entry",
|
||||||
|
g_variant_new_take_string (snap_desktop));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GLIB_VERSION_2_32
|
#ifdef GLIB_VERSION_2_32
|
||||||
application = g_application_get_default ();
|
if (!priv->snap_app) {
|
||||||
|
application = g_application_get_default ();
|
||||||
|
}
|
||||||
|
|
||||||
if (application != NULL) {
|
if (application != NULL) {
|
||||||
GVariant *desktop_entry = g_hash_table_lookup (priv->hints, "desktop-entry");
|
GVariant *desktop_entry = g_hash_table_lookup (priv->hints, "desktop-entry");
|
||||||
|
@ -680,6 +824,7 @@ notify_notification_show (NotifyNotification *notification,
|
||||||
if (desktop_entry == NULL) {
|
if (desktop_entry == NULL) {
|
||||||
const char *application_id = g_application_get_application_id (application);
|
const char *application_id = g_application_get_application_id (application);
|
||||||
|
|
||||||
|
g_debug ("Using desktop entry: %s", application_id);
|
||||||
g_variant_builder_add (&hints_builder, "{sv}", "desktop-entry",
|
g_variant_builder_add (&hints_builder, "{sv}", "desktop-entry",
|
||||||
g_variant_new_string (application_id));
|
g_variant_new_string (application_id));
|
||||||
}
|
}
|
||||||
|
@ -873,13 +1018,20 @@ notify_notification_set_image_from_pixbuf (NotifyNotification *notification,
|
||||||
notify_notification_set_hint (notification, hint_name, value);
|
notify_notification_set_hint (notification, hint_name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GVariant *
|
typedef gchar * (*StringParserFunc) (NotifyNotification *, const gchar *);
|
||||||
get_parsed_variant (GVariant *variant,
|
|
||||||
gchar *(*str_parser)(const gchar *))
|
|
||||||
{
|
|
||||||
gchar *parsed = str_parser (g_variant_get_string (variant, NULL));
|
|
||||||
|
|
||||||
if (parsed != NULL) {
|
static GVariant *
|
||||||
|
get_parsed_variant (NotifyNotification *notification,
|
||||||
|
const char *key,
|
||||||
|
GVariant *variant,
|
||||||
|
StringParserFunc str_parser)
|
||||||
|
{
|
||||||
|
const char *str = g_variant_get_string (variant, NULL);
|
||||||
|
gchar *parsed = str_parser (notification, str);
|
||||||
|
|
||||||
|
if (parsed != NULL && g_strcmp0 (str, parsed) != 0) {
|
||||||
|
g_debug ("Hint %s updated in snap environment: '%s' -> '%s'\n",
|
||||||
|
key, str, parsed);
|
||||||
g_variant_unref (variant);
|
g_variant_unref (variant);
|
||||||
variant = g_variant_new_take_string (parsed);
|
variant = g_variant_new_take_string (parsed);
|
||||||
}
|
}
|
||||||
|
@ -888,18 +1040,28 @@ get_parsed_variant (GVariant *variant,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GVariant *
|
static GVariant *
|
||||||
maybe_parse_snap_hint_value (const gchar *key,
|
maybe_parse_snap_hint_value (NotifyNotification *notification,
|
||||||
|
const gchar *key,
|
||||||
GVariant *value)
|
GVariant *value)
|
||||||
{
|
{
|
||||||
|
StringParserFunc parse_func = NULL;
|
||||||
|
|
||||||
|
if (!notification->priv->snap_path)
|
||||||
|
return value;
|
||||||
|
|
||||||
if (g_strcmp0 (key, "desktop-entry") == 0) {
|
if (g_strcmp0 (key, "desktop-entry") == 0) {
|
||||||
value = get_parsed_variant (value, try_prepend_desktop);
|
parse_func = try_prepend_snap_desktop;
|
||||||
} else if (g_strcmp0 (key, "image-path") == 0 ||
|
} else if (g_strcmp0 (key, "image-path") == 0 ||
|
||||||
g_strcmp0 (key, "image_path") == 0 ||
|
g_strcmp0 (key, "image_path") == 0 ||
|
||||||
g_strcmp0 (key, "sound-file") == 0) {
|
g_strcmp0 (key, "sound-file") == 0) {
|
||||||
value = get_parsed_variant (value, try_prepend_snap);
|
parse_func = try_prepend_snap;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
if (parse_func == NULL) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_parsed_variant (notification, key, value, parse_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -924,7 +1086,7 @@ notify_notification_set_hint (NotifyNotification *notification,
|
||||||
g_return_if_fail (key != NULL && *key != '\0');
|
g_return_if_fail (key != NULL && *key != '\0');
|
||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
value = maybe_parse_snap_hint_value (key, value);
|
value = maybe_parse_snap_hint_value (notification, key, value);
|
||||||
g_hash_table_insert (notification->priv->hints,
|
g_hash_table_insert (notification->priv->hints,
|
||||||
g_strdup (key),
|
g_strdup (key),
|
||||||
g_variant_ref_sink (value));
|
g_variant_ref_sink (value));
|
||||||
|
|
Loading…
Reference in New Issue