[gnome-software] Do not allow plugins to adopt wildcard applications



commit 43794ef7f60bbfe33fbf2db207b38d965b773aba
Author: Richard Hughes <richard hughsie com>
Date:   Mon Sep 19 10:36:44 2016 +0100

    Do not allow plugins to adopt wildcard applications
    
    The idea here was that plugins create and add a new application from refine()
    rather than both trying to fight over the wildcard application which will be
    harmlessly filtered out by the plugin loader.
    
    To make this less magic and to remove some boilerplate, also add a new vfunc
    which plugins can use for this special action.

 src/gs-app.c                              |   13 ++-
 src/gs-plugin-loader.c                    |  162 ++++++++++++++++++++---------
 src/gs-plugin-vfuncs.h                    |   24 +++++
 src/plugins/gs-plugin-appstream.c         |   41 ++------
 src/plugins/gs-plugin-packagekit-refine.c |   10 ++
 5 files changed, 169 insertions(+), 81 deletions(-)
---
diff --git a/src/gs-app.c b/src/gs-app.c
index 654e2cc..048ee64 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -2218,8 +2218,8 @@ gs_app_get_management_plugin (GsApp *app)
  * operations on the #GsApp.
  * Typical values include "packagekit" and "flatpak"
  *
- * It is an error to attempt to change the management plugin once
- * it has been previously set.
+ * It is an error to attempt to change the management plugin once it has been
+ * previously set or to try to use this function on a wildcard application.
  *
  * Since: 3.22
  **/
@@ -2228,6 +2228,15 @@ gs_app_set_management_plugin (GsApp *app, const gchar *management_plugin)
 {
        g_return_if_fail (GS_IS_APP (app));
 
+       /* plugins cannot adopt wildcard packages */
+       if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX)) {
+               g_warning ("plugins should not set the management plugin on "
+                          "%s to %s -- create a new GsApp in refine()!",
+                          gs_app_get_unique_id (app),
+                          management_plugin);
+               return;
+       }
+
        /* same */
        if (g_strcmp0 (app->management_plugin, management_plugin) == 0)
                return;
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 854198e..76c466c 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -126,6 +126,12 @@ typedef gboolean    (*GsPluginRefineAppFunc)       (GsPlugin       *plugin,
                                                         GsPluginRefineFlags flags,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+typedef gboolean        (*GsPluginRefineWildcardFunc)  (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        GsAppList      *list,
+                                                        GsPluginRefineFlags flags,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 typedef gboolean        (*GsPluginRefreshFunc  )       (GsPlugin       *plugin,
                                                         guint           cache_age,
                                                         GsPluginRefreshFlags flags,
@@ -371,6 +377,94 @@ gs_plugin_loader_review_score_sort_cb (gconstpointer a, gconstpointer b)
        return 0;
 }
 
+static void
+gs_plugin_loader_run_refine_wildcard (GsPluginLoader *plugin_loader,
+                                     GsPlugin *plugin,
+                                     GsApp *app,
+                                     GsAppList *list,
+                                     GsPluginRefineFlags flags,
+                                     GCancellable *cancellable)
+{
+       GsPluginRefineWildcardFunc plugin_func = NULL;
+       const gchar *function_name = "gs_plugin_refine_wildcard";
+       gboolean ret;
+       g_autoptr(GError) error_local = NULL;
+
+       /* load the possible symbols */
+       g_module_symbol (gs_plugin_get_module (plugin),
+                        function_name,
+                        (gpointer *) &plugin_func);
+       if (plugin_func == NULL)
+               return;
+
+       gs_plugin_loader_action_start (plugin_loader, plugin, FALSE);
+       ret = plugin_func (plugin, app, list, flags,
+                          cancellable, &error_local);
+       gs_plugin_loader_action_stop (plugin_loader, plugin);
+       if (!ret) {
+               /* badly behaved plugin */
+               if (error_local == NULL) {
+                       g_critical ("%s did not set error for %s",
+                                   gs_plugin_get_name (plugin),
+                                   function_name);
+                       return;
+               }
+               g_warning ("failed to call %s on %s: %s",
+                          function_name,
+                          gs_plugin_get_name (plugin),
+                          error_local->message);
+               gs_plugin_loader_create_event_from_error (plugin_loader,
+                                                         GS_PLUGIN_ACTION_REFINE,
+                                                         plugin,
+                                                         NULL, /* app */
+                                                         error_local);
+       }
+}
+
+static void
+gs_plugin_loader_run_refine_app (GsPluginLoader *plugin_loader,
+                               GsPlugin *plugin,
+                               GsApp *app,
+                               GsAppList *list,
+                               GsPluginRefineFlags flags,
+                               GCancellable *cancellable)
+{
+       GsPluginRefineAppFunc plugin_func = NULL;
+       const gchar *function_name = "gs_plugin_refine_app";
+       gboolean ret;
+       g_autoptr(GError) error_local = NULL;
+
+       g_module_symbol (gs_plugin_get_module (plugin),
+                        function_name,
+                        (gpointer *) &plugin_func);
+       if (plugin_func == NULL)
+               return;
+
+       gs_plugin_loader_action_start (plugin_loader, plugin, FALSE);
+       ret = plugin_func (plugin, app, flags,
+                                    cancellable, &error_local);
+       gs_plugin_loader_action_stop (plugin_loader, plugin);
+       if (!ret) {
+               /* badly behaved plugin */
+               if (error_local == NULL) {
+                       g_critical ("%s did not set error for %s",
+                                   gs_plugin_get_name (plugin),
+                                   function_name);
+                       return;
+               }
+               g_warning ("failed to call %s on %s: %s",
+                          function_name,
+                          gs_plugin_get_name (plugin),
+                          error_local->message);
+               gs_plugin_loader_create_event_from_error (plugin_loader,
+                                                         GS_PLUGIN_ACTION_REFINE,
+                                                         plugin,
+                                                         app,
+                                                         error_local);
+       }
+
+}
+
 static gboolean
 gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
                                      const gchar *function_name_parent,
@@ -386,7 +480,6 @@ gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
        GPtrArray *related;
        GsApp *app;
        GsPlugin *plugin;
-       const gchar *function_name_app = "gs_plugin_refine_app";
        const gchar *function_name = "gs_plugin_refine";
        gboolean ret = TRUE;
 
@@ -401,7 +494,6 @@ gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
 
        /* run each plugin */
        for (i = 0; i < priv->plugins->len; i++) {
-               GsPluginRefineAppFunc plugin_app_func = NULL;
                GsPluginRefineFunc plugin_func = NULL;
                g_autoptr(AsProfileTask) ptask = NULL;
 
@@ -413,11 +505,6 @@ gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
                g_module_symbol (gs_plugin_get_module (plugin),
                                 function_name,
                                 (gpointer *) &plugin_func);
-               g_module_symbol (gs_plugin_get_module (plugin),
-                                function_name_app,
-                                (gpointer *) &plugin_app_func);
-               if (plugin_func == NULL && plugin_app_func == NULL)
-                       continue;
 
                /* profile the plugin runtime */
                if (function_name_parent == NULL) {
@@ -463,36 +550,23 @@ gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
                                continue;
                        }
                }
-               if (plugin_app_func != NULL) {
-                       for (j = 0; j < gs_app_list_length (list); j++) {
-                               g_autoptr(GError) error_local = NULL;
-                               gboolean ret_local;
-
-                               app = gs_app_list_index (list, j);
-                               gs_plugin_loader_action_start (plugin_loader, plugin, FALSE);
-                               ret_local = plugin_app_func (plugin, app, flags,
-                                                            cancellable, &error_local);
-                               gs_plugin_loader_action_stop (plugin_loader, plugin);
-                               if (!ret_local) {
-                                       /* badly behaved plugin */
-                                       if (error_local == NULL) {
-                                               g_critical ("%s did not set error for %s",
-                                                           gs_plugin_get_name (plugin),
-                                                           function_name_app);
-                                               continue;
-                                       }
-                                       g_warning ("failed to call %s on %s: %s",
-                                                  function_name_app,
-                                                  gs_plugin_get_name (plugin),
-                                                  error_local->message);
-                                       gs_plugin_loader_create_event_from_error (plugin_loader,
-                                                                                 GS_PLUGIN_ACTION_REFINE,
-                                                                                 plugin,
-                                                                                 app,
-                                                                                 error_local);
-                                       continue;
-                               }
+               for (j = 0; j < gs_app_list_length (list); j++) {
+                       app = gs_app_list_index (list, j);
+                       if (!gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX)) {
+                               gs_plugin_loader_run_refine_app (plugin_loader,
+                                                                plugin,
+                                                                app,
+                                                                list,
+                                                                flags,
+                                                                cancellable);
+                               continue;
                        }
+                       gs_plugin_loader_run_refine_wildcard (plugin_loader,
+                                                             plugin,
+                                                             app,
+                                                             list,
+                                                             flags,
+                                                             cancellable);
                }
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
@@ -628,19 +702,13 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
        if (!ret)
                goto out;
 
-       /* second pass for any unadopted apps in the wildcard state */
+       /* second pass for any unadopted apps */
        for (i = 0; i < gs_app_list_length (list); i++) {
                GsApp *app = gs_app_list_index (list, i);
-
-               /* not needing to resolve */
-               if (!gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
-                       continue;
-               if (gs_app_get_management_plugin (app) != NULL)
-                       continue;
-
-               /* this doesn't make sense outside the plugin loader */
-               gs_app_remove_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX);
-               has_match_any_prefix = TRUE;
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX)) {
+                       has_match_any_prefix = TRUE;
+                       break;
+               }
        }
        if (has_match_any_prefix) {
                g_debug ("2nd resolve pass for unadopted wildcards");
diff --git a/src/gs-plugin-vfuncs.h b/src/gs-plugin-vfuncs.h
index 2205320..b75496c 100644
--- a/src/gs-plugin-vfuncs.h
+++ b/src/gs-plugin-vfuncs.h
@@ -429,6 +429,30 @@ gboolean    gs_plugin_refine_app                   (GsPlugin       *plugin,
                                                         GError         **error);
 
 /**
+ * gs_plugin_refine_wildcard:
+ * @plugin: a #GsPlugin
+ * @app: a #GsApp
+ * @list: a #GsAppList
+ * @flags: a #GsPluginRefineFlags, e.g. %GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Adds applications that match the wildcard specified in @app.
+ *
+ * The general idea is that plugins create and add *new* applications rather
+ * than all trying to fight over the wildcard application.
+ * This allows the plugin loader to filter using the #GsApp priority value.
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean        gs_plugin_refine_wildcard              (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        GsAppList      *list,
+                                                        GsPluginRefineFlags flags,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+
+/**
  * gs_plugin_launch:
  * @plugin: a #GsPlugin
  * @app: a #GsApp
diff --git a/src/plugins/gs-plugin-appstream.c b/src/plugins/gs-plugin-appstream.c
index 1e9dbab..3a2412e 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -442,10 +442,6 @@ gs_plugin_refine_app (GsPlugin *plugin,
 {
        gboolean found = FALSE;
 
-       /* handled already */
-       if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
-               return TRUE;
-
        /* find by ID then package name */
        if (!gs_plugin_refine_from_id (plugin, app, &found, error))
                return FALSE;
@@ -458,17 +454,20 @@ gs_plugin_refine_app (GsPlugin *plugin,
        return TRUE;
 }
 
-static gboolean
-gs_plugin_appstream_add_wildcards (GsPlugin *plugin,
-                                  GsAppList *list,
-                                  GsApp *app,
-                                  GError **error)
+gboolean
+gs_plugin_refine_wildcard (GsPlugin *plugin,
+                          GsApp *app,
+                          GsAppList *list,
+                          GsPluginRefineFlags flags,
+                          GCancellable *cancellable,
+                          GError **error)
 {
        GsPluginData *priv = gs_plugin_get_data (plugin);
        const gchar *id;
        guint i;
        g_autoptr(GPtrArray) items = NULL;
 
+       /* not enough info to find */
        id = gs_app_get_id (app);
        if (id == NULL)
                return TRUE;
@@ -497,30 +496,8 @@ gs_plugin_appstream_add_wildcards (GsPlugin *plugin,
                        return FALSE;
                gs_app_list_add (list, new);
        }
-       return TRUE;
-}
-
-/* wildcard results get added to the list, not replaced */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GsAppList *list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       guint i;
-
-       for (i = 0; i < gs_app_list_length (list); i++) {
-               GsApp *app = gs_app_list_index (list, i);
-               if (!gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
-                       continue;
-               if (!gs_plugin_appstream_add_wildcards (plugin,
-                                                       list,
-                                                       app,
-                                                       error))
-                       return FALSE;
-       }
 
+       /* sucess */
        return TRUE;
 }
 
diff --git a/src/plugins/gs-plugin-packagekit-refine.c b/src/plugins/gs-plugin-packagekit-refine.c
index 50306b7..5038720 100644
--- a/src/plugins/gs-plugin-packagekit-refine.c
+++ b/src/plugins/gs-plugin-packagekit-refine.c
@@ -573,6 +573,8 @@ gs_plugin_packagekit_refine_update_urgency (GsPlugin *plugin,
        for (i = 0; i < gs_app_list_length (list); i++) {
                g_autoptr (PkPackage) pkg = NULL;
                app = gs_app_list_index (list, i);
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
+                       continue;
                package_id = gs_app_get_source_id_default (app);
                if (package_id == NULL)
                        continue;
@@ -642,6 +644,8 @@ gs_plugin_refine_require_details (GsPlugin *plugin,
        list_tmp = gs_app_list_new ();
        for (i = 0; i < gs_app_list_length (list); i++) {
                app = gs_app_list_index (list, i);
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
+                       continue;
                if (gs_app_get_kind (app) == AS_APP_KIND_WEB_APP)
                        continue;
                if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
@@ -814,6 +818,8 @@ gs_plugin_refine (GsPlugin *plugin,
        resolve_all = gs_app_list_new ();
        for (i = 0; i < gs_app_list_length (list); i++) {
                app = gs_app_list_index (list, i);
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
+                       continue;
                if (gs_app_get_kind (app) == AS_APP_KIND_WEB_APP)
                        continue;
                tmp = gs_app_get_management_plugin (app);
@@ -850,6 +856,8 @@ gs_plugin_refine (GsPlugin *plugin,
                if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION) == 0)
                        continue;
                app = gs_app_list_index (list, i);
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
+                       continue;
                if (gs_app_get_source_id_default (app) != NULL)
                        continue;
                tmp = gs_app_get_management_plugin (app);
@@ -890,6 +898,8 @@ gs_plugin_refine (GsPlugin *plugin,
        updatedetails_all = gs_app_list_new ();
        for (i = 0; i < gs_app_list_length (list); i++) {
                app = gs_app_list_index (list, i);
+               if (gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX))
+                       continue;
                if (gs_app_get_state (app) != AS_APP_STATE_UPDATABLE)
                        continue;
                tmp = gs_app_get_management_plugin (app);


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