diff --git a/lib/gnome-software.h b/lib/gnome-software.h index b57e2572e84e9f1798248d923713392f7ceceba6..e131b800d6ff4ca53625549611b4b7b87d1e7164 100644 --- a/lib/gnome-software.h +++ b/lib/gnome-software.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/gs-app-private.h b/lib/gs-app-private.h index 1163bf3a9c4438f276cdd9058d660236ee580473..ce86a41480e0e0b34a1b54de8cf61b5a7f94aa41 100644 --- a/lib/gs-app-private.h +++ b/lib/gs-app-private.h @@ -26,5 +26,7 @@ void gs_app_set_pending_action (GsApp *app, GsPluginAction action); gint gs_app_compare_priority (GsApp *app1, GsApp *app2); +void gs_app_set_icons_state (GsApp *app, + GsAppIconsState icons_state); G_END_DECLS diff --git a/lib/gs-app.c b/lib/gs-app.c index 3e239dfc246367a3c1dc68d960ab572d9ede8cad..f155d3664592f3d23be5c28c06db00b8e758fe57 100644 --- a/lib/gs-app.c +++ b/lib/gs-app.c @@ -140,6 +140,7 @@ typedef struct GPtrArray *version_history; /* (element-type AsRelease) (nullable) (owned) */ GPtrArray *relations; /* (nullable) (element-type AsRelation) (owned) */ gboolean has_translations; + GsAppIconsState icons_state; } GsAppPrivate; typedef enum { @@ -180,9 +181,10 @@ typedef enum { PROP_RELATIONS, PROP_ORIGIN_UI, PROP_HAS_TRANSLATIONS, + PROP_ICONS_STATE, } GsAppProperty; -static GParamSpec *obj_props[PROP_HAS_TRANSLATIONS + 1] = { NULL, }; +static GParamSpec *obj_props[PROP_ICONS_STATE + 1] = { NULL, }; G_DEFINE_TYPE_WITH_PRIVATE (GsApp, gs_app, G_TYPE_OBJECT) @@ -5347,6 +5349,9 @@ gs_app_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec * case PROP_HAS_TRANSLATIONS: g_value_set_boolean (value, gs_app_get_has_translations (app)); break; + case PROP_ICONS_STATE: + g_value_set_enum (value, priv->icons_state); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -5997,6 +6002,19 @@ gs_app_class_init (GsAppClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * GsApp:icons-state: + * + * GNOME Software specific occupation of the #GsApp entity + * that does not reflect a software type defined by AppStream. + * + * Since: 43 + */ + obj_props[PROP_ICONS_STATE] = g_param_spec_enum ("icons-state", NULL, NULL, + GS_TYPE_APP_ICONS_STATE, + GS_APP_ICONS_STATE_UNKNOWN, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props); } @@ -6701,3 +6719,50 @@ gs_app_is_downloaded (GsApp *app) return TRUE; } + +/** + * gs_app_get_icons_state: + * @app: a #GsApp + * + * Returns the state of the icons of @app. + * + * Returns: a #GsAppIconsState + * + * Since: 43 + **/ +GsAppIconsState +gs_app_get_icons_state (GsApp *app) +{ + GsAppPrivate *priv = gs_app_get_instance_private (app); + + g_return_val_if_fail (GS_IS_APP (app), GS_APP_ICONS_STATE_UNKNOWN); + + return priv->icons_state; +} + +/** + * gs_app_set_icons_state: + * @app: a #GsApp + * @icons_state: a #GsAppIconsState + * + * Sets the app icons state of @app. + * + * Since: 43 + **/ +void +gs_app_set_icons_state (GsApp *app, + GsAppIconsState icons_state) +{ + GsAppPrivate *priv = gs_app_get_instance_private (app); + g_autoptr(GMutexLocker) locker = NULL; + + g_return_if_fail (GS_IS_APP (app)); + + locker = g_mutex_locker_new (&priv->mutex); + + if (priv->icons_state == icons_state) + return; + + priv->icons_state = icons_state; + gs_app_queue_notify (app, obj_props[PROP_ICONS_STATE]); +} diff --git a/lib/gs-app.h b/lib/gs-app.h index 5240b2ede5f44442b31c582631f36f5695f8ae97..51222a114bd2f7679580969409133f4b270c8f41 100644 --- a/lib/gs-app.h +++ b/lib/gs-app.h @@ -212,6 +212,21 @@ typedef enum { GS_APP_QUALITY_LAST /*< skip >*/ } GsAppQuality; +/** + * GsAppIconsState: + * @GS_APP_ICONS_STATE_UNKNOWN: The state of the icons is unknown + * @GS_APP_ICONS_STATE_DOWNLOADING: Icons are downloading + * @GS_APP_ICONS_STATE_AVAILABLE: Icons are available + * + * State of the icons of the application. + **/ +typedef enum { + GS_APP_ICONS_STATE_UNKNOWN, + GS_APP_ICONS_STATE_PENDING_DOWNLOAD, + GS_APP_ICONS_STATE_DOWNLOADING, + GS_APP_ICONS_STATE_AVAILABLE, +} GsAppIconsState; + /** * GS_APP_PROGRESS_UNKNOWN: * @@ -521,4 +536,6 @@ void gs_app_set_has_translations (GsApp *app, gboolean has_translations); gboolean gs_app_is_downloaded (GsApp *app); +GsAppIconsState gs_app_get_icons_state (GsApp *app); + G_END_DECLS diff --git a/lib/gs-debug.c b/lib/gs-debug.c index 1b2da0c2bf96b007fc996c0506b1090c7b66cabb..f76788af40fdeb15229942301311b82d33763dcf 100644 --- a/lib/gs-debug.c +++ b/lib/gs-debug.c @@ -82,7 +82,7 @@ gs_log_writer_console (GLogLevelFlags log_level, /* time header */ if (debug->use_time) { g_autoptr(GDateTime) dt = g_date_time_new_now_utc (); - tmp = g_strdup_printf ("%02i:%02i:%02i:%04i", + tmp = g_strdup_printf ("%02i:%02i:%02i:%03i", g_date_time_get_hour (dt), g_date_time_get_minute (dt), g_date_time_get_second (dt), diff --git a/lib/gs-icon-downloader.c b/lib/gs-icon-downloader.c new file mode 100644 index 0000000000000000000000000000000000000000..139799885bb127355de8ebb4b77a65a05962cb6a --- /dev/null +++ b/lib/gs-icon-downloader.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2022 Endless OS Foundation LLC + * + * Authors: + * - Georges Basile Stavracas Neto + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "gs-icon-downloader.h" + +#include "gs-app-private.h" +#include "gs-remote-icon.h" + +struct _GsIconDownloader +{ + GObject parent_instance; + + guint maximum_size; + GPtrArray *apps; /* (owned) (element-type GsApp) */ + SoupSession *soup_session; /* (owned) */ + + gboolean downloading; +}; + +G_DEFINE_FINAL_TYPE (GsIconDownloader, gs_icon_downloader, G_TYPE_OBJECT) + +typedef enum { + PROP_MAXIMUM_SIZE = 1, + PROP_SOUP_SESSION, +} GsIconDownloaderProperty; + +static GParamSpec *properties [PROP_SOUP_SESSION + 1] = { NULL, }; + +static void +download_icons_in_thread_cb (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + GsIconDownloader *self = GS_ICON_DOWNLOADER (source_object); + + g_atomic_int_set (&self->downloading, TRUE); + + for (guint i = 0; i < self->apps->len; i++) { + GsApp *app = g_ptr_array_index (self->apps, i); + GPtrArray *icons = gs_app_get_icons (app); + g_autoptr(GPtrArray) remote_icons = NULL; + + remote_icons = g_ptr_array_new_full (icons ? icons->len : 0, g_object_unref); + + for (guint j = 0; icons && j < icons->len; j++) { + GObject *icon = g_ptr_array_index (icons, j); + + if (GS_IS_REMOTE_ICON (icon)) + g_ptr_array_add (remote_icons, g_object_ref (icon)); + } + + if (remote_icons->len == 0) + continue; + + g_debug ("Downloading %u icons for app %s", remote_icons->len, gs_app_get_id (app)); + + gs_app_set_icons_state (app, GS_APP_ICONS_STATE_PENDING_DOWNLOAD); + + for (guint j = 0; j < remote_icons->len; j++) { + GObject *icon = g_ptr_array_index (remote_icons, j); + g_autoptr(GError) local_error = NULL; + + gs_app_set_icons_state (app, GS_APP_ICONS_STATE_DOWNLOADING); + + gs_remote_icon_ensure_cached (GS_REMOTE_ICON (icon), + self->soup_session, + self->maximum_size, + cancellable, + &local_error); + + if (local_error) + g_debug ("Error downloading remote icon: %s", local_error->message); + + if (g_task_return_error_if_cancelled (task)) { + g_ptr_array_set_size (self->apps, 0); + return; + } + } + + gs_app_set_icons_state (app, GS_APP_ICONS_STATE_AVAILABLE); + + if (g_task_return_error_if_cancelled (task)) { + g_ptr_array_set_size (self->apps, 0); + return; + } + } + + g_atomic_int_set (&self->downloading, FALSE); + + g_ptr_array_set_size (self->apps, 0); + g_task_return_boolean (task, TRUE); +} + +static void +gs_icon_downloader_finalize (GObject *object) +{ + GsIconDownloader *self = (GsIconDownloader *)object; + + g_clear_pointer (&self->apps, g_ptr_array_unref); + g_clear_object (&self->soup_session); + + G_OBJECT_CLASS (gs_icon_downloader_parent_class)->finalize (object); +} + +static void +gs_icon_downloader_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch ((GsIconDownloaderProperty) prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gs_icon_downloader_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GsIconDownloader *self = GS_ICON_DOWNLOADER (object); + + switch ((GsIconDownloaderProperty) prop_id) { + case PROP_MAXIMUM_SIZE: + g_assert (self->maximum_size == 0); + self->maximum_size = g_value_get_uint (value); + g_assert (self->maximum_size != 0); + break; + case PROP_SOUP_SESSION: + g_assert (self->soup_session == NULL); + self->soup_session = g_value_dup_object (value); + g_assert (self->soup_session != NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gs_icon_downloader_class_init (GsIconDownloaderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gs_icon_downloader_finalize; + object_class->get_property = gs_icon_downloader_get_property; + object_class->set_property = gs_icon_downloader_set_property; + + properties[PROP_MAXIMUM_SIZE] = + g_param_spec_uint ("maximum-size", NULL, NULL, + 0, G_MAXUINT, 0, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + properties[PROP_SOUP_SESSION] = + g_param_spec_object ("soup-session", NULL, NULL, + SOUP_TYPE_SESSION, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties); +} + +static void +gs_icon_downloader_init (GsIconDownloader *self) +{ + self->apps = g_ptr_array_new_with_free_func (g_object_unref); +} + +GsIconDownloader * +gs_icon_downloader_new (SoupSession *soup_session, + guint maximum_size) +{ + return g_object_new (GS_TYPE_ICON_DOWNLOADER, + "soup-session", soup_session, + "maximum-size", maximum_size, + NULL); +} + +void +gs_icon_downloader_queue_app (GsIconDownloader *self, + GsApp *app) +{ + g_return_if_fail (GS_IS_ICON_DOWNLOADER (self)); + g_return_if_fail (GS_IS_APP (app)); + g_return_if_fail (g_atomic_int_get (&self->downloading) == FALSE); + + g_ptr_array_add (self->apps, g_object_ref (app)); +} + +/** + * gs_icon_downloader_do_something_async: + * @self: an #GsIconDownloader + * @cancellable: (nullable): a #GCancellable + * @callback: a #GAsyncReadyCallback to execute upon completion + * @user_data: closure data for @callback + * + */ +void +gs_icon_downloader_download (GsIconDownloader *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + + g_return_if_fail (GS_IS_ICON_DOWNLOADER (self)); + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); + g_return_if_fail (g_atomic_int_get (&self->downloading) == FALSE); + + task = g_task_new (self, cancellable, callback, user_data); + g_task_set_source_tag (task, gs_icon_downloader_download); + + if (self->apps->len > 0) + g_task_run_in_thread (task, download_icons_in_thread_cb); + else + g_task_return_boolean (task, TRUE); +} + +/** + * gs_icon_downloader_download_finish: + * @self: an #GsIconDownloader + * @result: a #GAsyncResult provided to callback + * @error: a location for a #GError, or %NULL + * + * Returns: %TRUE on success, %FALSE on failure + */ +gboolean +gs_icon_downloader_download_finish (GsIconDownloader *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (GS_IS_ICON_DOWNLOADER (self), FALSE); + g_return_val_if_fail (g_task_is_valid (result, self), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + diff --git a/lib/gs-icon-downloader.h b/lib/gs-icon-downloader.h new file mode 100644 index 0000000000000000000000000000000000000000..728b64acd054249345fb53982a333f9d2ca712b8 --- /dev/null +++ b/lib/gs-icon-downloader.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2022 Endless OS Foundation LLC + * + * Authors: + * - Georges Basile Stavracas Neto + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#pragma once + +#include +#include + +#include + +#include "gs-app.h" + +G_BEGIN_DECLS + +#define GS_TYPE_ICON_DOWNLOADER (gs_icon_downloader_get_type ()) + +G_DECLARE_FINAL_TYPE (GsIconDownloader, gs_icon_downloader, GS, ICON_DOWNLOADER, GObject) + +GsIconDownloader *gs_icon_downloader_new (SoupSession *soup_session, + guint maximum_size); + +void gs_icon_downloader_queue_app (GsIconDownloader *self, + GsApp *app); + +void gs_icon_downloader_download (GsIconDownloader *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gs_icon_downloader_download_finish (GsIconDownloader *self, + GAsyncResult *result, + GError **error); + +G_END_DECLS diff --git a/lib/gs-plugin-job-list-apps.c b/lib/gs-plugin-job-list-apps.c index 811c7c08f7414ec48ab8b7bf3fa9db9004753c10..6874aede2c5d73762b424a77113d1052493adca4 100644 --- a/lib/gs-plugin-job-list-apps.c +++ b/lib/gs-plugin-job-list-apps.c @@ -36,6 +36,10 @@ #include #include +#ifdef HAVE_SYSPROF +#include +#endif + #include "gs-app.h" #include "gs-app-list-private.h" #include "gs-app-query.h" @@ -63,6 +67,10 @@ struct _GsPluginJobListApps /* Results. */ GsAppList *result_list; /* (owned) (nullable) */ + +#ifdef HAVE_SYSPROF + gint64 begin_time_nsec; +#endif }; G_DEFINE_TYPE (GsPluginJobListApps, gs_plugin_job_list_apps, GS_TYPE_PLUGIN_JOB) @@ -205,6 +213,10 @@ gs_plugin_job_list_apps_run_async (GsPluginJob *job, self->merged_list = gs_app_list_new (); plugins = gs_plugin_loader_get_plugins (plugin_loader); +#ifdef HAVE_SYSPROF + self->begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif + for (guint i = 0; i < plugins->len; i++) { GsPlugin *plugin = g_ptr_array_index (plugins, i); GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin); @@ -252,6 +264,20 @@ plugin_list_apps_cb (GObject *source_object, if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) g_clear_error (&local_error); +#ifdef HAVE_SYSPROF + { + g_autofree gchar *sysprof_name = g_strdup_printf ("%s:%s", + G_OBJECT_TYPE_NAME (self), + gs_plugin_get_name(plugin)); + + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + sysprof_name, + NULL); + } +#endif + finish_op (task, g_steal_pointer (&local_error)); } @@ -395,6 +421,14 @@ finish_task (GTask *task, /* success */ g_set_object (&self->result_list, merged_list); g_task_return_boolean (task, TRUE); + +#ifdef HAVE_SYSPROF + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + G_OBJECT_TYPE_NAME (self), + NULL); +#endif } static gboolean diff --git a/lib/gs-plugin-job-list-categories.c b/lib/gs-plugin-job-list-categories.c index f2d164433c13738f61653648613e8d368464fef7..0c3e0480c74302149c53ce6b11a1e99b05eaa4c4 100644 --- a/lib/gs-plugin-job-list-categories.c +++ b/lib/gs-plugin-job-list-categories.c @@ -34,6 +34,10 @@ #include #include +#ifdef HAVE_SYSPROF +#include +#endif + #include "gs-category.h" #include "gs-category-private.h" #include "gs-enums.h" @@ -58,6 +62,10 @@ struct _GsPluginJobListCategories /* Results. */ GPtrArray *result_list; /* (element-type GsCategory) (owned) (nullable) */ + +#ifdef HAVE_SYSPROF + gint64 begin_time_nsec; +#endif }; G_DEFINE_TYPE (GsPluginJobListCategories, gs_plugin_job_list_categories, GS_TYPE_PLUGIN_JOB) @@ -157,6 +165,10 @@ gs_plugin_job_list_categories_run_async (GsPluginJob *job, self->n_pending_ops = 1; plugins = gs_plugin_loader_get_plugins (plugin_loader); +#ifdef HAVE_SYSPROF + self->begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif + for (guint i = 0; i < plugins->len; i++) { GsPlugin *plugin = g_ptr_array_index (plugins, i); GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin); @@ -190,6 +202,21 @@ plugin_refine_categories_cb (GObject *source_object, g_autoptr(GTask) task = G_TASK (user_data); g_autoptr(GError) local_error = NULL; +#ifdef HAVE_SYSPROF + { + GsPluginJobListCategories *self = g_task_get_source_object (task); + g_autofree gchar *sysprof_name = g_strdup_printf ("%s:%s", + G_OBJECT_TYPE_NAME (self), + gs_plugin_get_name (plugin)); + + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + sysprof_name, + NULL); + } +#endif + if (!plugin_class->refine_categories_finish (plugin, result, &local_error)) { finish_op (task, g_steal_pointer (&local_error)); return; @@ -263,6 +290,14 @@ finish_op (GTask *task, /* success */ self->result_list = g_ptr_array_ref (category_list); g_task_return_boolean (task, TRUE); + +#ifdef HAVE_SYSPROF + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + G_OBJECT_TYPE_NAME (self), + NULL); +#endif } static gboolean diff --git a/lib/gs-plugin-job-refine.c b/lib/gs-plugin-job-refine.c index f9618cd476b19239566b33e825d7435989a2dfbe..f03fdec64e0c1717c8ebd027c717ef65cc959de1 100644 --- a/lib/gs-plugin-job-refine.c +++ b/lib/gs-plugin-job-refine.c @@ -82,11 +82,16 @@ #include #include +#ifdef HAVE_SYSPROF +#include +#endif + #include "gs-app.h" #include "gs-app-collation.h" #include "gs-app-private.h" #include "gs-app-list-private.h" #include "gs-enums.h" +#include "gs-plugin-private.h" #include "gs-plugin-job-private.h" #include "gs-plugin-job-refine.h" #include "gs-utils.h" @@ -101,6 +106,11 @@ struct _GsPluginJobRefine /* Output data. */ GsAppList *result_list; /* (owned) (nullable) */ + +#ifdef HAVE_SYSPROF + gint64 begin_time_nsec; + gint64 plugin_begin_time_nsec; +#endif }; G_DEFINE_TYPE (GsPluginJobRefine, gs_plugin_job_refine, GS_TYPE_PLUGIN_JOB) @@ -239,6 +249,7 @@ typedef struct { guint n_pending_ops; guint n_pending_recursions; guint next_plugin_index; + guint next_plugin_order; /* Output data. */ GError *error; /* (nullable) (owned) */ @@ -289,6 +300,7 @@ run_refine_internal_async (GsPluginJobRefine *self, gs_plugin_loader_run_adopt (plugin_loader, list); data->n_pending_ops = 0; + data->next_plugin_order = 0; /* run each plugin * @@ -310,6 +322,12 @@ run_refine_internal_async (GsPluginJobRefine *self, continue; if (plugin_class->refine_async == NULL) continue; + if (gs_plugin_get_order (plugin) > data->next_plugin_order) + return; + +#ifdef HAVE_SYSPROF + self->plugin_begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif /* FIXME: The next refine_async() call is made in * finish_refine_internal_op(). */ @@ -319,10 +337,6 @@ run_refine_internal_async (GsPluginJobRefine *self, data->n_pending_ops++; plugin_class->refine_async (plugin, list, flags, cancellable, plugin_refine_cb, g_object_ref (task)); - - /* FIXME: The next refine_async() call is made in - * finish_refine_internal_op(). */ - return; } data->n_pending_ops++; @@ -339,6 +353,21 @@ plugin_refine_cb (GObject *source_object, GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin); g_autoptr(GError) local_error = NULL; +#ifdef HAVE_SYSPROF + { + GsPluginJobRefine *self = g_task_get_source_object (task); + g_autofree gchar *sysprof_name = g_strdup_printf ("%s:%s", + G_OBJECT_TYPE_NAME (self), + gs_plugin_get_name (plugin)); + + sysprof_collector_mark (self->plugin_begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->plugin_begin_time_nsec, + "gnome-software", + sysprof_name, + NULL); + } +#endif + if (!plugin_class->refine_finish (plugin, result, &local_error)) { finish_refine_internal_op (task, g_steal_pointer (&local_error)); return; @@ -387,6 +416,13 @@ finish_refine_internal_op (GTask *task, g_assert (data->n_pending_ops > 0); data->n_pending_ops--; + if (data->n_pending_ops > 0) + return; + + /* We reach this line after all plugins of a certain order ran, and now + * we need to run the next set of plugins. */ + data->next_plugin_order++; + plugins = gs_plugin_loader_get_plugins (plugin_loader); for (guint i = data->next_plugin_index; i < plugins->len; i++) { @@ -397,6 +433,14 @@ finish_refine_internal_op (GTask *task, continue; if (plugin_class->refine_async == NULL) continue; + if (gs_plugin_get_order (plugin) < data->next_plugin_order) + continue; + if (gs_plugin_get_order (plugin) > data->next_plugin_order) + return; + +#ifdef HAVE_SYSPROF + self->plugin_begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif /* FIXME: The next refine_async() call is made in * finish_refine_internal_op(). */ @@ -406,10 +450,6 @@ finish_refine_internal_op (GTask *task, data->n_pending_ops++; plugin_class->refine_async (plugin, list, flags, cancellable, plugin_refine_cb, g_object_ref (task)); - - /* FIXME: The next refine_async() call is made in - * finish_refine_internal_op(). */ - return; } if (data->next_plugin_index == plugins->len) { @@ -645,6 +685,10 @@ gs_plugin_job_refine_run_async (GsPluginJob *job, g_object_freeze_notify (G_OBJECT (app)); } +#ifdef HAVE_SYSPROF + self->begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif + /* Start refining the apps. */ run_refine_internal_async (self, plugin_loader, result_list, self->flags, cancellable, @@ -738,10 +782,22 @@ finish_run (GTask *task, } static gboolean -gs_plugin_job_refine_run_finish (GsPluginJob *self, +gs_plugin_job_refine_run_finish (GsPluginJob *plugin_job, GAsyncResult *result, GError **error) { +#ifdef HAVE_SYSPROF + { + GsPluginJobRefine *self = GS_PLUGIN_JOB_REFINE (plugin_job); + + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + G_OBJECT_TYPE_NAME (self), + NULL); + } +#endif + return g_task_propagate_boolean (G_TASK (result), error); } diff --git a/lib/gs-plugin-job-refresh-metadata.c b/lib/gs-plugin-job-refresh-metadata.c index 8d0b95b5d5749304bc45bc955cfc8f15ae14d520..e955dc9c9ec562998b0ea4f8b4bf801939fae299 100644 --- a/lib/gs-plugin-job-refresh-metadata.c +++ b/lib/gs-plugin-job-refresh-metadata.c @@ -41,6 +41,10 @@ #include #include +#ifdef HAVE_SYSPROF +#include +#endif + #include "gs-enums.h" #include "gs-external-appstream-utils.h" #include "gs-plugin-job-private.h" @@ -76,6 +80,10 @@ struct _GsPluginJobRefreshMetadata guint n_plugins_complete; } plugins_progress; GSource *progress_source; /* (owned) (nullable) */ + +#ifdef HAVE_SYSPROF + gint64 begin_time_nsec; +#endif }; G_DEFINE_TYPE (GsPluginJobRefreshMetadata, gs_plugin_job_refresh_metadata, GS_TYPE_PLUGIN_JOB) @@ -223,6 +231,10 @@ gs_plugin_job_refresh_metadata_run_async (GsPluginJob *job, g_object_ref (task)); #endif +#ifdef HAVE_SYSPROF + self->begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME; +#endif + for (guint i = 0; i < plugins->len; i++) { GsPlugin *plugin = g_ptr_array_index (plugins, i); GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin); @@ -357,6 +369,19 @@ odrs_provider_refresh_ratings_cb (GObject *source_object, g_autoptr(GTask) task = G_TASK (user_data); g_autoptr(GError) local_error = NULL; +#ifdef HAVE_SYSPROF + { + GsPluginJobRefreshMetadata *self = g_task_get_source_object (task); + g_autofree gchar *sysprof_name = g_strdup_printf ("%s:odrs", G_OBJECT_TYPE_NAME (self)); + + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + sysprof_name, + NULL); + } +#endif + gs_odrs_provider_refresh_ratings_finish (odrs_provider, result, &local_error); finish_op (task, g_steal_pointer (&local_error)); } @@ -378,6 +403,20 @@ plugin_refresh_metadata_cb (GObject *source_object, /* Update progress reporting. */ self->plugins_progress.n_plugins_complete++; +#ifdef HAVE_SYSPROF + { + g_autofree gchar *sysprof_name = g_strdup_printf ("%s:%s", + G_OBJECT_TYPE_NAME (self), + gs_plugin_get_name (plugin)); + + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + sysprof_name, + NULL); + } +#endif + finish_op (task, g_steal_pointer (&local_error)); } @@ -423,6 +462,14 @@ finish_op (GTask *task, /* success */ g_task_return_boolean (task, TRUE); + +#ifdef HAVE_SYSPROF + sysprof_collector_mark (self->begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - self->begin_time_nsec, + "gnome-software", + G_OBJECT_TYPE_NAME (self), + NULL); +#endif } static gboolean diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c index e3f48666a84fe6c60881a2d4cce0b0ea583efd60..33c642348f9f609eb1c045b4791b6f60b7697691 100644 --- a/lib/gs-plugin-loader.c +++ b/lib/gs-plugin-loader.c @@ -78,10 +78,6 @@ struct _GsPluginLoader GsCategoryManager *category_manager; GsOdrsProvider *odrs_provider; /* (owned) (nullable) */ -#ifdef HAVE_SYSPROF - SysprofCaptureWriter *sysprof_writer; /* (owned) (nullable) */ -#endif - GDBusConnection *session_bus_connection; /* (owned); (not nullable) after setup */ GDBusConnection *system_bus_connection; /* (owned); (not nullable) after setup */ }; @@ -454,7 +450,6 @@ gs_plugin_error_handle_failure (GsPluginLoaderHelper *helper, g_autoptr(GError) error_local_copy = NULL; g_autofree gchar *app_id = NULL; g_autofree gchar *origin_id = NULL; - g_autoptr(GsPluginEvent) event = NULL; /* badly behaved plugin */ if (error_local == NULL) { @@ -694,20 +689,17 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper, } #ifdef HAVE_SYSPROF - if (plugin_loader->sysprof_writer != NULL) { + { g_autofree gchar *sysprof_name = NULL; g_autofree gchar *sysprof_message = NULL; sysprof_name = g_strconcat ("vfunc:", gs_plugin_action_to_string (action), NULL); sysprof_message = gs_plugin_job_to_string (helper->plugin_job); - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, - "gnome-software", - sysprof_name, - sysprof_message); + sysprof_collector_mark (begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, + "gnome-software", + sysprof_name, + sysprof_message); } #endif /* HAVE_SYSPROF */ @@ -808,7 +800,7 @@ gs_plugin_loader_run_results (GsPluginLoaderHelper *helper, } #ifdef HAVE_SYSPROF - if (plugin_loader->sysprof_writer != NULL) { + { g_autofree gchar *sysprof_name = NULL; g_autofree gchar *sysprof_message = NULL; @@ -816,14 +808,11 @@ gs_plugin_loader_run_results (GsPluginLoaderHelper *helper, gs_plugin_action_to_string (gs_plugin_job_get_action (helper->plugin_job)), NULL); sysprof_message = gs_plugin_job_to_string (helper->plugin_job); - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, - "gnome-software", - sysprof_name, - sysprof_message); + sysprof_collector_mark (begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, + "gnome-software", + sysprof_name, + sysprof_message); } #endif /* HAVE_SYSPROF */ @@ -1945,7 +1934,6 @@ gs_plugin_loader_setup_async (GsPluginLoader *plugin_loader, SetupData *setup_data; g_autoptr(SetupData) setup_data_owned = NULL; g_autoptr(GTask) task = NULL; - g_autoptr(GError) local_error = NULL; #ifdef HAVE_SYSPROF gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME; #endif @@ -2037,8 +2025,6 @@ finish_setup_get_bus (GTask *task) guint dep_loop_check = 0; guint i; guint j; - g_autoptr(GsPluginLoaderHelper) helper = NULL; - g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GPtrArray) locations = NULL; g_autoptr(GError) local_error = NULL; @@ -2280,7 +2266,6 @@ plugin_setup_cb (GObject *source_object, g_autoptr(GTask) task = g_steal_pointer (&user_data); g_autoptr(GError) local_error = NULL; #ifdef HAVE_SYSPROF - GsPluginLoader *plugin_loader = g_task_get_source_object (task); SetupData *data = g_task_get_task_data (task); #endif /* HAVE_SYSPROF */ @@ -2294,16 +2279,11 @@ plugin_setup_cb (GObject *source_object, } #ifdef HAVE_SYSPROF - if (plugin_loader->sysprof_writer != NULL) { - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - data->plugins_begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - data->plugins_begin_time_nsec, - "gnome-software", - "setup-plugin", - NULL); - } + sysprof_collector_mark (data->plugins_begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - data->plugins_begin_time_nsec, + "gnome-software", + "setup-plugin", + NULL); #endif /* HAVE_SYSPROF */ /* Indicate this plugin has finished setting up. */ @@ -2339,16 +2319,11 @@ finish_setup_op (GTask *task) notify_setup_complete (plugin_loader); #ifdef HAVE_SYSPROF - if (plugin_loader->sysprof_writer != NULL) { - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - data->setup_begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - data->setup_begin_time_nsec, - "gnome-software", - "setup", - NULL); - } + sysprof_collector_mark (data->setup_begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - data->setup_begin_time_nsec, + "gnome-software", + "setup", + NULL); #endif /* HAVE_SYSPROF */ /* Refine the install queue. */ @@ -2576,10 +2551,6 @@ gs_plugin_loader_dispose (GObject *object) g_clear_object (&plugin_loader->odrs_provider); g_clear_object (&plugin_loader->setup_complete_cancellable); -#ifdef HAVE_SYSPROF - g_clear_pointer (&plugin_loader->sysprof_writer, sysprof_capture_writer_unref); -#endif - g_clear_object (&plugin_loader->session_bus_connection); g_clear_object (&plugin_loader->system_bus_connection); @@ -2772,10 +2743,6 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader) const guint odrs_review_n_results_max = 20; const gchar *locale; -#ifdef HAVE_SYSPROF - plugin_loader->sysprof_writer = sysprof_capture_writer_new_from_env (0); -#endif /* HAVE_SYSPROF */ - plugin_loader->setup_complete_cancellable = g_cancellable_new (); plugin_loader->scale = 1; plugin_loader->plugins = g_ptr_array_new_with_free_func (g_object_unref); @@ -3436,17 +3403,14 @@ gs_plugin_loader_process_thread_cb (GTask *task, gs_plugin_loader_job_sorted_truncation_again (helper->plugin_job, list); #ifdef HAVE_SYSPROF - if (plugin_loader->sysprof_writer != NULL) { + { g_autofree gchar *sysprof_name = g_strconcat ("process-thread:", gs_plugin_action_to_string (action), NULL); g_autofree gchar *sysprof_message = gs_plugin_job_to_string (helper->plugin_job); - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, - "gnome-software", - sysprof_name, - sysprof_message); + sysprof_collector_mark (begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, + "gnome-software", + sysprof_name, + sysprof_message); } #endif /* HAVE_SYSPROF */ @@ -3520,20 +3484,16 @@ run_job_cb (GObject *source_object, g_autoptr(GTask) task = g_steal_pointer (&user_data); g_autoptr(GError) local_error = NULL; #ifdef HAVE_SYSPROF - GsPluginLoader *plugin_loader = g_task_get_source_object (task); gint64 begin_time_nsec = GPOINTER_TO_SIZE (g_task_get_task_data (task)); - if (plugin_loader->sysprof_writer != NULL) { + { g_autofree gchar *sysprof_name = g_strconcat ("process-thread:", G_OBJECT_TYPE_NAME (plugin_job), NULL); g_autofree gchar *sysprof_message = gs_plugin_job_to_string (plugin_job); - sysprof_capture_writer_add_mark (plugin_loader->sysprof_writer, - begin_time_nsec, - sched_getcpu (), - getpid (), - SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, - "gnome-software", - sysprof_name, - sysprof_message); + sysprof_collector_mark (begin_time_nsec, + SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec, + "gnome-software", + sysprof_name, + sysprof_message); } #endif /* HAVE_SYSPROF */ diff --git a/lib/meson.build b/lib/meson.build index d591bca3dff8b35140d89412ee2e22c632923c53..9815346b1473a2f2b51c524ac1f4c049513c59e7 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -15,6 +15,7 @@ libgnomesoftware_public_headers = [ 'gs-download-utils.h', 'gs-external-appstream-utils.h', 'gs-icon.h', + 'gs-icon-downloader.h', 'gs-ioprio.h', 'gs-key-colors.h', 'gs-metered.h', @@ -97,6 +98,7 @@ libgnomesoftware = library( 'gs-external-appstream-utils.c', 'gs-fedora-third-party.c', 'gs-icon.c', + 'gs-icon-downloader.c', 'gs-ioprio.c', 'gs-ioprio.h', 'gs-key-colors.c', diff --git a/meson.build b/meson.build index 54a1087a330d9e24d71c12837248492919a676aa..0cf03aaa5be91bf771a7f7e3b0a8ff7a2ed96b83 100644 --- a/meson.build +++ b/meson.build @@ -39,7 +39,6 @@ test_args = [ '-Warray-bounds', '-Wcast-align', '-Wclobbered', - '-Wdeclaration-after-statement', '-Wempty-body', '-Wextra', '-Wformat=2', diff --git a/plugins/core/gs-plugin-icons.c b/plugins/core/gs-plugin-icons.c index 0dbb8ba568dc83171d32ef6f32941a2850fdeaf9..2d11e5a659180f47b2d0884ea34e760dfa71b4ca 100644 --- a/plugins/core/gs-plugin-icons.c +++ b/plugins/core/gs-plugin-icons.c @@ -32,6 +32,8 @@ struct _GsPluginIcons { GsPlugin parent; + GCancellable *download_cancellable; /* (nullable) (owned) */ + SoupSession *soup_session; /* (owned) */ GsWorkerThread *worker; /* (owned) */ }; @@ -118,6 +120,8 @@ shutdown_cb (GObject *source_object, g_autoptr(GsWorkerThread) worker = NULL; g_autoptr(GError) local_error = NULL; + g_cancellable_cancel (self->download_cancellable); + g_clear_object (&self->download_cancellable); g_clear_object (&self->soup_session); worker = g_steal_pointer (&self->worker); @@ -140,26 +144,26 @@ gs_plugin_icons_shutdown_finish (GsPlugin *plugin, static gboolean refine_app (GsPluginIcons *self, GsApp *app, + GsIconDownloader *icon_downloader, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { - guint maximum_icon_size; - assert_in_worker (self); /* not required */ if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON) == 0) return TRUE; - /* Currently a 160px icon is needed for #GsFeatureTile, at most. */ - maximum_icon_size = 160 * gs_plugin_get_scale (GS_PLUGIN (self)); - - gs_app_ensure_icons_downloaded (app, self->soup_session, maximum_icon_size, cancellable); + gs_icon_downloader_queue_app (icon_downloader, app); return TRUE; } +static void icon_download_finished_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data); + static void refine_thread_cb (GTask *task, gpointer source_object, gpointer task_data, @@ -203,21 +207,48 @@ refine_thread_cb (GTask *task, GsAppList *list = data->list; GsPluginRefineFlags flags = data->flags; g_autoptr(GError) local_error = NULL; + g_autoptr(GsIconDownloader) icon_downloader = NULL; assert_in_worker (self); + g_cancellable_cancel (self->download_cancellable); + g_clear_object (&self->download_cancellable); + + icon_downloader = gs_icon_downloader_new (self->soup_session, + 160 * gs_plugin_get_scale (GS_PLUGIN (self))); + for (guint i = 0; i < gs_app_list_length (list); i++) { GsApp *app = gs_app_list_index (list, i); - if (!refine_app (self, app, flags, cancellable, &local_error)) { + if (!refine_app (self, app, icon_downloader, flags, cancellable, &local_error)) { g_task_return_error (task, g_steal_pointer (&local_error)); return; } } + self->download_cancellable = g_cancellable_new (); + + gs_icon_downloader_download (icon_downloader, + self->download_cancellable, + icon_download_finished_cb, + self); + g_task_return_boolean (task, TRUE); } +static void +icon_download_finished_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + + if (!g_task_propagate_boolean (G_TASK (result), &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Error downloading app icons: %s", error->message); + } +} + static gboolean gs_plugin_icons_refine_finish (GsPlugin *plugin, GAsyncResult *result, diff --git a/plugins/flatpak/gs-flatpak-tracing.h b/plugins/flatpak/gs-flatpak-tracing.h new file mode 100644 index 0000000000000000000000000000000000000000..5b1fe47b0206e121667baa86f24e4ead2d78ee5f --- /dev/null +++ b/plugins/flatpak/gs-flatpak-tracing.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2022 Endless OS Foundation LLC + * + * Authors: + * - Georges Basile Stavracas Neto + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#pragma once + +#include +#include + +#ifdef HAVE_SYSPROF +#include +#endif + +#ifdef HAVE_SYSPROF +typedef struct +{ + gint64 begin_time; + const gchar *name; +} GsFlatpakTraceHead; + +static inline void +gs_flatpak_tracing_end (GsFlatpakTraceHead *head) +{ + sysprof_collector_mark (head->begin_time, + SYSPROF_CAPTURE_CURRENT_TIME - head->begin_time, + "gnome-software", + head->name, + NULL); +} + +static inline void +gs_flatpak_tracing_auto_trace_end_helper (GsFlatpakTraceHead **head) +{ + if (*head) + gs_flatpak_tracing_end (*head); +} + +#define GS_FLATPAK_TRACE_BEGIN(Name, sysprof_name) \ + GsFlatpakTraceHead GsFlatpakTrace##Name = { \ + .begin_time = SYSPROF_CAPTURE_CURRENT_TIME, \ + .name = sysprof_name, \ + }; + +#define GS_FLATPAK_TRACE_BEGIN_SCOPED(Name, sysprof_name) \ + GS_FLATPAK_TRACE_BEGIN (Name, sysprof_name); \ + __attribute__((cleanup (gs_flatpak_tracing_auto_trace_end_helper))) \ + GsFlatpakTraceHead *ScopedGsFlatpakTraceHead##Name = &GsFlatpakTrace##Name; \ + +#define GS_FLATPAK_TRACE_END(Name) \ + gs_flatpak_tracing_end (&GsFlatpakTrace##Name); + +#else + +#define GS_FLATPAK_TRACE_BEGIN(Name, name) ((void) 0) +#define GS_FLATPAK_TRACE_BEGIN_SCOPED(Name, sysprof_name) ((void) 0) +#define GS_FLATPAK_TRACE_END(Name) ((void) 0) + +#endif diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c index 7bc976e63c8539884fbcff4f6f726f3bcc5b7843..199fce398eae2925833669761648ec87df285817 100644 --- a/plugins/flatpak/gs-flatpak.c +++ b/plugins/flatpak/gs-flatpak.c @@ -35,6 +35,7 @@ #include "gs-appstream.h" #include "gs-flatpak-app.h" #include "gs-flatpak.h" +#include "gs-flatpak-tracing.h" #include "gs-flatpak-utils.h" struct _GsFlatpak { @@ -3581,6 +3582,8 @@ gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app, g_autoptr(GPtrArray) components = NULL; g_autoptr(GRWLockReaderLocker) locker = NULL; + GS_FLATPAK_TRACE_BEGIN_SCOPED (GsFlatpakRefineWildcard, "Flatpak (refine wildcard)"); + /* not enough info to find */ id = gs_app_get_id (app); if (id == NULL) @@ -3589,6 +3592,8 @@ gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app, if (!ensure_flatpak_silo_with_locker (self, &locker, interactive, cancellable, error)) return FALSE; + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineWildcardQuerySilo, "Flatpak (query silo)"); + /* find all apps when matching any prefixes */ xpath = g_strdup_printf ("components/component/id[text()='%s']/..", id); components = xb_silo_query (self->silo, xpath, 0, &error_local); @@ -3599,20 +3604,35 @@ gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app, return FALSE; } + GS_FLATPAK_TRACE_END (GsFlatpakRefineWildcardQuerySilo); + gs_flatpak_ensure_remote_title (self, interactive, cancellable); + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineWildcardGenerateApps, "Flatpak (create app)"); for (guint i = 0; i < components->len; i++) { XbNode *component = g_ptr_array_index (components, i); g_autoptr(GsApp) new = NULL; + + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineWildcardCreateAppstreamApp, "Flatpak (create Appstream app)"); new = gs_appstream_create_app (self->plugin, self->silo, component, error); + GS_FLATPAK_TRACE_END (GsFlatpakRefineWildcardCreateAppstreamApp); + if (new == NULL) return FALSE; gs_flatpak_claim_app (self, new); + + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineWildcardRefineNewApp, "Flatpak (refine new app)"); if (!gs_flatpak_refine_app_unlocked (self, new, refine_flags, interactive, cancellable, error)) return FALSE; + GS_FLATPAK_TRACE_END (GsFlatpakRefineWildcardRefineNewApp); + + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineWildcardSubsumeMetadata, "Flatpak (subsume metadata)"); gs_app_subsume_metadata (new, app); + GS_FLATPAK_TRACE_END (GsFlatpakRefineWildcardSubsumeMetadata); + gs_app_list_add (list, new); } + GS_FLATPAK_TRACE_END (GsFlatpakRefineWildcardGenerateApps); /* success */ return TRUE; diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c index f5bc685692c3032a5937efcad1b950f7a26f2226..79ee04a6ec3e33f13692ed4255463217be4502b0 100644 --- a/plugins/flatpak/gs-plugin-flatpak.c +++ b/plugins/flatpak/gs-plugin-flatpak.c @@ -33,6 +33,7 @@ #include "gs-appstream.h" #include "gs-flatpak-app.h" #include "gs-flatpak.h" +#include "gs-flatpak-tracing.h" #include "gs-flatpak-transaction.h" #include "gs-flatpak-utils.h" #include "gs-metered.h" @@ -533,6 +534,8 @@ refine_app (GsPluginFlatpak *self, GCancellable *cancellable, GError **error) { + GS_FLATPAK_TRACE_BEGIN (GsFlatpakRefineApp, "Flatpak (refine app)"); + /* only process this app if was created by this plugin */ if (!gs_app_has_management_plugin (app, GS_PLUGIN (self))) return TRUE; @@ -541,10 +544,14 @@ refine_app (GsPluginFlatpak *self, if (!gs_plugin_flatpak_refine_app (self, app, flags, interactive, cancellable, error)) return FALSE; + GS_FLATPAK_TRACE_END (GsFlatpakRefineApp); + /* the runtime might be installed in a different scope */ if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME) { GsApp *runtime = gs_app_get_runtime (app); if (runtime != NULL) { + GS_FLATPAK_TRACE_BEGIN_SCOPED (GsFlatpakRefineAppRuntime, "Flatpak (refine runtime)"); + if (!gs_plugin_flatpak_refine_app (self, runtime, flags, interactive, diff --git a/src/gs-application.c b/src/gs-application.c index 83aea790aa087a825c8ee4957dfb251ff1308f13..0e5a1a49ca83cfb020ca1b6e25956cbd1cb87319 100644 --- a/src/gs-application.c +++ b/src/gs-application.c @@ -175,10 +175,21 @@ gs_application_dbus_unregister (GApplication *application, { GsApplication *app = GS_APPLICATION (application); - if (app->search_provider != NULL) { + if (app->search_provider != NULL) gs_shell_search_provider_unregister (app->search_provider); - g_clear_object (&app->search_provider); - } +} + +static void +gs_application_shutdown (GApplication *application) +{ + GsApplication *app = GS_APPLICATION (application); + + g_cancellable_cancel (app->cancellable); + g_clear_object (&app->cancellable); + + g_clear_object (&app->shell); + + G_APPLICATION_CLASS (gs_application_parent_class)->shutdown (application); } static void @@ -1168,11 +1179,8 @@ gs_application_dispose (GObject *object) { GsApplication *app = GS_APPLICATION (object); - g_cancellable_cancel (app->cancellable); - g_clear_object (&app->cancellable); - + g_clear_object (&app->search_provider); g_clear_object (&app->plugin_loader); - g_clear_object (&app->shell); g_clear_object (&app->update_monitor); #ifdef HAVE_PACKAGEKIT g_clear_object (&app->dbus_helper); @@ -1345,6 +1353,7 @@ gs_application_class_init (GsApplicationClass *klass) application_class->open = gs_application_open; application_class->dbus_register = gs_application_dbus_register; application_class->dbus_unregister = gs_application_dbus_unregister; + application_class->shutdown = gs_application_shutdown; /** * GsApplication:debug: (nullable) diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c index b9fd8c33890770e139a3a482999f971dfe3d5bcd..7a3d7660602d34c6bc4ce8805b3b03066d78b1af 100644 --- a/src/gs-overview-page.c +++ b/src/gs-overview-page.c @@ -549,7 +549,6 @@ fedora_third_party_disable (GsOverviewPage *self) static gchar * gs_overview_page_dup_deployment_featured_filename (void) { - g_autoptr(GPtrArray) dirs = NULL; g_autofree gchar *filename = NULL; const gchar * const *sys_dirs; diff --git a/src/gs-updates-section.c b/src/gs-updates-section.c index 02aae8e8005836d7daeb4ab2c76696fa35e13400..5dd50d6b45b2bd9c2807f18b7f57222c319d4399 100644 --- a/src/gs-updates-section.c +++ b/src/gs-updates-section.c @@ -38,7 +38,7 @@ struct _GsUpdatesSection GsAppList *list; GsUpdatesSectionKind kind; GCancellable *cancellable; - GsPage *page; + GsPage *page; /* (transfer none) */ GsPluginLoader *plugin_loader; GtkSizeGroup *sizegroup_name; GtkSizeGroup *sizegroup_button_label; @@ -542,7 +542,6 @@ gs_updates_section_dispose (GObject *object) g_clear_object (&self->cancellable); g_clear_object (&self->list); g_clear_object (&self->plugin_loader); - g_clear_object (&self->page); g_clear_object (&self->sizegroup_name); g_clear_object (&self->sizegroup_button_label); g_clear_object (&self->sizegroup_button_image); @@ -551,6 +550,7 @@ gs_updates_section_dispose (GObject *object) self->button_update = NULL; self->button_cancel = NULL; self->button_stack = NULL; + self->page = NULL; G_OBJECT_CLASS (gs_updates_section_parent_class)->dispose (object); } @@ -726,7 +726,7 @@ gs_updates_section_new (GsUpdatesSectionKind kind, self = g_object_new (GS_TYPE_UPDATES_SECTION, NULL); self->kind = kind; self->plugin_loader = g_object_ref (plugin_loader); - self->page = g_object_ref (page); + self->page = page; _setup_section_header (self); if (self->kind == GS_UPDATES_SECTION_KIND_ONLINE) { diff --git a/src/gs-upgrade-banner.c b/src/gs-upgrade-banner.c index f0b340726771fe9c39f353a2eba0fa9ffd8d5e71..8a5e6a29eeabc8aa40cc2f364ea0b32ea2db7bb8 100644 --- a/src/gs-upgrade-banner.c +++ b/src/gs-upgrade-banner.c @@ -35,7 +35,7 @@ typedef struct GtkCssProvider *banner_provider; /* (owned) (nullable) */ } GsUpgradeBannerPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (GsUpgradeBanner, gs_upgrade_banner, GTK_TYPE_WIDGET) +G_DEFINE_TYPE_WITH_PRIVATE (GsUpgradeBanner, gs_upgrade_banner, ADW_TYPE_BIN) enum { SIGNAL_DOWNLOAD_CLICKED, @@ -348,7 +348,6 @@ gs_upgrade_banner_class_init (GsUpgradeBannerClass *klass) G_TYPE_NONE, 0); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-upgrade-banner.ui"); - gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, box_upgrades_info); gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, box_upgrades_download); diff --git a/src/gs-upgrade-banner.h b/src/gs-upgrade-banner.h index 2ddf6021e6e0300336a0b8a3525a6073889fcfeb..7aff12ba089db88114ac697ecb602c7141c448e3 100644 --- a/src/gs-upgrade-banner.h +++ b/src/gs-upgrade-banner.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include "gnome-software-private.h" @@ -16,11 +16,11 @@ G_BEGIN_DECLS #define GS_TYPE_UPGRADE_BANNER (gs_upgrade_banner_get_type ()) -G_DECLARE_DERIVABLE_TYPE (GsUpgradeBanner, gs_upgrade_banner, GS, UPGRADE_BANNER, GtkWidget) +G_DECLARE_DERIVABLE_TYPE (GsUpgradeBanner, gs_upgrade_banner, GS, UPGRADE_BANNER, AdwBin) struct _GsUpgradeBannerClass { - GtkWidgetClass parent_class; + AdwBinClass parent_class; void (*download_clicked) (GsUpgradeBanner *self); void (*install_clicked) (GsUpgradeBanner *self); diff --git a/src/gs-upgrade-banner.ui b/src/gs-upgrade-banner.ui index 1f0f6abef327b7536b2134bd94b796e10127683f..3ea236bd33dc6591c1bc366b52a1c1e21279af7e 100644 --- a/src/gs-upgrade-banner.ui +++ b/src/gs-upgrade-banner.ui @@ -1,7 +1,7 @@ -