[gnome-software] Add a per-plugin GsApp cache for use by plugins
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add a per-plugin GsApp cache for use by plugins
- Date: Tue, 19 Apr 2016 14:36:26 +0000 (UTC)
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]