Blob Blame History Raw
From 23f1fe1736b35fe15ca17a1388251f6b52628d46 Mon Sep 17 00:00:00 2001
From: Richard Hughes <richard@hughsie.com>
Date: Tue, 8 Oct 2019 17:07:09 +0100
Subject: [PATCH] Do not show non-applications in the installed panel

Using appstream-glib to parse the desktop files into fake AppStream components
had a drawback: it worked too well. What we wanted to do was only show
applications with AppData files in the installed list, only using the desktop
metadata if the icon could not be found in the AppStream metadata.

Instead we showed all apps, even ones that would be disasterous if removed...

Lets make this simpler; we can parse the desktop file directly. We only need
the icon and the component ID, so create a fake component without using
as_app_parse_data() at all. This should speed up initial startup, as we're
doing a lot less IO than before if there are a lot of desktop files installed.

We'll also be storing less data (e.g. translations we're never going to use) in
the xmlb mmap store -- although it makes no difference to query speed it'll
make a difference for storage space.

To ensure we only query AppData files for the installed list, we can now just
query for the existance of the <name> tag -- which the fake components now will
not have.

So that the xmlb store is regenerated with the fix, also add the package
version to the libxmlb cache guid.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1759193
---
 plugins/core/gs-plugin-appstream.c | 72 ++++++++++++++++++++++++++----
 1 file changed, 63 insertions(+), 9 deletions(-)

diff --git a/plugins/core/gs-plugin-appstream.c b/plugins/core/gs-plugin-appstream.c
index 1f18693b..4f5873cf 100644
--- a/plugins/core/gs-plugin-appstream.c
+++ b/plugins/core/gs-plugin-appstream.c
@@ -206,20 +206,71 @@ gs_plugin_appstream_load_desktop_cb (XbBuilderSource *self,
 				     GCancellable *cancellable,
 				     GError **error)
 {
-	GString *xml;
-	g_autoptr(AsApp) app = as_app_new ();
+	g_autofree gchar *icon = NULL;
+	g_autofree gchar *type = NULL;
+	g_autofree gchar *xml = NULL;
+	g_autofree gchar *name = NULL;
 	g_autoptr(GBytes) bytes = NULL;
+	g_autoptr(GKeyFile) kf = g_key_file_new ();
+
+	/* get icon from desktop file */
 	bytes = xb_builder_source_ctx_get_bytes (ctx, cancellable, error);
 	if (bytes == NULL)
 		return NULL;
-	as_app_set_id (app, xb_builder_source_ctx_get_filename (ctx));
-	if (!as_app_parse_data (app, bytes, AS_APP_PARSE_FLAG_USE_FALLBACKS, error))
+	if (!g_key_file_load_from_data (kf,
+					g_bytes_get_data (bytes, NULL),
+					g_bytes_get_size (bytes),
+					G_KEY_FILE_NONE,
+					error))
 		return NULL;
-	xml = as_app_to_xml (app, error);
-	if (xml == NULL)
+	if (g_key_file_get_boolean (kf,
+				    G_KEY_FILE_DESKTOP_GROUP,
+				    G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
+				    NULL)) {
+		g_set_error_literal (error,
+				     GS_PLUGIN_ERROR,
+				     GS_PLUGIN_ERROR_NOT_SUPPORTED,
+				     "NoDisplay=true");
 		return NULL;
-	g_string_prepend (xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-	return g_memory_input_stream_new_from_data (g_string_free (xml, FALSE), -1, g_free);
+	}
+	type = g_key_file_get_string (kf,
+				      G_KEY_FILE_DESKTOP_GROUP,
+				      G_KEY_FILE_DESKTOP_KEY_TYPE,
+				      error);
+	if (type == NULL)
+		return NULL;
+	if (g_strcmp0 (type, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) != 0) {
+		g_set_error (error,
+			     GS_PLUGIN_ERROR,
+			     GS_PLUGIN_ERROR_NOT_SUPPORTED,
+			     "Type=%s", type);
+		return NULL;
+	}
+	icon = g_key_file_get_string (kf,
+				      G_KEY_FILE_DESKTOP_GROUP,
+				      G_KEY_FILE_DESKTOP_KEY_ICON,
+				      error);
+	if (icon == NULL)
+		return NULL;
+
+	name = g_key_file_get_string (kf,
+				      G_KEY_FILE_DESKTOP_GROUP,
+				      G_KEY_FILE_DESKTOP_KEY_NAME,
+				      error);
+	if (name == NULL)
+		return NULL;
+
+	/* build a super-simple fake AppData file */
+	xml = g_strdup_printf ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+			       "<component type=\"desktop\">\n"
+			       "<id>%s</id>\n"
+			       "<name>%s</name>"
+			       "<icon type=\"stock\">%s</icon>\n"
+			       "</component>\n",
+			       xb_builder_source_ctx_get_filename (ctx),
+			       name,
+			       icon);
+	return g_memory_input_stream_new_from_data (g_steal_pointer (&xml), -1, g_free);
 }
 
 static gboolean
@@ -517,6 +568,9 @@ gs_plugin_appstream_check_silo (GsPlugin *plugin,
 		}
 	}
 
+	/* regenerate with each minor release */
+	xb_builder_append_guid (builder, PACKAGE_VERSION);
+
 	/* create per-user cache */
 	blobfn = gs_utils_get_cache_filename ("appstream", "components.xmlb",
 					      GS_UTILS_CACHE_FLAG_WRITEABLE,
@@ -925,7 +979,7 @@ gs_plugin_add_installed (GsPlugin *plugin,
 	locker = g_rw_lock_reader_locker_new (&priv->silo_lock);
 
 	/* get all installed appdata files (notice no 'components/' prefix...) */
-	components = xb_silo_query (priv->silo, "component", 0, NULL);
+	components = xb_silo_query (priv->silo, "component/description/..", 0, NULL);
 	if (components == NULL)
 		return TRUE;
 	for (guint i = 0; i < components->len; i++) {
-- 
2.23.0