[gnome-software/mwleeds/pwa-plugin: 116/118] fixup! Revive webapp support




commit b868f6f14c1d66e363748c78f8e4891285e5f5fd
Author: Phaedrus Leeds <mwleeds protonmail com>
Date:   Thu Feb 24 17:31:11 2022 -0800

    fixup! Revive webapp support

 plugins/epiphany/gs-plugin-epiphany.c | 111 +++++++++++++++++++++++++++++++---
 1 file changed, 102 insertions(+), 9 deletions(-)
---
diff --git a/plugins/epiphany/gs-plugin-epiphany.c b/plugins/epiphany/gs-plugin-epiphany.c
index 73b1f3711..fac152a21 100644
--- a/plugins/epiphany/gs-plugin-epiphany.c
+++ b/plugins/epiphany/gs-plugin-epiphany.c
@@ -36,6 +36,9 @@ struct _GsPluginEpiphany
 
        GsEphyWebAppProvider *epiphany_proxy;  /* (owned) */
        GDBusProxy *launcher_portal_proxy;  /* (owned) */
+       GFileMonitor *monitor; /* (owned) */
+       guint changed_id;
+       GMutex installed_apps_mutex;
 };
 
 G_DEFINE_TYPE (GsPluginEpiphany, gs_plugin_epiphany, GS_TYPE_PLUGIN)
@@ -79,6 +82,22 @@ gs_epiphany_error_convert (GError **perror)
                return;
 }
 
+/* Run in the main thread. */
+static void
+gs_plugin_epiphany_changed_cb (GFileMonitor      *monitor,
+                               GFile             *file,
+                               GFile             *other_file,
+                               GFileMonitorEvent  event_type,
+                               gpointer           user_data)
+{
+       GsPluginEpiphany *self = GS_PLUGIN_EPIPHANY (user_data);
+
+       /* With the current API this is the only way to reload the list of
+        * installed apps.
+        */
+       gs_plugin_reload (GS_PLUGIN (self));
+}
+
 static void setup_thread_cb (GTask        *task,
                              gpointer      source_object,
                              gpointer      task_data,
@@ -92,16 +111,37 @@ gs_plugin_epiphany_setup_async (GsPlugin            *plugin,
 {
        GsPluginEpiphany *self = GS_PLUGIN_EPIPHANY (plugin);
        g_autoptr(GTask) task = NULL;
+       g_autoptr(GError) local_error = NULL;
+       g_autofree char *portal_apps_path = NULL;
+       g_autoptr(GFile) portal_apps_file = NULL;
 
        task = g_task_new (plugin, cancellable, callback, user_data);
        g_task_set_source_tag (task, gs_plugin_epiphany_setup_async);
 
        g_debug ("%s", G_STRFUNC);
 
+       /* Watch for changes to the set of installed apps in the main thread.
+        * This will also trigger when other apps' dynamic launchers are
+        * installed or removed but that is expected to be infrequent.
+        */
+       portal_apps_path = g_build_filename (g_get_user_data_dir (), "xdg-desktop-portal", "applications", 
NULL);
+       g_mkdir_with_parents (portal_apps_path, 0700);
+       portal_apps_file = g_file_new_for_path (portal_apps_path);
+       self->monitor = g_file_monitor_directory (portal_apps_file, G_FILE_MONITOR_WATCH_MOVES,
+                                                 cancellable, &local_error);
+       if (self->monitor == NULL) {
+               gs_epiphany_error_convert (&local_error);
+               g_task_return_error (task, g_steal_pointer (&local_error));
+               return;
+       }
+
+       self->changed_id = g_signal_connect (self->monitor, "changed",
+                                            G_CALLBACK (gs_plugin_epiphany_changed_cb), self);
+
        /* Start up a worker thread to process all the plugin’s function calls. */
        self->worker = gs_worker_thread_new ("gs-plugin-epiphany");
 
-       /* Queue a job to find installed apps */
+       /* Queue a job to set up D-Bus proxies */
        gs_worker_thread_queue (self->worker, G_PRIORITY_DEFAULT,
                                setup_thread_cb, g_steal_pointer (&task));
 }
@@ -170,10 +210,11 @@ setup_thread_cb (GTask        *task,
        } else {
                version_child = g_variant_get_child_value (version, 0);
                version_grandchild = g_variant_get_child_value (version_child, 0);
-               g_debug ("Found version %" G_GUINT32_FORMAT " of the dynamic launcher portal", 
g_variant_get_uint32 (version_grandchild));
+               g_debug ("Found version %" G_GUINT32_FORMAT " of the dynamic launcher portal",
+                        g_variant_get_uint32 (version_grandchild));
        }
 
-       /* And finally, make a proxy object for the dynamic launcher portal */
+       /* And make a proxy object for the dynamic launcher portal */
        self->launcher_portal_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 
G_DBUS_PROXY_FLAGS_NONE, NULL,
                                                                     "org.freedesktop.portal.Desktop",
                                                                     "/org/freedesktop/portal/desktop",
@@ -263,13 +304,29 @@ gs_plugin_epiphany_dispose (GObject *object)
 {
        GsPluginEpiphany *self = GS_PLUGIN_EPIPHANY (object);
 
+       if (self->changed_id > 0) {
+               g_signal_handler_disconnect (self->monitor, self->changed_id);
+               self->changed_id = 0;
+       }
+
        g_clear_object (&self->epiphany_proxy);
        g_clear_object (&self->launcher_portal_proxy);
+       g_clear_object (&self->monitor);
        g_clear_object (&self->worker);
 
        G_OBJECT_CLASS (gs_plugin_epiphany_parent_class)->dispose (object);
 }
 
+static void
+gs_plugin_epiphany_finalize (GObject *object)
+{
+       GsPluginEpiphany *self = GS_PLUGIN_EPIPHANY (object);
+
+       g_mutex_clear (&self->installed_apps_mutex);
+
+       G_OBJECT_CLASS (gs_plugin_epiphany_parent_class)->finalize (object);
+}
+
 void
 gs_plugin_adopt_app (GsPlugin *plugin,
                     GsApp    *app)
@@ -322,11 +379,11 @@ gs_epiphany_create_app (GsPluginEpiphany *self,
        gs_app_set_kind (tmp_app, AS_COMPONENT_KIND_WEB_APP);
        gs_app_set_scope (tmp_app, AS_COMPONENT_SCOPE_USER);
 
-       app_cached = gs_plugin_cache_lookup (GS_PLUGIN (self), gs_app_get_unique_id (tmp_app));
+       app_cached = gs_plugin_cache_lookup (GS_PLUGIN (self), id);
        if (app_cached != NULL)
                return g_steal_pointer (&app_cached);
 
-       gs_plugin_cache_add (GS_PLUGIN (self), NULL, tmp_app);
+       gs_plugin_cache_add (GS_PLUGIN (self), id, tmp_app);
        return g_steal_pointer (&tmp_app);
 }
 
@@ -339,9 +396,11 @@ list_installed_apps_thread_cb (GTask        *task,
 {
        GsPluginEpiphany *self = GS_PLUGIN_EPIPHANY (source_object);
        g_autoptr(GsAppList) list = gs_app_list_new ();
+       g_autoptr(GsAppList) installed_cache = gs_app_list_new ();
        g_autoptr(GError) local_error = NULL;
        g_autoptr(GVariant) webapps_v = NULL;
        g_auto(GStrv) webapps = NULL;
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&self->installed_apps_mutex);
        guint n_webapps;
 
        assert_in_worker (self);
@@ -368,6 +427,7 @@ list_installed_apps_thread_cb (GTask        *task,
                int argc;
                g_auto(GStrv) argv = NULL;
                guint64 install_date = 0;
+               goffset desktop_size = 0, icon_size = 0;
                g_autoptr(GsApp) app = NULL;
                g_autoptr(GDesktopAppInfo) desktop_info = NULL;
                g_autoptr(GFileInfo) file_info = NULL;
@@ -403,13 +463,19 @@ list_installed_apps_thread_cb (GTask        *task,
 
                /* FIXME: this should use TIME_CREATED but it does not seem to
                 * be working (copied from Epiphany) */
-               file_info = g_file_query_info (desktop_file, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL);
-               install_date = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+               file_info = g_file_query_info (desktop_file,
+                                              G_FILE_ATTRIBUTE_TIME_MODIFIED "," 
G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                              0, NULL, NULL);
+               if (file_info) {
+                       install_date = g_file_info_get_attribute_uint64 (file_info, 
G_FILE_ATTRIBUTE_TIME_MODIFIED);
+                       desktop_size = g_file_info_get_size (file_info);
+               }
 
                app = gs_epiphany_create_app (self, desktop_file_id);
                gs_app_set_state (app, GS_APP_STATE_INSTALLED);
                gs_app_set_name (app, GS_APP_QUALITY_NORMAL, name);
                gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, url);
+               gs_app_set_permissions (app, GS_APP_PERMISSIONS_NETWORK);
 
                /* Use the domain name as a fallback summary.
                 * FIXME: Fetch the summary from the site's webapp manifest.
@@ -421,14 +487,22 @@ list_installed_apps_thread_cb (GTask        *task,
                        g_autoptr(GFile) icon_file = g_file_new_for_path (icon_path);
                        g_autoptr(GIcon) icon = g_file_icon_new (icon_file);
                        g_autofree char *icon_dir = g_path_get_dirname (icon_path);
+                       g_autofree char *icon_dir_basename = g_path_get_basename (icon_dir);
                        const char *x;
                        int size = 0;
 
+                       g_clear_object (&file_info);
+                       file_info = g_file_query_info (icon_file,
+                                                      G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                                      0, NULL, NULL);
+                       if (file_info)
+                               icon_size = g_file_info_get_size (file_info);
+
                        /* dir should be either scalable or e.g. 512x512 */
-                       if (g_strcmp0 (icon_dir, "scalable") == 0) {
+                       if (g_strcmp0 (icon_dir_basename, "scalable") == 0) {
                                /* Ensure scalable icons are preferred */
                                size = 4096;
-                       } else if ((x = strchr (icon_dir, 'x')) != NULL) {
+                       } else if ((x = strchr (icon_dir_basename, 'x')) != NULL) {
                                size = atoi (x + 1);
                        }
                        if (size > 0 && size <= 4096) {
@@ -443,9 +517,27 @@ list_installed_apps_thread_cb (GTask        *task,
                if (install_date) {
                        gs_app_set_install_date (app, install_date);
                }
+               if (desktop_size > 0 || icon_size > 0) {
+                       gs_app_set_size_installed (app, desktop_size + icon_size);
+               }
                gs_app_list_add (list, app);
        }
 
+       /* Update the state on any apps that were uninstalled outside
+        * gnome-software
+        */
+       gs_plugin_cache_lookup_by_state (GS_PLUGIN (self), installed_cache, GS_APP_STATE_INSTALLED);
+       for (guint i = 0; i < gs_app_list_length (installed_cache); i++) {
+               GsApp *app = gs_app_list_index (installed_cache, i);
+               const char *app_id = gs_app_get_id (app);
+               g_autoptr(GsApp) app_cached = NULL;
+
+               if (g_strv_contains ((const char * const *)webapps, app_id))
+                       continue;
+
+               gs_app_set_state (app, GS_APP_STATE_UNKNOWN);
+               gs_plugin_cache_remove (GS_PLUGIN (self), app_id);
+       }
 
        g_task_return_pointer (task, g_steal_pointer (&list), g_object_unref);
 }
@@ -616,6 +708,7 @@ gs_plugin_epiphany_class_init (GsPluginEpiphanyClass *klass)
        GsPluginClass *plugin_class = GS_PLUGIN_CLASS (klass);
 
        object_class->dispose = gs_plugin_epiphany_dispose;
+       object_class->finalize = gs_plugin_epiphany_finalize;
 
        plugin_class->setup_async = gs_plugin_epiphany_setup_async;
        plugin_class->setup_finish = gs_plugin_epiphany_setup_finish;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]