From 60b40c4bfae3cec76ef55dedf2e096e2f8403705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Apr 2022 18:29:55 +0200 Subject: [PATCH 1/8] notification: Do not prepend SNAP prefix when is already present We used to just add it again, to eventually figure out that the file did not exists, but may not work properly in some scenarios. Also always fill the path_filename when using a file-name only, as that may be refer to something under the SNAP path, and in such case we want to try check if that exists before giving up. --- libnotify/notification.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index 1c442db..d3f0755 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -443,16 +443,27 @@ try_prepend_path (const char *base_path, path_filename = g_strdup (base_path); } else { 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.", - base_path, - path); - - path_ret = g_build_filename (path, path_filename, NULL); + if (g_str_has_prefix (path_filename, path)) { + path_ret = g_strdup (path_filename); + } else { + g_debug ("Trying to look at file '%s' in the '%s' prefix.", + base_path, + path); + path_ret = g_build_filename (path, path_filename, NULL); + } if (!g_file_test (path_ret, G_FILE_TEST_EXISTS)) { + g_debug ("Nothing found at %s", path_ret); g_free (path_ret); path_ret = NULL; } From d1f402294ee3993d617d9893aba8b00155c0910a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Apr 2022 18:33:28 +0200 Subject: [PATCH 2/8] notification: Do not try to append snap name to desktop when it's a path --- libnotify/notification.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index d3f0755..e1d6532 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -485,7 +485,7 @@ try_prepend_desktop (const gchar *desktop) */ ret = try_prepend_path (desktop, g_getenv ("SNAP")); - if (ret == NULL) { + if (ret == NULL && strchr (desktop, G_DIR_SEPARATOR) == NULL) { const gchar *snap_name = g_getenv ("SNAP_NAME"); if (snap_name != NULL && snap_name[0] != '\0') { From eba4dfa5405cc5a2b62d97502edc0d9b163c2891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Apr 2022 18:42:00 +0200 Subject: [PATCH 3/8] notification: Preserve snap details into the private struct We may need to use them in various places, so there's no point to repeat the same in multiple places, this way we can also use some shortcuts for non-snap setups. --- libnotify/notification.c | 84 +++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index e1d6532..475a978 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -69,6 +69,9 @@ struct _NotifyNotificationPrivate char *summary; char *body; + const char *snap_path; + const char *snap_name; + /* NULL to use icon data. Anything else to have server lookup icon */ char *icon_name; @@ -350,6 +353,30 @@ destroy_pair (CallbackPair *pair) g_free (pair); } +static void +maybe_initialize_snap (NotifyNotification *obj) +{ + NotifyNotificationPrivate *priv = obj->priv; + + 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; + } + + g_debug ("SNAP path: %s", priv->snap_path); + g_debug ("SNAP name: %s", priv->snap_name); +} + static void notify_notification_init (NotifyNotification *obj) { @@ -365,6 +392,8 @@ notify_notification_init (NotifyNotification *obj) g_str_equal, g_free, (GDestroyNotify) destroy_pair); + + maybe_initialize_snap (obj); } static void @@ -474,33 +503,37 @@ try_prepend_path (const char *base_path, } 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 - * $SNAP_NAME_; snap .desktop files are in the format + * ${SNAP_NAME}_; snap .desktop files are in the format * ${SNAP_NAME}_desktop_file_name */ - ret = try_prepend_path (desktop, g_getenv ("SNAP")); + ret = try_prepend_path (desktop, priv->snap_path); - if (ret == NULL && strchr (desktop, G_DIR_SEPARATOR) == NULL) { - const gchar *snap_name = g_getenv ("SNAP_NAME"); + if (ret == NULL && priv->snap_name != NULL && + 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); - } + if (ret) { + g_debug ("Using snap ID: %s", ret); } return ret; } 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 */ - return try_prepend_path (value, g_getenv ("SNAP")); + return try_prepend_path (value, notification->priv->snap_path); } @@ -535,7 +568,8 @@ notify_notification_update_internal (NotifyNotification *notification, g_free (notification->priv->icon_name); notification->priv->icon_name = (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) { g_debug ("Icon updated in snap environment: '%s' -> '%s'\n", notification->priv->icon_name, snapped_icon); @@ -884,11 +918,15 @@ notify_notification_set_image_from_pixbuf (NotifyNotification *notification, notify_notification_set_hint (notification, hint_name, value); } +typedef gchar * (*StringParserFunc) (NotifyNotification *, const gchar *); + static GVariant * -get_parsed_variant (GVariant *variant, - gchar *(*str_parser)(const gchar *)) +get_parsed_variant (NotifyNotification *notification, + GVariant *variant, + StringParserFunc str_parser) { - gchar *parsed = str_parser (g_variant_get_string (variant, NULL)); + const char *str = g_variant_get_string (variant, NULL); + gchar *parsed = str_parser (notification, str); if (parsed != NULL) { g_variant_unref (variant); @@ -899,15 +937,23 @@ get_parsed_variant (GVariant *variant, } static GVariant * -maybe_parse_snap_hint_value (const gchar *key, +maybe_parse_snap_hint_value (NotifyNotification *notification, + const gchar *key, GVariant *value) { + if (!notification->priv->snap_path) + return value; + if (g_strcmp0 (key, "desktop-entry") == 0) { - value = get_parsed_variant (value, try_prepend_desktop); + value = get_parsed_variant (notification, + value, + try_prepend_snap_desktop); } else if (g_strcmp0 (key, "image-path") == 0 || g_strcmp0 (key, "image_path") == 0 || g_strcmp0 (key, "sound-file") == 0) { - value = get_parsed_variant (value, try_prepend_snap); + value = get_parsed_variant (notification, + value, + try_prepend_snap); } return value; @@ -935,7 +981,7 @@ notify_notification_set_hint (NotifyNotification *notification, g_return_if_fail (key != NULL && *key != '\0'); 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_strdup (key), g_variant_ref_sink (value)); From a1dd92dc2a6694b5ac6e64004b7be9d07203304b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Apr 2022 20:08:39 +0200 Subject: [PATCH 4/8] notification: Use snap name and app name as fallback desktop-entry Snaps use desktop IDs based on the snap name and the application name inside the snap, so if we're in a such container, we need to compute the desktop-entry using those values. We can figure them out from the snap cgroup they're in. In such case, don't even try to use the GApplication ID as that is likely wrong in a snapped environment. --- libnotify/notification.c | 97 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index 475a978..ba3e6e8 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -71,6 +71,7 @@ struct _NotifyNotificationPrivate const char *snap_path; const char *snap_name; + char *snap_app; /* NULL to use icon data. Anything else to have server lookup icon */ char *icon_name; @@ -357,6 +358,7 @@ 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) @@ -373,8 +375,81 @@ maybe_initialize_snap (NotifyNotification *obj) 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 @@ -409,6 +484,7 @@ notify_notification_finalize (GObject *object) g_free (priv->summary); g_free (priv->body); g_free (priv->icon_name); + g_free (priv->snap_app); if (priv->actions != NULL) { g_slist_foreach (priv->actions, (GFunc) g_free, NULL); @@ -680,7 +756,7 @@ notify_notification_show (NotifyNotification *notification, gpointer key, data; GVariant *result; #ifdef GLIB_VERSION_2_32 - GApplication *application; + GApplication *application = NULL; #endif g_return_val_if_fail (notification != NULL, FALSE); @@ -716,8 +792,24 @@ notify_notification_show (NotifyNotification *notification, 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 - application = g_application_get_default (); + if (!priv->snap_app) { + application = g_application_get_default (); + } if (application != NULL) { GVariant *desktop_entry = g_hash_table_lookup (priv->hints, "desktop-entry"); @@ -725,6 +817,7 @@ notify_notification_show (NotifyNotification *notification, if (desktop_entry == NULL) { 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_new_string (application_id)); } From de3affa100c6a118bde26f407ad674beba4569f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 22 Apr 2022 00:49:38 +0200 Subject: [PATCH 5/8] notification: Avoid creating a new hint variant when nothing has changed --- libnotify/notification.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index ba3e6e8..5589ff1 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -1021,7 +1021,7 @@ get_parsed_variant (NotifyNotification *notification, const char *str = g_variant_get_string (variant, NULL); gchar *parsed = str_parser (notification, str); - if (parsed != NULL) { + if (parsed != NULL && g_strcmp0 (str, parsed) != 0) { g_variant_unref (variant); variant = g_variant_new_take_string (parsed); } From 12a7f008a8d3a9688c1e6e84d0e75aec4e9235e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 22 Apr 2022 00:52:41 +0200 Subject: [PATCH 6/8] notification: Improve debug logs when rewriting paths --- libnotify/notification.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index 5589ff1..b8e38ef 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -597,10 +597,6 @@ try_prepend_snap_desktop (NotifyNotification *notification, ret = g_strdup_printf ("%s_%s", priv->snap_name, desktop); } - if (ret) { - g_debug ("Using snap ID: %s", ret); - } - return ret; } @@ -1015,6 +1011,7 @@ typedef gchar * (*StringParserFunc) (NotifyNotification *, const gchar *); static GVariant * get_parsed_variant (NotifyNotification *notification, + const char *key, GVariant *variant, StringParserFunc str_parser) { @@ -1022,6 +1019,8 @@ get_parsed_variant (NotifyNotification *notification, 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); variant = g_variant_new_take_string (parsed); } @@ -1039,12 +1038,14 @@ maybe_parse_snap_hint_value (NotifyNotification *notification, if (g_strcmp0 (key, "desktop-entry") == 0) { value = get_parsed_variant (notification, + key, value, try_prepend_snap_desktop); } else if (g_strcmp0 (key, "image-path") == 0 || g_strcmp0 (key, "image_path") == 0 || g_strcmp0 (key, "sound-file") == 0) { value = get_parsed_variant (notification, + key, value, try_prepend_snap); } From 0be9962a4608f64a5c3885ce943beb6b5444a692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 22 Apr 2022 01:01:56 +0200 Subject: [PATCH 7/8] notification: Do not duplicate calls on parse functions --- libnotify/notification.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libnotify/notification.c b/libnotify/notification.c index b8e38ef..fe7476b 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -1033,24 +1033,24 @@ maybe_parse_snap_hint_value (NotifyNotification *notification, const gchar *key, GVariant *value) { + StringParserFunc parse_func = NULL; + if (!notification->priv->snap_path) return value; if (g_strcmp0 (key, "desktop-entry") == 0) { - value = get_parsed_variant (notification, - key, - value, - try_prepend_snap_desktop); + parse_func = try_prepend_snap_desktop; } else if (g_strcmp0 (key, "image-path") == 0 || g_strcmp0 (key, "image_path") == 0 || g_strcmp0 (key, "sound-file") == 0) { - value = get_parsed_variant (notification, - key, - 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); } /** From 02481a84a28b928a4a431eab9a434fdfeb3430eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 22 Apr 2022 02:15:18 +0200 Subject: [PATCH 8/8] notification: Keep converted URIs as such when we prepend a path --- libnotify/notification.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libnotify/notification.c b/libnotify/notification.c index fe7476b..97f5f99 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -536,14 +536,18 @@ try_prepend_path (const char *base_path, { gchar *path_filename; gchar *path_ret; + gboolean was_uri; if (!path || *path == '\0') return NULL; + was_uri = TRUE; path_ret = NULL; path_filename = g_filename_from_uri (base_path, NULL, NULL); if (path_filename == NULL) { + was_uri = FALSE; + if (base_path && base_path[0] == G_DIR_SEPARATOR) { path_filename = g_strdup (base_path); } else { @@ -571,6 +575,13 @@ try_prepend_path (const char *base_path, g_debug ("Nothing found at %s", path_ret); g_free (path_ret); 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);