static void snapd_error_convert (GError **perror) { GError *error = perror != NULL ? *perror : NULL; /* not set */ if (error == NULL) return; /* this are allowed for low-level errors */ if (gs_utils_error_convert_gio (perror)) return; /* custom to this plugin */ if (error->domain == SNAPD_ERROR) { switch (error->code) { case SNAPD_ERROR_AUTH_DATA_REQUIRED: error->code = GS_PLUGIN_ERROR_AUTH_REQUIRED; g_free (error->message); error->message = g_strdup ("Requires authentication with @snapd"); break; case SNAPD_ERROR_AUTH_DATA_INVALID: case SNAPD_ERROR_TWO_FACTOR_INVALID: error->code = GS_PLUGIN_ERROR_AUTH_INVALID; break; case SNAPD_ERROR_AUTH_CANCELLED: error->code = GS_PLUGIN_ERROR_CANCELLED; break; case SNAPD_ERROR_CONNECTION_FAILED: case SNAPD_ERROR_WRITE_FAILED: case SNAPD_ERROR_READ_FAILED: case SNAPD_ERROR_BAD_REQUEST: case SNAPD_ERROR_BAD_RESPONSE: case SNAPD_ERROR_PERMISSION_DENIED: case SNAPD_ERROR_FAILED: case SNAPD_ERROR_TERMS_NOT_ACCEPTED: case SNAPD_ERROR_PAYMENT_NOT_SETUP: case SNAPD_ERROR_PAYMENT_DECLINED: case SNAPD_ERROR_ALREADY_INSTALLED: case SNAPD_ERROR_NOT_INSTALLED: case SNAPD_ERROR_NO_UPDATE_AVAILABLE: case SNAPD_ERROR_PASSWORD_POLICY_ERROR: case SNAPD_ERROR_NEEDS_DEVMODE: case SNAPD_ERROR_NEEDS_CLASSIC: case SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM: default: error->code = GS_PLUGIN_ERROR_FAILED; break; } } else { g_warning ("can't reliably fixup error from domain %s", g_quark_to_string (error->domain)); error->code = GS_PLUGIN_ERROR_FAILED; } error->domain = GS_PLUGIN_ERROR; }
static gchar * gs_plugin_fwupd_get_file_checksum (const gchar *filename, GChecksumType checksum_type, GError **error) { gsize len; g_autofree gchar *data = NULL; if (!g_file_get_contents (filename, &data, &len, error)) { gs_utils_error_convert_gio (error); return NULL; } return g_compute_checksum_for_data (checksum_type, (const guchar *)data, len); }
static void gs_plugin_fwupd_error_convert (GError **perror) { GError *error = perror != NULL ? *perror : NULL; /* not set */ if (error == NULL) return; /* already correct */ if (error->domain == GS_PLUGIN_ERROR) return; /* this are allowed for low-level errors */ if (gs_utils_error_convert_gio (perror)) return; /* this are allowed for low-level errors */ if (gs_utils_error_convert_gdbus (perror)) return; /* custom to this plugin */ if (error->domain == FWUPD_ERROR) { switch (error->code) { case FWUPD_ERROR_ALREADY_PENDING: case FWUPD_ERROR_INVALID_FILE: case FWUPD_ERROR_NOT_SUPPORTED: error->code = GS_PLUGIN_ERROR_NOT_SUPPORTED; break; case FWUPD_ERROR_AUTH_FAILED: error->code = GS_PLUGIN_ERROR_AUTH_INVALID; break; case FWUPD_ERROR_SIGNATURE_INVALID: error->code = GS_PLUGIN_ERROR_NO_SECURITY; break; case FWUPD_ERROR_AC_POWER_REQUIRED: error->code = GS_PLUGIN_ERROR_AC_POWER_REQUIRED; break; default: error->code = GS_PLUGIN_ERROR_FAILED; break; } } else { g_warning ("can't reliably fixup error from domain %s", g_quark_to_string (error->domain)); error->code = GS_PLUGIN_ERROR_FAILED; } error->domain = GS_PLUGIN_ERROR; }
static GHashTable * gs_plugin_steam_load_app_manifest (const gchar *fn, GError **error) { GHashTable *manifest = NULL; guint i; guint j; g_autofree gchar *data = NULL; g_auto(GStrv) lines = NULL; /* get file */ if (!g_file_get_contents (fn, &data, NULL, error)) { gs_utils_error_convert_gio (error); return NULL; } /* parse each line */ manifest = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); lines = g_strsplit (data, "\n", -1); for (i = 0; lines[i] != NULL; i++) { gboolean is_key = TRUE; const gchar *tmp = lines[i]; g_autoptr(GString) key = g_string_new (""); g_autoptr(GString) value = g_string_new (""); for (j = 0; tmp[j] != '\0'; j++) { /* alphanum, so either key or value */ if (g_ascii_isalnum (tmp[j])) { g_string_append_c (is_key ? key : value, tmp[j]); continue; } /* first whitespace after the key */ if (g_ascii_isspace (tmp[j]) && key->len > 0) is_key = FALSE; } if (g_getenv ("GS_PLUGIN_STEAM_DEBUG") != NULL) g_debug ("manifest %s=%s", key->str, value->str); if (key->len == 0 || value->len == 0) continue; g_hash_table_insert (manifest, g_strdup (key->str), g_strdup (value->str)); } return manifest; }
gboolean gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(GFile) file = g_file_new_for_path (priv->reposdir); /* watch for changes */ priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, cancellable, error); if (priv->monitor == NULL) { gs_utils_error_convert_gio (error); return FALSE; } g_signal_connect (priv->monitor, "changed", G_CALLBACK (gs_plugin_repos_changed_cb), plugin); /* unconditionally at startup */ return gs_plugin_repos_setup (plugin, cancellable, error); }
gboolean gs_plugin_launch (GsPlugin *plugin, GsApp *app, GCancellable *cancellable, GError **error) { const gchar *gameid; g_autofree gchar *cmdline = NULL; /* only process this app if was created by this plugin */ if (g_strcmp0 (gs_app_get_management_plugin (app), gs_plugin_get_name (plugin)) != 0) return TRUE; /* this is async as steam is a different process: FIXME: use D-Bus */ gameid = gs_app_get_metadata_item (app, "X-Steam-GameID"); cmdline = g_strdup_printf ("steam steam://run/%s", gameid); if (!g_spawn_command_line_sync (cmdline, NULL, NULL, NULL, error)) { gs_utils_error_convert_gio (error); return FALSE; } return TRUE; }
gboolean gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); priv->monitor = pk_offline_get_prepared_monitor (cancellable, error); if (priv->monitor == NULL) { gs_utils_error_convert_gio (error); return FALSE; } g_signal_connect (priv->monitor, "changed", G_CALLBACK (gs_plugin_systemd_updates_changed_cb), plugin); /* check if we have permission to trigger the update */ priv->permission = gs_utils_get_permission ( "org.freedesktop.packagekit.trigger-offline-update"); if (priv->permission != NULL) { g_signal_connect (priv->permission, "notify", G_CALLBACK (gs_plugin_systemd_updates_permission_cb), plugin); } return TRUE; }
static gboolean gs_plugin_repos_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autoptr(GDir) dir = NULL; const gchar *fn; /* already valid */ if (priv->valid) return TRUE; /* clear existing */ g_hash_table_remove_all (priv->urls); /* search all files */ dir = g_dir_open (priv->reposdir, 0, error); if (dir == NULL) { gs_utils_error_convert_gio (error); return FALSE; } while ((fn = g_dir_read_name (dir)) != NULL) { g_autofree gchar *filename = NULL; g_auto(GStrv) groups = NULL; g_autoptr(GKeyFile) kf = g_key_file_new (); guint i; /* not a repo */ if (!g_str_has_suffix (fn, ".repo")) continue; /* load file */ filename = g_build_filename (priv->reposdir, fn, NULL); if (!g_key_file_load_from_file (kf, filename, G_KEY_FILE_NONE, error)) { gs_utils_error_convert_gio (error); return FALSE; } /* we can have multiple repos in one file */ groups = g_key_file_get_groups (kf, NULL); for (i = 0; groups[i] != NULL; i++) { g_autofree gchar *tmp = NULL; tmp = g_key_file_get_string (kf, groups[i], "baseurl", NULL); if (tmp != NULL) { g_hash_table_insert (priv->urls, g_strdup (groups[i]), g_strdup (tmp)); continue; } tmp = g_key_file_get_string (kf, groups[i], "metalink", NULL); if (tmp != NULL) { g_hash_table_insert (priv->urls, g_strdup (groups[i]), g_strdup (tmp)); continue; } } } /* success */ priv->valid = TRUE; return TRUE; }
static gboolean gs_plugin_steam_update_store_app (GsPlugin *plugin, AsStore *store, GHashTable *app, GError **error) { const gchar *name; GVariant *tmp; guint32 gameid; gchar *app_id; g_autofree gchar *cache_basename = NULL; g_autofree gchar *cache_fn = NULL; g_autofree gchar *gameid_str = NULL; g_autofree gchar *html = NULL; g_autofree gchar *uri = NULL; g_autoptr(AsApp) item = NULL; /* this is the key */ tmp = g_hash_table_lookup (app, "gameid"); if (tmp == NULL) return TRUE; gameid = g_variant_get_uint32 (tmp); /* valve use the name as the application ID, not the gameid */ tmp = g_hash_table_lookup (app, "name"); if (tmp == NULL) return TRUE; name = g_variant_get_string (tmp, NULL); app_id = g_strdup_printf ("%s.desktop", name); /* already exists */ if (as_store_get_app_by_id (store, app_id) != NULL) { g_debug ("already exists %" G_GUINT32_FORMAT ", skipping", gameid); return TRUE; } /* create application with the gameid as the key */ g_debug ("parsing steam %" G_GUINT32_FORMAT, gameid); item = as_app_new (); as_app_set_kind (item, AS_APP_KIND_DESKTOP); as_app_set_project_license (item, "Steam"); as_app_set_id (item, app_id); as_app_set_name (item, NULL, name); as_app_add_category (item, "Game"); as_app_add_kudo_kind (item, AS_KUDO_KIND_MODERN_TOOLKIT); as_app_set_comment (item, NULL, "Available on Steam"); /* this is for the GNOME Software plugin */ gameid_str = g_strdup_printf ("%" G_GUINT32_FORMAT, gameid); as_app_add_metadata (item, "X-Steam-GameID", gameid_str); as_app_add_metadata (item, "GnomeSoftware::Plugin", "steam"); /* ban certains apps based on the name */ if (g_strstr_len (name, -1, "Dedicated Server") != NULL) as_app_add_veto (item, "Dedicated Server"); /* oslist */ tmp = g_hash_table_lookup (app, "oslist"); if (tmp == NULL) { as_app_add_veto (item, "No operating systems listed"); } else if (g_strstr_len (g_variant_get_string (tmp, NULL), -1, "linux") == NULL) { as_app_add_veto (item, "No Linux support"); } /* url: homepage */ tmp = g_hash_table_lookup (app, "homepage"); if (tmp != NULL) as_app_add_url (item, AS_URL_KIND_HOMEPAGE, g_variant_get_string (tmp, NULL)); /* developer name */ tmp = g_hash_table_lookup (app, "developer"); if (tmp != NULL) as_app_set_developer_name (item, NULL, g_variant_get_string (tmp, NULL)); /* type */ tmp = g_hash_table_lookup (app, "type"); if (tmp != NULL) { const gchar *kind = g_variant_get_string (tmp, NULL); if (g_strcmp0 (kind, "DLC") == 0 || g_strcmp0 (kind, "Config") == 0 || g_strcmp0 (kind, "Tool") == 0) as_app_add_veto (item, "type is %s", kind); } /* don't bother saving apps with failures */ if (as_app_get_vetos(item)->len > 0) return TRUE; /* icons */ tmp = g_hash_table_lookup (app, "clienticns"); if (tmp != NULL) { g_autoptr(GError) error_local = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.icns", gameid, g_variant_get_string (tmp, NULL)); if (!gs_plugin_steam_download_icon (plugin, item, ic_uri, &error_local)) { g_warning ("Failed to parse clienticns: %s", error_local->message); } } /* try clienticon */ if (as_app_get_icons(item)->len == 0) { tmp = g_hash_table_lookup (app, "clienticon"); if (tmp != NULL) { g_autoptr(GError) error_local = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.ico", gameid, g_variant_get_string (tmp, NULL)); if (!gs_plugin_steam_download_icon (plugin, item, ic_uri, &error_local)) { g_warning ("Failed to parse clienticon: %s", error_local->message); } } } /* fall back to a resized logo */ if (as_app_get_icons(item)->len == 0) { tmp = g_hash_table_lookup (app, "logo"); if (tmp != NULL) { AsIcon *icon = NULL; g_autofree gchar *ic_uri = NULL; ic_uri = g_strdup_printf ("http://cdn.akamai.steamstatic.com/steamcommunity/public/images/apps/%" G_GUINT32_FORMAT "/%s.jpg", gameid, g_variant_get_string (tmp, NULL)); icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_REMOTE); as_icon_set_url (icon, ic_uri); as_app_add_icon (item, icon); } } /* size */ tmp = g_hash_table_lookup (app, "maxsize"); if (tmp != NULL) { /* string when over 16Gb... :/ */ if (g_strcmp0 (g_variant_get_type_string (tmp), "u") == 0) { g_autofree gchar *val = NULL; val = g_strdup_printf ("%" G_GUINT32_FORMAT, g_variant_get_uint32 (tmp)); as_app_add_metadata (item, "X-Steam-Size", val); } else { as_app_add_metadata (item, "X-Steam-Size", g_variant_get_string (tmp, NULL)); } } /* download page from the store */ cache_basename = g_strdup_printf ("%s.html", gameid_str); cache_fn = gs_utils_get_cache_filename ("steam", cache_basename, GS_UTILS_CACHE_FLAG_WRITEABLE, error); if (cache_fn == NULL) return FALSE; if (!g_file_test (cache_fn, G_FILE_TEST_EXISTS)) { g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin)); uri = g_strdup_printf ("http://store.steampowered.com/app/%s/", gameid_str); if (!gs_plugin_download_file (plugin, app_dl, uri, cache_fn, NULL, /* GCancellable */ error)) return FALSE; } /* get screenshots and descriptions */ if (!g_file_get_contents (cache_fn, &html, NULL, error)) { gs_utils_error_convert_gio (error); return FALSE; } if (!gs_plugin_steam_update_screenshots (item, html, error)) return FALSE; if (!gs_plugin_steam_update_description (item, html, error)) return FALSE; /* add */ as_store_add_app (store, item); return TRUE; }
static gboolean gs_plugin_steam_download_icon (GsPlugin *plugin, AsApp *app, const gchar *uri, GError **error) { gsize data_len; g_autofree gchar *cache_basename = NULL; g_autofree gchar *cache_fn = NULL; g_autofree gchar *cache_png = NULL; g_autofree gchar *data = NULL; g_autoptr(AsIcon) icon = NULL; g_autoptr(GdkPixbuf) pb = NULL; /* download icons from the cdn */ cache_basename = g_path_get_basename (uri); cache_fn = gs_utils_get_cache_filename ("steam", cache_basename, GS_UTILS_CACHE_FLAG_NONE, error); if (cache_fn == NULL) return FALSE; if (g_file_test (cache_fn, G_FILE_TEST_EXISTS)) { if (!g_file_get_contents (cache_fn, &data, &data_len, error)) { gs_utils_error_convert_gio (error); return FALSE; } } else { if (!gs_mkdir_parent (cache_fn, error)) return FALSE; if (!gs_plugin_download_file (plugin, NULL, /* GsApp */ uri, cache_fn, NULL, /* GCancellable */ error)) return FALSE; } /* load the icon as large as possible */ pb = gdk_pixbuf_new_from_file (cache_fn, error); if (pb == NULL) { gs_utils_error_convert_gdk_pixbuf (error); return FALSE; } /* too small? */ if (gdk_pixbuf_get_width (pb) < 48 || gdk_pixbuf_get_height (pb) < 48) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_INVALID_FORMAT, "icon is too small %ix%i", gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb)); return FALSE; } /* save to cache */ memcpy (cache_basename + 40, ".png\0", 5); cache_png = gs_utils_get_cache_filename ("steam", cache_basename, GS_UTILS_CACHE_FLAG_WRITEABLE, error); if (cache_png == NULL) return FALSE; if (!gdk_pixbuf_save (pb, cache_png, "png", error, NULL)) { gs_utils_error_convert_gdk_pixbuf (error); return FALSE; } /* add an icon */ icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_LOCAL); as_icon_set_filename (icon, cache_png); as_app_add_icon (app, icon); return TRUE; }
static GPtrArray * gs_plugin_steam_parse_appinfo_file (const gchar *filename, GError **error) { GPtrArray *apps; GHashTable *app = NULL; const gchar *tmp; guint8 *data = NULL; gsize data_len = 0; guint i = 0; gboolean debug = g_getenv ("GS_PLUGIN_STEAM_DEBUG") != NULL; /* load file */ if (!g_file_get_contents (filename, (gchar **) &data, &data_len, error)) { gs_utils_error_convert_gio (error); return NULL; } /* a GPtrArray of GHashTable */ apps = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref); /* find the first application and avoid header */ gs_plugin_steam_find_next_sync_point (data, data_len, &i); for (i = i + 1; i < data_len; i++) { if (debug) g_debug ("%04x {0x%02x} %s", i, data[i], gs_plugin_steam_token_kind_to_str (data[i])); if (data[i] == GS_PLUGIN_STEAM_TOKEN_START) { /* this is a new application/game */ if (data[i+1] == 0x02) { /* reset */ app = gs_plugin_steam_add_app (apps); i++; continue; } /* new group */ if (g_ascii_isprint (data[i+1])) { tmp = gs_plugin_steam_consume_string (data, data_len, &i); if (debug) g_debug ("[%s] {", tmp); continue; } /* something went wrong */ if (debug) g_debug ("CORRUPTION DETECTED"); gs_plugin_steam_find_next_sync_point (data, data_len, &i); continue; } if (data[i] == GS_PLUGIN_STEAM_TOKEN_END) { if (debug) g_debug ("}"); continue; } if (data[i] == GS_PLUGIN_STEAM_TOKEN_STRING) { const gchar *value; tmp = gs_plugin_steam_consume_string (data, data_len, &i); value = gs_plugin_steam_consume_string (data, data_len, &i); if (debug) g_debug ("\t%s=%s", tmp, value); if (tmp != NULL && value != NULL) { if (g_hash_table_lookup (app, tmp) != NULL) continue; g_hash_table_insert (app, g_strdup (tmp), g_variant_new_string (value)); } continue; } if (data[i] == GS_PLUGIN_STEAM_TOKEN_INTEGER) { guint32 value; tmp = gs_plugin_steam_consume_string (data, data_len, &i); value = gs_plugin_steam_consume_uint32 (data, data_len, &i); if (debug) g_debug ("\t%s=%u", tmp, value); if (tmp != NULL) { if (g_hash_table_lookup (app, tmp) != NULL) continue; g_hash_table_insert (app, g_strdup (tmp), g_variant_new_uint32 (value)); } continue; } } return apps; }
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; }
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; }