static GsApp* gs_plugin_app_from_pki (LiPkgInfo *pki) { const gchar *cptkind_str; GsApp *app; cptkind_str = li_pkg_info_get_component_kind (pki); if ((cptkind_str != NULL) && (g_strcmp0 (cptkind_str, "desktop") == 0)) { g_autofree gchar *tmp = NULL; /* type=desktop AppStream components result in a Limba bundle name which has the .desktop stripped away. * We need to re-add it for GNOME Software. * In any other case, the Limba bundle name equals the AppStream ID of the component it contains */ tmp = g_strdup_printf ("%s.desktop", li_pkg_info_get_name (pki)); app = gs_app_new (tmp); gs_app_set_kind (app, AS_APP_KIND_DESKTOP); } else { app = gs_app_new (li_pkg_info_get_name (pki)); gs_app_set_kind (app, AS_APP_KIND_GENERIC); } /* TODO: scope?, branch? */ gs_app_set_management_plugin (app, "limba"); gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE); gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_LIMBA); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, li_pkg_info_get_name (pki)); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, li_pkg_info_get_name (pki)); gs_app_set_version (app, li_pkg_info_get_version (pki)); gs_app_add_source (app, li_pkg_info_get_id (pki)); return app; }
static GsApp * gs_plugin_generic_updates_get_os_update (GsPlugin *plugin) { GsApp *app; const gchar *id = "org.gnome.Software.OsUpdate"; g_autoptr(AsIcon) ic = NULL; /* create new */ app = gs_app_new (id); gs_app_add_quirk (app, GS_APP_QUIRK_IS_PROXY); gs_app_set_management_plugin (app, ""); gs_app_set_kind (app, AS_APP_KIND_OS_UPDATE); gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, /* TRANSLATORS: this is a group of updates that are not * packages and are not shown in the main list */ _("OS Updates")); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, /* TRANSLATORS: this is a longer description of the * "OS Updates" string */ _("Includes performance, stability and security improvements.")); gs_app_set_description (app, GS_APP_QUALITY_NORMAL, gs_app_get_summary (app)); ic = as_icon_new (); as_icon_set_kind (ic, AS_ICON_KIND_STOCK); as_icon_set_name (ic, "software-update-available-symbolic"); gs_app_add_icon (app, ic); return app; }
/** * gs_plugin_xdg_app_create_installed: */ static GsApp * gs_plugin_xdg_app_create_installed (GsPlugin *plugin, XdgAppInstalledRef *xref, GError **error) { g_autofree gchar *id = NULL; g_autoptr(AsIcon) icon = NULL; g_autoptr(GsApp) app = NULL; g_return_val_if_fail (xref != NULL, NULL); /* * Only show the current application in GNOME Software * * You can have multiple versions/branches of a particular app-id * installed but only one of them is "current" where this means: * 1) the default to launch unless you specify a version * 2) The one that gets its exported files exported */ if (!xdg_app_installed_ref_get_is_current (xref) && xdg_app_ref_get_kind (XDG_APP_REF(xref)) == XDG_APP_REF_KIND_APP) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "%s not current, ignoring", xdg_app_ref_get_name (XDG_APP_REF (xref))); return NULL; } /* create new object */ id = gs_plugin_xdg_app_build_id (XDG_APP_REF (xref)); app = gs_app_new (id); gs_plugin_xdg_app_set_metadata_installed (app, xref); switch (xdg_app_ref_get_kind (XDG_APP_REF(xref))) { case XDG_APP_REF_KIND_APP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); break; case XDG_APP_REF_KIND_RUNTIME: gs_app_set_xdgapp_kind (app, XDG_APP_REF_KIND_RUNTIME); gs_app_set_kind (app, AS_APP_KIND_RUNTIME); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, xdg_app_ref_get_name (XDG_APP_REF (xref))); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Framework for applications"); gs_app_set_version (app, xdg_app_ref_get_branch (XDG_APP_REF (xref))); icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "system-run-symbolic"); gs_app_set_icon (app, icon); break; default: g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "XdgAppRefKind not known"); return NULL; } return g_object_ref (app); }
gboolean gs_plugin_add_sources (GsPlugin *plugin, GsAppList *list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); PkBitfield filter; PkRepoDetail *rd; ProgressData data; const gchar *id; guint i; g_autoptr(GHashTable) hash = NULL; g_autoptr(PkResults) results = NULL; g_autoptr(GPtrArray) array = NULL; data.app = NULL; data.plugin = plugin; data.ptask = NULL; /* ask PK for the repo details */ filter = pk_bitfield_from_enums (PK_FILTER_ENUM_NOT_SOURCE, PK_FILTER_ENUM_NOT_SUPPORTED, -1); results = pk_client_get_repo_list (PK_CLIENT(priv->task), filter, cancellable, gs_plugin_packagekit_progress_cb, &data, error); if (!gs_plugin_packagekit_results_valid (results, error)) return FALSE; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); array = pk_results_get_repo_detail_array (results); for (i = 0; i < array->len; i++) { g_autoptr(GsApp) app = NULL; rd = g_ptr_array_index (array, i); id = pk_repo_detail_get_id (rd); app = gs_app_new (id); gs_app_set_management_plugin (app, gs_plugin_get_name (plugin)); gs_app_set_kind (app, AS_APP_KIND_SOURCE); gs_app_set_state (app, pk_repo_detail_get_enabled (rd) ? AS_APP_STATE_INSTALLED : AS_APP_STATE_AVAILABLE); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, pk_repo_detail_get_description (rd)); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, pk_repo_detail_get_description (rd)); gs_app_list_add (list, app); g_hash_table_insert (hash, g_strdup (id), (gpointer) app); } /* get every application on the system and add it as a related package * if it matches */ return gs_plugin_add_sources_related (plugin, hash, cancellable, error); }
/** * gs_plugin_add_updates: */ gboolean gs_plugin_add_updates (GsPlugin *plugin, GList **list, GCancellable *cancellable, GError **error) { GsApp *app; /* update UI as this might take some time */ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING); /* spin */ g_usleep (2 * G_USEC_PER_SEC); /* add a normal application */ app = gs_app_new ("gnome-boxes"); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Boxes"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Do not segfault when using newer versons of libvirt."); gs_app_set_kind (app, GS_APP_KIND_NORMAL); gs_app_set_id_kind (app, AS_ID_KIND_DESKTOP); gs_plugin_add_app (list, app); g_object_unref (app); /* add an OS update */ app = gs_app_new ("libvirt-glib-devel;0.0.1;noarch;fedora"); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "libvirt-glib-devel"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Fix several memory leaks."); gs_app_set_kind (app, GS_APP_KIND_PACKAGE); gs_app_set_id_kind (app, AS_ID_KIND_DESKTOP); gs_plugin_add_app (list, app); g_object_unref (app); /* add a second OS update */ app = gs_app_new ("gnome-boxes-libs;0.0.1;i386;updates-testing"); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "gnome-boxes-libs"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Do not segfault when using newer versons of libvirt."); gs_app_set_kind (app, GS_APP_KIND_PACKAGE); gs_app_set_id_kind (app, AS_ID_KIND_DESKTOP); gs_plugin_add_app (list, app); g_object_unref (app); return TRUE; }
static GsApp * gs_plugin_create_app_dummy (const gchar *id) { GsApp *app = gs_app_new (id); g_autoptr(GString) str = NULL; str = g_string_new (id); as_utils_string_replace (str, ".desktop", ""); g_string_prepend (str, "No description is available for "); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, "Unknown Application"); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, "Application not found"); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, str->str); return app; }
/** * gs_plugin_add_popular: */ gboolean gs_plugin_add_popular (GsPlugin *plugin, GList **list, GCancellable *cancellable, GError **error) { g_autoptr(GsApp) app = gs_app_new ("gnome-power-manager"); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Power Manager"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Power Management Program"); gs_app_set_state (app, AS_APP_STATE_AVAILABLE); gs_app_set_kind (app, GS_APP_KIND_NORMAL); gs_plugin_add_app (list, app); gs_app_set_id_kind (app, AS_ID_KIND_DESKTOP); return TRUE; }
/** * gs_plugin_add_category_apps: */ gboolean gs_plugin_add_category_apps (GsPlugin *plugin, GsCategory *category, GList **list, GCancellable *cancellable, GError **error) { g_autoptr(GsApp) app = gs_app_new ("gnome-boxes"); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Boxes"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "View and use virtual machines"); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, "http://www.box.org"); gs_app_set_kind (app, GS_APP_KIND_NORMAL); gs_app_set_state (app, AS_APP_STATE_AVAILABLE); gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file ("/usr/share/icons/hicolor/48x48/apps/gnome-boxes.png", NULL)); gs_app_set_id_kind (app, AS_ID_KIND_DESKTOP); gs_plugin_add_app (list, app); return TRUE; }
gboolean gs_plugin_add_sources (GsPlugin *plugin, GsAppList *list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(GPtrArray) remotes = NULL; /* find all remotes */ remotes = fwupd_client_get_remotes (priv->client, cancellable, error); if (remotes == NULL) return FALSE; for (guint i = 0; i < remotes->len; i++) { FwupdRemote *remote = g_ptr_array_index (remotes, i); g_autofree gchar *id = NULL; g_autoptr(GsApp) app = NULL; /* ignore these, they're built in */ if (fwupd_remote_get_kind (remote) != FWUPD_REMOTE_KIND_DOWNLOAD) continue; /* create something that we can use to enable/disable */ id = g_strdup_printf ("org.fwupd.%s.remote", fwupd_remote_get_id (remote)); app = gs_app_new (id); gs_app_set_kind (app, AS_APP_KIND_SOURCE); gs_app_set_scope (app, AS_APP_SCOPE_SYSTEM); gs_app_set_state (app, fwupd_remote_get_enabled (remote) ? AS_APP_STATE_INSTALLED : AS_APP_STATE_AVAILABLE); gs_app_add_quirk (app, GS_APP_QUIRK_NOT_LAUNCHABLE); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, fwupd_remote_get_title (remote)); #if FWUPD_CHECK_VERSION(1,0,7) gs_app_set_agreement (app, fwupd_remote_get_agreement (remote)); #endif gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, fwupd_remote_get_metadata_uri (remote)); gs_app_set_metadata (app, "fwupd::remote-id", fwupd_remote_get_id (remote)); gs_app_set_management_plugin (app, "fwupd"); gs_app_list_add (list, app); } return TRUE; }
/** * gs_plugin_add_sources: */ gboolean gs_plugin_add_sources (GsPlugin *plugin, GList **list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(GPtrArray) xremotes = NULL; guint i; xremotes = xdg_app_installation_list_remotes (priv->installation, cancellable, error); if (xremotes == NULL) return FALSE; for (i = 0; i < xremotes->len; i++) { XdgAppRemote *xremote = g_ptr_array_index (xremotes, i); g_autoptr(GsApp) app = NULL; /* apps installed from bundles add their own remote that only * can be used for updating that app only -- so hide them */ if (xdg_app_remote_get_noenumerate (xremote)) continue; app = gs_app_new (xdg_app_remote_get_name (xremote)); gs_app_set_management_plugin (app, gs_plugin_get_name (plugin)); gs_app_set_kind (app, AS_APP_KIND_SOURCE); gs_app_set_state (app, AS_APP_STATE_INSTALLED); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, xdg_app_remote_get_name (xremote)); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, xdg_app_remote_get_title (xremote)); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, xdg_app_remote_get_url (xremote)); gs_app_list_add (list, app); } return TRUE; }
/** * gs_plugin_refine: */ gboolean gs_plugin_refine (GsPlugin *plugin, GList **list, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GsApp *app; GList *l; for (l = *list; l != NULL; l = l->next) { app = GS_APP (l->data); if (gs_app_get_name (app) == NULL) { if (g_strcmp0 (gs_app_get_id (app), "gnome-boxes") == 0) { gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Boxes"); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A simple GNOME 3 application to access remote or virtual systems"); } } } return TRUE; }
static GsApp * gs_plugin_fwupd_new_app_from_device_raw (GsPlugin *plugin, FwupdDevice *device) { GPtrArray *icons; g_autofree gchar *id = NULL; g_autoptr(GsApp) app = NULL; /* create a GsApp based on the device, not the release */ id = gs_plugin_fwupd_build_device_id (device); app = gs_app_new (id); gs_app_set_kind (app, AS_APP_KIND_FIRMWARE); gs_app_set_scope (app, AS_APP_SCOPE_SYSTEM); gs_app_set_state (app, AS_APP_STATE_INSTALLED); gs_app_add_quirk (app, GS_APP_QUIRK_NOT_LAUNCHABLE); gs_app_set_version (app, fwupd_device_get_version (device)); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, fwupd_device_get_name (device)); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, fwupd_device_get_summary (device)); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, fwupd_device_get_description (device)); gs_app_set_origin (app, fwupd_device_get_vendor (device)); gs_fwupd_app_set_device_id (app, fwupd_device_get_id (device)); gs_app_set_management_plugin (app, "fwupd"); /* create icon */ icons = fwupd_device_get_icons (device); for (guint j = 0; j < icons->len; j++) { const gchar *icon = g_ptr_array_index (icons, j); g_autoptr(AsIcon) icon_tmp = as_icon_new (); if (g_str_has_prefix (icon, "/")) { as_icon_set_kind (icon_tmp, AS_ICON_KIND_LOCAL); as_icon_set_filename (icon_tmp, icon); } else { as_icon_set_kind (icon_tmp, AS_ICON_KIND_STOCK); as_icon_set_name (icon_tmp, icon); } gs_app_add_icon (app, icon_tmp); } return g_steal_pointer (&app); }
gboolean gs_plugin_add_distro_upgrades (GsPlugin *plugin, GsAppList *list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); gsize len; guint i; g_autofree gchar *data = NULL; g_autoptr(GPtrArray) distros = NULL; g_autoptr(GSettings) settings = NULL; /* just ensure there is any data, no matter how old */ if (!gs_plugin_fedora_distro_upgrades_refresh (plugin, G_MAXUINT, cancellable, error)) return FALSE; /* get cached file */ if (!g_file_get_contents (priv->cachefn, &data, &len, error)) { gs_utils_error_convert_gio (error); return FALSE; } /* parse data */ settings = g_settings_new ("org.gnome.software"); distros = parse_pkgdb_collections_data (data, (gssize) len, error); if (distros == NULL) return FALSE; g_ptr_array_sort (distros, sort_distros_cb); for (i = 0; i < distros->len; i++) { DistroInfo *distro_info = g_ptr_array_index (distros, i); g_autofree gchar *app_id = NULL; g_autofree gchar *app_version = NULL; g_autofree gchar *background = NULL; g_autofree gchar *cache_key = NULL; g_autofree gchar *url = NULL; g_autofree gchar *css = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(AsIcon) ic = NULL; /* only interested in upgrades to the same distro */ if (g_strcmp0 (distro_info->name, priv->os_name) != 0) continue; /* only interested in newer versions, but not more than N+2 */ if (distro_info->version <= priv->os_version || distro_info->version > priv->os_version + 2) continue; /* only interested in non-devel distros */ if (!g_settings_get_boolean (settings, "show-upgrade-prerelease")) { if (distro_info->status == DISTRO_STATUS_DEVEL) continue; } /* search in the cache */ cache_key = g_strdup_printf ("release-%u", distro_info->version); app = gs_plugin_cache_lookup (plugin, cache_key); if (app != NULL) { gs_app_list_add (list, app); continue; } app_id = g_strdup_printf ("org.fedoraproject.release-%u.upgrade", distro_info->version); app_version = g_strdup_printf ("%u", distro_info->version); /* icon from disk */ ic = as_icon_new (); as_icon_set_kind (ic, AS_ICON_KIND_LOCAL); as_icon_set_filename (ic, "/usr/share/pixmaps/fedora-logo-sprite.png"); /* create */ app = gs_app_new (app_id); gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE); gs_app_set_state (app, AS_APP_STATE_AVAILABLE); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, distro_info->name); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, /* TRANSLATORS: this is a title for Fedora distro upgrades */ _("A major upgrade, with new features and added polish.")); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, "Fedora Workstation is a polished, " "easy to use operating system for " "laptop and desktop computers, with a " "complete set of tools for developers " "and makers of all kinds."); gs_app_set_version (app, app_version); gs_app_set_size_installed (app, 1024 * 1024 * 1024); /* estimate */ gs_app_set_size_download (app, 256 * 1024 * 1024); /* estimate */ gs_app_set_license (app, GS_APP_QUALITY_LOWEST, "LicenseRef-free"); gs_app_add_quirk (app, AS_APP_QUIRK_NEEDS_REBOOT); gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE); gs_app_add_quirk (app, AS_APP_QUIRK_NOT_REVIEWABLE); gs_app_set_origin_ui (app, distro_info->name); gs_app_add_icon (app, ic); gs_app_set_management_plugin (app, "packagekit"); /* show a Fedora magazine article for the release */ url = g_strdup_printf ("https://fedoramagazine.org/whats-new-fedora-%u-workstation", distro_info->version); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, url); /* use a fancy background */ background = get_upgrade_css_background (distro_info->version); css = g_strdup_printf ("background: %s;" "background-position: center;" "background-size: cover;", background); gs_app_set_metadata (app, "GnomeSoftware::UpgradeBanner-css", css); gs_app_list_add (list, app); /* save in the cache */ gs_plugin_cache_add (plugin, cache_key, app); } return TRUE; }
/** * gs_plugin_filename_to_app: */ gboolean gs_plugin_filename_to_app (GsPlugin *plugin, GList **list, const gchar *filename, GCancellable *cancellable, GError **error) { const gchar *package_id; gboolean supported; PkDetails *item; ProgressData data; g_autoptr (PkResults) results = NULL; g_autofree gchar *basename = NULL; g_autofree gchar *license_spdx = NULL; g_auto(GStrv) files = NULL; g_auto(GStrv) split = NULL; g_autoptr(GPtrArray) array = NULL; g_autoptr(GsApp) app = NULL; /* does this match any of the mimetypes we support */ if (!gs_plugin_packagekit_refresh_content_type_matches (filename, &supported, cancellable, error)) return FALSE; if (!supported) return TRUE; data.plugin = plugin; data.ptask = NULL; /* get details */ files = g_strsplit (filename, "\t", -1); pk_client_set_cache_age (PK_CLIENT (plugin->priv->task), G_MAXUINT); results = pk_client_get_details_local (PK_CLIENT (plugin->priv->task), files, cancellable, gs_plugin_packagekit_progress_cb, &data, error); if (results == NULL) return FALSE; /* get results */ array = pk_results_get_details_array (results); if (array->len == 0) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "no details for %s", filename); return FALSE; } if (array->len > 1) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "too many details [%i] for %s", array->len, filename); return FALSE; } /* create application */ item = g_ptr_array_index (array, 0); app = gs_app_new (NULL); package_id = pk_details_get_package_id (item); split = pk_package_id_split (package_id); basename = g_path_get_basename (filename); gs_app_set_management_plugin (app, "PackageKit"); gs_app_set_kind (app, GS_APP_KIND_PACKAGE); gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL); if (pk_details_get_summary (item)) gs_app_set_name (app, GS_APP_QUALITY_LOWEST, pk_details_get_summary (item)); else gs_app_set_name (app, GS_APP_QUALITY_LOWEST, split[PK_PACKAGE_ID_NAME]); gs_app_set_version (app, split[PK_PACKAGE_ID_VERSION]); gs_app_set_metadata (app, "PackageKit::local-filename", filename); gs_app_set_origin (app, basename); gs_app_add_source (app, split[PK_PACKAGE_ID_NAME]); gs_app_add_source_id (app, package_id); gs_plugin_packagekit_refresh_set_text (app, pk_details_get_description (item)); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, pk_details_get_url (item)); gs_app_set_size (app, pk_details_get_size (item)); license_spdx = as_utils_license_to_spdx (pk_details_get_license (item)); gs_app_set_licence (app, license_spdx, GS_APP_QUALITY_LOWEST); /* look for a desktop file so we can use a valid application id */ if (!gs_plugin_packagekit_refresh_guess_app_id (plugin, app, filename, cancellable, error)) return FALSE; gs_plugin_add_app (list, app); return TRUE; }
/** * gs_appstream_refine_app: */ gboolean gs_appstream_refine_app (GsPlugin *plugin, GsApp *app, AsApp *item, GError **error) { AsRelease *rel; GHashTable *urls; GPtrArray *pkgnames; GPtrArray *kudos; const gchar *tmp; guint i; /* set the kind to be more precise */ if (gs_app_get_kind (app) == AS_APP_KIND_UNKNOWN || gs_app_get_kind (app) == AS_APP_KIND_GENERIC) { gs_app_set_kind (app, as_app_get_kind (item)); } /* is installed already */ if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN) { switch (as_app_get_source_kind (item)) { case AS_APP_SOURCE_KIND_APPDATA: case AS_APP_SOURCE_KIND_DESKTOP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); gs_app_set_state (app, AS_APP_STATE_INSTALLED); break; case AS_APP_SOURCE_KIND_METAINFO: gs_app_set_state (app, AS_APP_STATE_INSTALLED); break; case AS_APP_SOURCE_KIND_APPSTREAM: gs_app_set_state (app, as_app_get_state (item)); break; default: break; } } /* set management plugin automatically */ gs_refine_item_management_plugin (app, item); /* set id */ if (as_app_get_id (item) != NULL && gs_app_get_id (app) == NULL) gs_app_set_id (app, as_app_get_id (item)); /* set name */ tmp = as_app_get_name (item, NULL); if (tmp != NULL) { if (g_str_has_prefix (tmp, "(Nightly) ")) { tmp += 10; if (gs_app_get_metadata_item (app, "X-XdgApp-Tags") == NULL) gs_app_set_metadata (app, "X-XdgApp-Tags", "nightly"); } gs_app_set_name (app, GS_APP_QUALITY_HIGHEST, tmp); } /* set summary */ tmp = as_app_get_comment (item, NULL); if (tmp != NULL) { gs_app_set_summary (app, GS_APP_QUALITY_HIGHEST, tmp); } /* add urls */ urls = as_app_get_urls (item); if (g_hash_table_size (urls) > 0 && gs_app_get_url (app, AS_URL_KIND_HOMEPAGE) == NULL) { GList *l; g_autoptr(GList) keys = NULL; keys = g_hash_table_get_keys (urls); for (l = keys; l != NULL; l = l->next) { gs_app_set_url (app, as_url_kind_from_string (l->data), g_hash_table_lookup (urls, l->data)); } } /* set licence */ if (as_app_get_project_license (item) != NULL && gs_app_get_license (app) == NULL) gs_app_set_license (app, GS_APP_QUALITY_HIGHEST, as_app_get_project_license (item)); /* set keywords */ if (as_app_get_keywords (item, NULL) != NULL && gs_app_get_keywords (app) == NULL) { gs_app_set_keywords (app, as_app_get_keywords (item, NULL)); gs_app_add_kudo (app, GS_APP_KUDO_HAS_KEYWORDS); } /* set origin */ if (as_app_get_origin (item) != NULL && gs_app_get_origin (app) == NULL) { gs_app_set_origin (app, as_app_get_origin (item)); } /* set description */ tmp = as_app_get_description (item, NULL); if (tmp != NULL) { g_autofree gchar *from_xml = NULL; from_xml = as_markup_convert_simple (tmp, error); if (from_xml == NULL) { g_prefix_error (error, "trying to parse '%s': ", tmp); return FALSE; } gs_app_set_description (app, GS_APP_QUALITY_HIGHEST, from_xml); } /* set icon */ if (as_app_get_icon_default (item) != NULL && gs_app_get_pixbuf (app) == NULL) gs_refine_item_pixbuf (plugin, app, item); /* set categories */ if (as_app_get_categories (item) != NULL && gs_app_get_categories (app)->len == 0) gs_app_set_categories (app, as_app_get_categories (item)); /* set project group */ if (as_app_get_project_group (item) != NULL && gs_app_get_project_group (app) == NULL) gs_app_set_project_group (app, as_app_get_project_group (item)); /* this is a core application for the desktop and cannot be removed */ if (_as_app_has_compulsory_for_desktop (item, "GNOME") && gs_app_get_kind (app) == AS_APP_KIND_DESKTOP) gs_app_add_quirk (app, AS_APP_QUIRK_COMPULSORY); /* set id kind */ if (gs_app_get_kind (app) == AS_APP_KIND_UNKNOWN) gs_app_set_kind (app, as_app_get_kind (item)); /* copy all the metadata */ gs_appstream_copy_metadata (app, item); /* set package names */ pkgnames = as_app_get_pkgnames (item); if (pkgnames->len > 0 && gs_app_get_sources(app)->len == 0) gs_app_set_sources (app, pkgnames); /* set addons */ gs_appstream_refine_add_addons (plugin, app, item); /* set screenshots */ gs_appstream_refine_add_screenshots (app, item); /* are the screenshots perfect */ if (gs_appstream_are_screenshots_perfect (item)) gs_app_add_kudo (app, GS_APP_KUDO_PERFECT_SCREENSHOTS); /* was this application released recently */ if (gs_appstream_is_recent_release (item)) gs_app_add_kudo (app, GS_APP_KUDO_RECENT_RELEASE); /* add kudos */ if (as_app_get_language (item, plugin->locale) > 50) gs_app_add_kudo (app, GS_APP_KUDO_MY_LANGUAGE); /* add new-style kudos */ kudos = as_app_get_kudos (item); for (i = 0; i < kudos->len; i++) { tmp = g_ptr_array_index (kudos, i); switch (as_kudo_kind_from_string (tmp)) { case AS_KUDO_KIND_SEARCH_PROVIDER: gs_app_add_kudo (app, GS_APP_KUDO_SEARCH_PROVIDER); break; case AS_KUDO_KIND_USER_DOCS: gs_app_add_kudo (app, GS_APP_KUDO_INSTALLS_USER_DOCS); break; case AS_KUDO_KIND_APP_MENU: gs_app_add_kudo (app, GS_APP_KUDO_USES_APP_MENU); break; case AS_KUDO_KIND_MODERN_TOOLKIT: gs_app_add_kudo (app, GS_APP_KUDO_MODERN_TOOLKIT); break; case AS_KUDO_KIND_NOTIFICATIONS: gs_app_add_kudo (app, GS_APP_KUDO_USES_NOTIFICATIONS); break; case AS_KUDO_KIND_HIGH_CONTRAST: gs_app_add_kudo (app, GS_APP_KUDO_HIGH_CONTRAST); break; case AS_KUDO_KIND_HI_DPI_ICON: gs_app_add_kudo (app, GS_APP_KUDO_HI_DPI_ICON); break; default: g_debug ("no idea how to handle kudo '%s'", tmp); break; } } /* is there any update information */ rel = as_app_get_release_default (item); if (rel != NULL) { tmp = as_release_get_description (rel, NULL); if (tmp != NULL) { g_autofree gchar *desc = NULL; desc = as_markup_convert (tmp, AS_MARKUP_CONVERT_FORMAT_MARKDOWN, error); if (desc == NULL) return FALSE; gs_app_set_update_details (app, desc); } gs_app_set_update_urgency (app, as_release_get_urgency (rel)); gs_app_set_update_version (app, as_release_get_version (rel)); } return TRUE; }
gboolean gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(SnapdClient) client = NULL; const gchar *name; g_autoptr(SnapdSnap) local_snap = NULL; g_autoptr(SnapdSnap) store_snap = NULL; SnapdSnap *snap; const gchar *developer_name; g_autofree gchar *description = NULL; /* not us */ if (g_strcmp0 (gs_app_get_management_plugin (app), "snap") != 0) return TRUE; client = get_client (plugin, error); if (client == NULL) return FALSE; /* get information from local snaps and store */ local_snap = snapd_client_get_snap_sync (client, gs_app_get_metadata_item (app, "snap::name"), cancellable, NULL); if (local_snap == NULL || (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SCREENSHOTS) != 0) store_snap = get_store_snap (plugin, gs_app_get_metadata_item (app, "snap::name"), cancellable, NULL); if (local_snap == NULL && store_snap == NULL) return TRUE; if (local_snap != NULL) gs_app_set_state (app, AS_APP_STATE_INSTALLED); else gs_app_set_state (app, AS_APP_STATE_AVAILABLE); /* use store information for basic metadata over local information */ snap = store_snap != NULL ? store_snap : local_snap; name = snapd_snap_get_title (snap); if (name == NULL || g_strcmp0 (name, "") == 0) name = snapd_snap_get_name (snap); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, name); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, snapd_snap_get_summary (snap)); description = gs_plugin_snap_get_description_safe (snap); if (description != NULL) gs_app_set_description (app, GS_APP_QUALITY_NORMAL, description); gs_app_set_license (app, GS_APP_QUALITY_NORMAL, snapd_snap_get_license (snap)); developer_name = snapd_snap_get_publisher_display_name (snap); if (developer_name == NULL) developer_name = snapd_snap_get_publisher_username (snap); gs_app_set_developer_name (app, developer_name); if (snapd_snap_get_publisher_validation (snap) == SNAPD_PUBLISHER_VALIDATION_VERIFIED) gs_app_add_quirk (app, GS_APP_QUIRK_DEVELOPER_VERIFIED); snap = local_snap != NULL ? local_snap : store_snap; gs_app_set_version (app, snapd_snap_get_version (snap)); switch (snapd_snap_get_snap_type (snap)) { case SNAPD_SNAP_TYPE_APP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); break; case SNAPD_SNAP_TYPE_KERNEL: case SNAPD_SNAP_TYPE_GADGET: case SNAPD_SNAP_TYPE_OS: gs_app_set_kind (app, AS_APP_KIND_RUNTIME); break; default: case SNAPD_SNAP_TYPE_UNKNOWN: gs_app_set_kind (app, AS_APP_KIND_UNKNOWN); break; } /* add information specific to installed snaps */ if (local_snap != NULL) { SnapdApp *snap_app; GDateTime *install_date; install_date = snapd_snap_get_install_date (local_snap); gs_app_set_size_installed (app, snapd_snap_get_installed_size (local_snap)); gs_app_set_install_date (app, install_date != NULL ? g_date_time_to_unix (install_date) : GS_APP_INSTALL_DATE_UNKNOWN); snap_app = get_primary_app (local_snap); if (snap_app != NULL) { gs_app_set_metadata (app, "snap::launch-name", snapd_app_get_name (snap_app)); gs_app_set_metadata (app, "snap::launch-desktop", snapd_app_get_desktop_file (snap_app)); } else { gs_app_add_quirk (app, GS_APP_QUIRK_NOT_LAUNCHABLE); } } /* add information specific to store snaps */ if (store_snap != NULL) { gs_app_set_origin (app, priv->store_name); gs_app_set_size_download (app, snapd_snap_get_download_size (store_snap)); if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SCREENSHOTS && gs_app_get_screenshots (app)->len == 0) refine_screenshots (app, store_snap); } /* load icon if requested */ if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON && gs_app_get_pixbuf (app) == NULL) load_icon (plugin, client, app, gs_app_get_metadata_item (app, "snap::name"), local_snap, store_snap, cancellable); return TRUE; }
static GsApp * gs_editor_convert_app (GsEditor *self, AsApp *item) { AsApp *item_global; AsAppState item_state; GsApp *app; const gchar *keys[] = { "GnomeSoftware::AppTile-css", "GnomeSoftware::FeatureTile-css", "GnomeSoftware::UpgradeBanner-css", NULL }; /* copy name, summary and description */ app = gs_app_new (as_app_get_id (item)); item_global = as_store_get_app_by_id (self->store_global, as_app_get_id (item)); if (item_global == NULL) { const gchar *tmp; g_autoptr(AsIcon) ic = NULL; g_debug ("no app found for %s, using fallback", as_app_get_id (item)); /* copy from AsApp, falling back to something sane */ tmp = as_app_get_name (item, NULL); if (tmp == NULL) tmp = "Application"; gs_app_set_name (app, GS_APP_QUALITY_NORMAL, tmp); tmp = as_app_get_comment (item, NULL); if (tmp == NULL) tmp = "Description"; gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, tmp); tmp = as_app_get_description (item, NULL); if (tmp == NULL) tmp = "A multiline description"; gs_app_set_description (app, GS_APP_QUALITY_NORMAL, tmp); ic = as_icon_new (); as_icon_set_kind (ic, AS_ICON_KIND_STOCK); as_icon_set_name (ic, "application-x-executable"); gs_app_add_icon (app, ic); item_state = as_app_get_state (item); } else { GPtrArray *icons; g_debug ("found global app for %s", as_app_get_id (item)); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, as_app_get_name (item_global, NULL)); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, as_app_get_comment (item_global, NULL)); gs_app_set_description (app, GS_APP_QUALITY_NORMAL, as_app_get_description (item_global, NULL)); icons = as_app_get_icons (item_global); for (guint i = 0; i < icons->len; i++) { AsIcon *icon = g_ptr_array_index (icons, i); gs_app_add_icon (app, icon); } item_state = as_app_get_state (item_global); } /* copy state */ if (item_state == AS_APP_STATE_UNKNOWN) item_state = AS_APP_STATE_AVAILABLE; gs_app_set_state (app, item_state); /* copy version */ gs_app_set_version (app, "3.28"); /* load pixbuf */ gs_editor_refine_app_pixbuf (app); /* copy metadata */ for (guint i = 0; keys[i] != NULL; i++) { g_autoptr(GError) error = NULL; const gchar *markup = as_app_get_metadata_item (item, keys[i]); if (markup != NULL) { g_autofree gchar *css_new = NULL; css_new = gs_editor_css_download_resources (self, markup, &error); if (css_new == NULL) { g_warning ("%s", error->message); gs_app_set_metadata (app, keys[i], markup); } else { gs_app_set_metadata (app, keys[i], css_new); } } else { gs_app_set_metadata (app, keys[i], NULL); } } return app; }
gboolean gs_plugin_file_to_app (GsPlugin *plugin, GsAppList *list, GFile *file, GCancellable *cancellable, GError **error) { GsApp *app; guint i; g_autofree gchar *content_type = NULL; g_autofree gchar *output = NULL; g_auto(GStrv) argv = NULL; g_auto(GStrv) tokens = NULL; g_autoptr(GString) str = NULL; const gchar *mimetypes[] = { "application/vnd.debian.binary-package", NULL }; /* does this match any of the mimetypes we support */ content_type = gs_utils_get_content_type (file, cancellable, error); if (content_type == NULL) return FALSE; if (!g_strv_contains (mimetypes, content_type)) return TRUE; /* exec sync */ argv = g_new0 (gchar *, 5); argv[0] = g_strdup (DPKG_DEB_BINARY); argv[1] = g_strdup ("--showformat=${Package}\\n" "${Version}\\n" "${Installed-Size}\\n" "${Homepage}\\n" "${Description}"); argv[2] = g_strdup ("-W"); argv[3] = g_file_get_path (file); if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, NULL, error)) { gs_utils_error_convert_gio (error); return FALSE; } /* parse output */ tokens = g_strsplit (output, "\n", 0); if (g_strv_length (tokens) < 5) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "dpkg-deb output format incorrect:\n\"%s\"\n", output); return FALSE; } /* create app */ app = gs_app_new (NULL); gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL); gs_app_add_source (app, tokens[0]); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, tokens[0]); gs_app_set_version (app, tokens[1]); gs_app_set_size_installed (app, 1024 * g_ascii_strtoull (tokens[2], NULL, 10)); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, tokens[3]); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, tokens[4]); gs_app_set_kind (app, AS_APP_KIND_GENERIC); gs_app_set_metadata (app, "GnomeSoftware::Creator", gs_plugin_get_name (plugin)); /* multiline text */ str = g_string_new (""); for (i = 5; tokens[i] != NULL; i++) { if (g_strcmp0 (tokens[i], " .") == 0) { if (str->len > 0) g_string_truncate (str, str->len - 1); g_string_append (str, "\n"); continue; } g_strstrip (tokens[i]); g_string_append_printf (str, "%s ", tokens[i]); } if (str->len > 0) g_string_truncate (str, str->len - 1); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, str->str); /* success */ gs_app_list_add (list, app); return TRUE; }
static void refine_app (GsPlugin *plugin, GsApp *app, JsonObject *package, gboolean from_search, GCancellable *cancellable) { g_autofree gchar *macaroon = NULL; g_auto(GStrv) discharges = NULL; const gchar *status, *icon_url, *launch_name = NULL; g_autoptr(GdkPixbuf) icon_pixbuf = NULL; gint64 size = -1; get_macaroon (plugin, &macaroon, &discharges); status = json_object_get_string_member (package, "status"); if (g_strcmp0 (status, "installed") == 0 || g_strcmp0 (status, "active") == 0) { const gchar *update_available; update_available = json_object_has_member (package, "update_available") ? json_object_get_string_member (package, "update_available") : NULL; if (update_available) gs_app_set_state (app, AS_APP_STATE_UPDATABLE); else { if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE) gs_app_set_state (app, AS_APP_STATE_UNKNOWN); gs_app_set_state (app, AS_APP_STATE_INSTALLED); } } else if (g_strcmp0 (status, "not installed") == 0 || g_strcmp0 (status, "available") == 0) { gs_app_set_state (app, AS_APP_STATE_AVAILABLE); } gs_app_set_name (app, GS_APP_QUALITY_HIGHEST, json_object_get_string_member (package, "summary")); gs_app_set_summary (app, GS_APP_QUALITY_HIGHEST, json_object_get_string_member (package, "summary")); gs_app_set_description (app, GS_APP_QUALITY_HIGHEST, json_object_get_string_member (package, "description")); gs_app_set_version (app, json_object_get_string_member (package, "version")); if (json_object_has_member (package, "installed-size")) { size = json_object_get_int_member (package, "installed-size"); if (size > 0) gs_app_set_size_installed (app, (guint64) size); } if (json_object_has_member (package, "download-size")) { size = json_object_get_int_member (package, "download-size"); if (size > 0) gs_app_set_size_download (app, (guint64) size); } gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE); icon_url = json_object_get_string_member (package, "icon"); if (g_str_has_prefix (icon_url, "/")) { g_autofree gchar *icon_data = NULL; gsize icon_data_length; g_autoptr(GError) error = NULL; icon_data = gs_snapd_get_resource (macaroon, discharges, icon_url, &icon_data_length, cancellable, &error); if (icon_data != NULL) { g_autoptr(GdkPixbufLoader) loader = NULL; loader = gdk_pixbuf_loader_new (); gdk_pixbuf_loader_write (loader, (guchar *) icon_data, icon_data_length, NULL); gdk_pixbuf_loader_close (loader, NULL); icon_pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)); } else g_printerr ("Failed to get icon: %s\n", error->message); } else { g_autoptr(SoupMessage) message = NULL; g_autoptr(GdkPixbufLoader) loader = NULL; message = soup_message_new (SOUP_METHOD_GET, icon_url); if (message != NULL) { soup_session_send_message (gs_plugin_get_soup_session (plugin), message); loader = gdk_pixbuf_loader_new (); gdk_pixbuf_loader_write (loader, (guint8 *) message->response_body->data, (gsize) message->response_body->length, NULL); gdk_pixbuf_loader_close (loader, NULL); icon_pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)); } } if (icon_pixbuf) { gs_app_set_pixbuf (app, icon_pixbuf); } else { g_autoptr(AsIcon) icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "package-x-generic"); gs_app_add_icon (app, icon); } if (json_object_has_member (package, "screenshots") && gs_app_get_screenshots (app)->len <= 0) { JsonArray *screenshots; guint i; screenshots = json_object_get_array_member (package, "screenshots"); for (i = 0; i < json_array_get_length (screenshots); i++) { JsonObject *screenshot = json_array_get_object_element (screenshots, i); g_autoptr(AsScreenshot) ss = NULL; g_autoptr(AsImage) image = NULL; ss = as_screenshot_new (); as_screenshot_set_kind (ss, AS_SCREENSHOT_KIND_NORMAL); image = as_image_new (); as_image_set_url (image, json_object_get_string_member (screenshot, "url")); as_image_set_kind (image, AS_IMAGE_KIND_SOURCE); as_screenshot_add_image (ss, image); gs_app_add_screenshot (app, ss); } } if (!from_search) { JsonArray *apps; apps = json_object_get_array_member (package, "apps"); if (apps && json_array_get_length (apps) > 0) launch_name = json_object_get_string_member (json_array_get_object_element (apps, 0), "name"); if (launch_name) gs_app_set_metadata (app, "snap::launch-name", launch_name); else gs_app_add_quirk (app, AS_APP_QUIRK_NOT_LAUNCHABLE); } }
/** * gs_plugin_add_updates: */ gboolean gs_plugin_add_updates (GsPlugin *plugin, GList **list, GCancellable *cancellable, GError **error) { g_autoptr(GList) updates = NULL; GList *l; g_autoptr(GError) error_local = NULL; updates = li_manager_get_update_list (plugin->priv->mgr, &error_local); if (error_local != NULL) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Failed to list updates: %s", error_local->message); return FALSE; } for (l = updates; l != NULL; l = l->next) { LiPkgInfo *old_pki; LiPkgInfo *new_pki; const gchar *cptkind_str; g_autoptr(GsApp) app = NULL; LiUpdateItem *uitem = LI_UPDATE_ITEM (l->data); old_pki = li_update_item_get_installed_pkg (uitem); new_pki = li_update_item_get_available_pkg (uitem); cptkind_str = li_pkg_info_get_component_kind (old_pki); if ((cptkind_str != NULL) && (g_strcmp0 (cptkind_str, "desktop") == 0)) { g_autofree gchar *tmp = NULL; /* type=desktop AppStream components result in a Limba bundle name which has the .desktop stripped away. * We need to re-add it for GNOME Software. * In any other case, the Limba bundle name equals the AppStream ID of the component it contains */ tmp = g_strdup_printf ("%s.desktop", li_pkg_info_get_name (old_pki)); app = gs_app_new (tmp); gs_app_set_kind (app, AS_APP_KIND_DESKTOP); } else { app = gs_app_new (li_pkg_info_get_name (old_pki)); } gs_app_set_management_plugin (app, "Limba"); gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE); gs_app_set_kind (app, AS_APP_KIND_GENERIC); gs_plugin_add_app (list, app); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, li_pkg_info_get_name (old_pki)); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, li_pkg_info_get_name (old_pki)); gs_app_set_version (app, li_pkg_info_get_version (old_pki)); gs_app_set_update_version (app, li_pkg_info_get_version (new_pki)); gs_app_add_source (app, li_pkg_info_get_id (old_pki)); gs_plugin_add_app (list, app); } return TRUE; }