[gnome-software] Add a per-plugin GsApp cache for use by plugins



commit 048f98b87d2fa3889c7202741d100aeb6ad9d30b
Author: Richard Hughes <richard hughsie com>
Date:   Tue Apr 19 13:56:04 2016 +0100

    Add a per-plugin GsApp cache for use by plugins
    
    This is designed to be used when the read lock is held, and ensures that
    plugins can only access GsApps that have been manually added.
    
    This now means that the 'key' can be chosen to what makes sense, for instance
    in the packagekit plugin the pkgname can be used as the desktop ID or AsAppKind
    is not yet known.
    
    Also add an example of how to use this API in the dummy backend. This just
    makes the 3rd-party banner on the details page flash when searching for
    'chiron' but it shows the general idea.

 src/gs-plugin-loader.c        |    3 +
 src/gs-plugin.c               |   24 ++++++++++
 src/gs-plugin.h               |    7 +++
 src/plugins/gs-plugin-dummy.c |   96 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 130 insertions(+), 0 deletions(-)
---
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 107e1bd..c2dc21e 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -3080,6 +3080,8 @@ gs_plugin_loader_open_plugin (GsPluginLoader *plugin_loader,
        plugin->profile = g_object_ref (priv->profile);
        plugin->soup_session = g_object_ref (priv->soup_session);
        plugin->scale = gs_plugin_loader_get_scale (plugin_loader);
+       plugin->cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                              g_free, (GDestroyNotify) g_object_unref);
        g_debug ("opened plugin %s: %s", filename, plugin->name);
 
        /* rwlock */
@@ -3367,6 +3369,7 @@ gs_plugin_loader_plugin_free (GsPlugin *plugin)
        g_rw_lock_clear (&plugin->rwlock);
        g_object_unref (plugin->profile);
        g_object_unref (plugin->soup_session);
+       g_hash_table_unref (plugin->cache);
        g_module_close (plugin->module);
        g_slice_free (GsPlugin, plugin);
 }
diff --git a/src/gs-plugin.c b/src/gs-plugin.c
index 3957dad..a3c8765 100644
--- a/src/gs-plugin.c
+++ b/src/gs-plugin.c
@@ -528,4 +528,28 @@ gs_plugin_download_file (GsPlugin *plugin,
        return TRUE;
 }
 
+/**
+ * gs_plugin_cache_lookup:
+ */
+GsApp *
+gs_plugin_cache_lookup (GsPlugin *plugin, const gchar *key)
+{
+       GsApp *app;
+       app = g_hash_table_lookup (plugin->cache, key);
+       if (app == NULL)
+               return NULL;
+       return g_object_ref (app);
+}
+
+/**
+ * gs_plugin_cache_add:
+ */
+void
+gs_plugin_cache_add (GsPlugin *plugin, const gchar *key, GsApp *app)
+{
+       if (g_hash_table_lookup (plugin->cache, key) == app)
+               return;
+       g_hash_table_insert (plugin->cache, g_strdup (key), g_object_ref (app));
+}
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index c0830d9..4484161 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -79,6 +79,7 @@ struct GsPlugin {
        gpointer                 updates_changed_user_data;
        AsProfile               *profile;
        SoupSession             *soup_session;
+       GHashTable              *cache;
        GRWLock                  rwlock;
 };
 
@@ -232,6 +233,12 @@ void                gs_plugin_list_filter                  (GList          **list,
 void            gs_plugin_list_filter_duplicates       (GList          **list);
 void            gs_plugin_list_randomize               (GList          **list);
 
+GsApp          *gs_plugin_cache_lookup                 (GsPlugin       *plugin,
+                                                        const gchar    *key);
+void            gs_plugin_cache_add                    (GsPlugin       *plugin,
+                                                        const gchar    *key,
+                                                        GsApp          *app);
+
 void            gs_plugin_status_update                (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GsPluginStatus  status);
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 66987dc..e1fa82a 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -28,6 +28,10 @@
  * Provides some dummy data that is useful in self test programs.
  */
 
+struct GsPluginPrivate {
+       guint                    quirk_id;
+};
+
 /**
  * gs_plugin_get_name:
  */
@@ -43,6 +47,7 @@ gs_plugin_get_name (void)
 void
 gs_plugin_initialize (GsPlugin *plugin)
 {
+       plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
        if (g_getenv ("GS_SELF_TEST_DUMMY_ENABLE") == NULL) {
                g_debug ("disabling '%s' as not in self test", plugin->name);
                gs_plugin_set_enabled (plugin, FALSE);
@@ -50,6 +55,16 @@ gs_plugin_initialize (GsPlugin *plugin)
 }
 
 /**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       if (plugin->priv->quirk_id > 0)
+               g_source_remove (plugin->priv->quirk_id);
+}
+
+/**
  * gs_plugin_adopt_app:
  */
 void
@@ -143,6 +158,87 @@ gs_plugin_dummy_delay (GsPlugin *plugin,
 }
 
 /**
+ * gs_plugin_dummy_poll_cb:
+ */
+static gboolean
+gs_plugin_dummy_poll_cb (gpointer user_data)
+{
+       g_autoptr(GsApp) app = NULL;
+       GsPlugin *plugin = GS_PLUGIN (user_data);
+
+       /* find the app in the per-plugin cache -- this assumes that we can
+        * calculate the same key as used when calling gs_plugin_cache_add() */
+       app = gs_plugin_cache_lookup (plugin, "example:chiron");
+       if (app == NULL) {
+               g_warning ("app not found in cache!");
+               return FALSE;
+       }
+
+       /* toggle this to animate the hide/show the 3rd party banner */
+       if (!gs_app_has_quirk (app, AS_APP_QUIRK_PROVENANCE)) {
+               g_debug ("about to make app distro-provided");
+               gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
+       } else {
+               g_debug ("about to make app 3rd party");
+               gs_app_clear_quirk (app, AS_APP_QUIRK_PROVENANCE);
+       }
+
+       /* continue polling */
+       return TRUE;
+}
+
+/**
+ * gs_plugin_add_search:
+ */
+gboolean
+gs_plugin_add_search (GsPlugin *plugin,
+                     gchar **values,
+                     GList **list,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(AsIcon) ic = NULL;
+
+       /* we're very specific */
+       if (g_strcmp0 (values[0], "chiron") != 0)
+               return TRUE;
+
+       /* does the app already exist? */
+       app = gs_plugin_cache_lookup (plugin, "example:chiron");
+       if (app != NULL) {
+               g_debug ("using %s fom the cache", gs_app_get_id (app));
+               gs_plugin_add_app (list, app);
+               return TRUE;
+       }
+
+       /* set up a timeout to emulate getting a GFileMonitor callback */
+       plugin->priv->quirk_id =
+               g_timeout_add_seconds (1, gs_plugin_dummy_poll_cb, plugin);
+
+       /* use a generic stock icon */
+       ic = as_icon_new ();
+       as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
+       as_icon_set_name (ic, "drive-harddisk");
+
+       /* add a live updatable normal application */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Chiron");
+       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A teaching application");
+       gs_app_set_icon (app, ic);
+       gs_app_set_size (app, 42 * 1024 * 1024);
+       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       gs_app_set_management_plugin (app, plugin->name);
+       gs_plugin_add_app (list, app);
+
+       /* add to cache so it can be found by the flashing callback */
+       gs_plugin_cache_add (plugin, "example:chiron", app);
+
+       return TRUE;
+}
+
+/**
  * gs_plugin_add_updates:
  */
 gboolean


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