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



commit 2251b08b8d33f12d3743271cab19bc960a1915a3
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.
    
    (cherry picked from commit 43794ef7f60bbfe33fbf2db207b38d965b773aba)

 src/gs-app.c                              |   13 ++-
 src/gs-plugin-loader.c                    |  147 ++++++++++++++++++++--------
 src/gs-plugin-vfuncs.h                    |   24 +++++
 src/plugins/gs-plugin-appstream.c         |   41 ++------
 src/plugins/gs-plugin-packagekit-refine.c |   10 ++
 5 files changed, 159 insertions(+), 76 deletions(-)
---
diff --git a/src/gs-app.c b/src/gs-app.c
index 8a9df66..218c986 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -2224,8 +2224,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
  **/
@@ -2234,6 +2234,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 253a383..a84492f 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -119,6 +119,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,
@@ -295,6 +301,84 @@ 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);
+       }
+}
+
+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);
+       }
+
+}
+
 static gboolean
 gs_plugin_loader_run_refine_internal (GsPluginLoader *plugin_loader,
                                      const gchar *function_name_parent,
@@ -310,7 +394,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;
 
@@ -325,7 +408,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;
 
@@ -337,11 +419,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) {
@@ -382,31 +459,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);
-                                       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);
        }
@@ -542,19 +611,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 525a2ae..ce6ad7e 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 dc5d199..a5fe0a8 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -440,10 +440,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;
@@ -456,17 +452,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;
@@ -495,30 +494,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 5f6aff8..04e162f 100644
--- a/src/plugins/gs-plugin-packagekit-refine.c
+++ b/src/plugins/gs-plugin-packagekit-refine.c
@@ -581,6 +581,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;
@@ -650,6 +652,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)
@@ -822,6 +826,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);
@@ -858,6 +864,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);
@@ -898,6 +906,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]