[gnome-software] Add gs_plugin_download_data()



commit 7fb0a391ed7245c2c4344adeff95ffe7ce3da546
Author: Richard Hughes <richard hughsie com>
Date:   Tue Apr 12 11:39:19 2016 +0100

    Add gs_plugin_download_data()
    
    This allows us to do the progress changed logic in one place.

 src/gs-plugin.c                          |  137 ++++++++++++++++++++++++++++++
 src/gs-plugin.h                          |   11 +++
 src/plugins/gs-plugin-fwupd.c            |   54 +++++--------
 src/plugins/gs-plugin-shell-extensions.c |   34 +++----
 src/plugins/gs-plugin-steam.c            |   74 ++++-------------
 5 files changed, 199 insertions(+), 111 deletions(-)
---
diff --git a/src/gs-plugin.c b/src/gs-plugin.c
index ebb85b0..3957dad 100644
--- a/src/gs-plugin.c
+++ b/src/gs-plugin.c
@@ -391,4 +391,141 @@ gs_plugin_updates_changed (GsPlugin *plugin)
        g_idle_add (gs_plugin_updates_changed_cb, plugin);
 }
 
+typedef struct {
+       GsPlugin        *plugin;
+       GsApp           *app;
+       GCancellable    *cancellable;
+} GsPluginDownloadHelper;
+
+/**
+ * gs_plugin_download_chunk_cb:
+ **/
+static void
+gs_plugin_download_chunk_cb (SoupMessage *msg, SoupBuffer *chunk,
+                            GsPluginDownloadHelper *helper)
+{
+       guint percentage;
+       goffset header_size;
+       goffset body_length;
+
+       /* cancelled? */
+       if (g_cancellable_is_cancelled (helper->cancellable)) {
+               g_debug ("cancelling download of %s",
+                        gs_app_get_id (helper->app));
+               soup_session_cancel_message (helper->plugin->soup_session,
+                                            msg,
+                                            SOUP_STATUS_CANCELLED);
+               return;
+       }
+
+       /* if it's returning "Found" or an error, ignore the percentage */
+       if (msg->status_code != SOUP_STATUS_OK) {
+               g_debug ("ignoring status code %i (%s)",
+                        msg->status_code, msg->reason_phrase);
+               return;
+       }
+
+       /* get data */
+       body_length = msg->response_body->length;
+       header_size = soup_message_headers_get_content_length (msg->response_headers);
+
+       /* size is not known */
+       if (header_size < body_length)
+               return;
+
+       /* calulate percentage */
+       percentage = (100 * body_length) / header_size;
+       g_debug ("%s progress: %i%%", gs_app_get_id (helper->app), percentage);
+       gs_app_set_progress (helper->app, percentage);
+       gs_plugin_status_update (helper->plugin,
+                                helper->app,
+                                GS_PLUGIN_STATUS_DOWNLOADING);
+}
+
+/**
+ * gs_plugin_download_data:
+ */
+GBytes *
+gs_plugin_download_data (GsPlugin *plugin,
+                        GsApp *app,
+                        const gchar *uri,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+       GsPluginDownloadHelper helper;
+       guint status_code;
+       g_autoptr(SoupMessage) msg = NULL;
+
+       g_debug ("downloading %s from %s", uri, plugin->name);
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       if (app != NULL) {
+               helper.plugin = plugin;
+               helper.app = app;
+               helper.cancellable = cancellable;
+               g_signal_connect (msg, "got-chunk",
+                                 G_CALLBACK (gs_plugin_download_chunk_cb),
+                                 &helper);
+       }
+       status_code = soup_session_send_message (plugin->soup_session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "failed to get shell extensions: %s",
+                            msg->response_body->data);
+               return NULL;
+       }
+       return g_bytes_new (msg->response_body->data,
+                           msg->response_body->length);
+}
+
+/**
+ * gs_plugin_download_file:
+ */
+gboolean
+gs_plugin_download_file (GsPlugin *plugin,
+                        GsApp *app,
+                        const gchar *uri,
+                        const gchar *filename,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+       GsPluginDownloadHelper helper;
+       guint status_code;
+       g_autoptr(GError) error_local = NULL;
+       g_autoptr(SoupMessage) msg = NULL;
+
+       g_debug ("downloading %s to %s from %s", uri, filename, plugin->name);
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       if (app != NULL) {
+               helper.plugin = plugin;
+               helper.app = app;
+               helper.cancellable = cancellable;
+               g_signal_connect (msg, "got-chunk",
+                                 G_CALLBACK (gs_plugin_download_chunk_cb),
+                                 &helper);
+       }
+       status_code = soup_session_send_message (plugin->soup_session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "failed to get shell extensions: %s",
+                            msg->response_body->data);
+               return FALSE;
+       }
+       if (!g_file_set_contents (filename,
+                                 msg->response_body->data,
+                                 msg->response_body->length,
+                                 &error_local)) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed to save firmware: %s",
+                            error_local->message);
+               return FALSE;
+       }
+       return TRUE;
+}
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index 814cd43..26c06c9 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -205,6 +205,17 @@ void                gs_plugin_initialize                   (GsPlugin       *plugin);
 void            gs_plugin_destroy                      (GsPlugin       *plugin);
 void            gs_plugin_set_enabled                  (GsPlugin       *plugin,
                                                         gboolean        enabled);
+GBytes         *gs_plugin_download_data                (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        const gchar    *uri,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+gboolean        gs_plugin_download_file                (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        const gchar    *uri,
+                                                        const gchar    *filename,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_check_distro_id              (GsPlugin       *plugin,
                                                         const gchar    *distro_id);
 void            gs_plugin_add_app                      (GList          **list,
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 1a137c0..dd5a120 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -455,16 +455,15 @@ gs_plugin_fwupd_check_lvfs_metadata (GsPlugin *plugin,
                                     GCancellable *cancellable,
                                     GError **error)
 {
-       guint status_code;
        g_autoptr(GError) error_local = NULL;
        g_autofree gchar *basename_data = NULL;
        g_autofree gchar *cache_fn_data = NULL;
        g_autofree gchar *checksum = NULL;
        g_autofree gchar *url_data = NULL;
        g_autofree gchar *url_sig = NULL;
+       g_autoptr(GBytes) data = NULL;
        g_autoptr(GKeyFile) config = NULL;
-       g_autoptr(SoupMessage) msg_data = NULL;
-       g_autoptr(SoupMessage) msg_sig = NULL;
+       g_autoptr(GsApp) app_dl = gs_app_new (plugin->name);
 
        /* read config file */
        config = g_key_file_new ();
@@ -491,18 +490,18 @@ gs_plugin_fwupd_check_lvfs_metadata (GsPlugin *plugin,
 
        /* download the signature first, it's smaller */
        url_sig = g_strdup_printf ("%s.asc", url_data);
-       msg_sig = soup_message_new (SOUP_METHOD_GET, url_sig);
-       status_code = soup_session_send_message (plugin->soup_session, msg_sig);
-       if (status_code != SOUP_STATUS_OK) {
-               g_warning ("Failed to download %s, ignoring: %s",
-                          url_sig, soup_status_get_phrase (status_code));
-               return TRUE;
-       }
+       data = gs_plugin_download_data (plugin,
+                                       app_dl,
+                                       url_sig,
+                                       cancellable,
+                                       error);
+       if (data == NULL)
+               return FALSE;
 
        /* is the signature hash the same as we had before? */
        checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1,
-                                               (const guchar *) msg_sig->response_body->data,
-                                               msg_sig->response_body->length);
+                                               (const guchar *) g_bytes_get_data (data, NULL),
+                                               g_bytes_get_size (data));
        if (g_strcmp0 (checksum, plugin->priv->lvfs_sig_hash) == 0) {
                g_debug ("signature of %s is unchanged", url_sig);
                return TRUE;
@@ -511,8 +510,8 @@ gs_plugin_fwupd_check_lvfs_metadata (GsPlugin *plugin,
        /* save to a file */
        g_debug ("saving new LVFS signature to %s:", plugin->priv->lvfs_sig_fn);
        if (!g_file_set_contents (plugin->priv->lvfs_sig_fn,
-                                 msg_sig->response_body->data,
-                                 msg_sig->response_body->length,
+                                 g_bytes_get_data (data, NULL),
+                                 g_bytes_get_size (data),
                                  &error_local)) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
@@ -526,30 +525,17 @@ gs_plugin_fwupd_check_lvfs_metadata (GsPlugin *plugin,
        g_free (plugin->priv->lvfs_sig_hash);
        plugin->priv->lvfs_sig_hash = g_strdup (checksum);
 
-       /* download the payload */
-       msg_data = soup_message_new (SOUP_METHOD_GET, url_data);
-       status_code = soup_session_send_message (plugin->soup_session, msg_data);
-       if (status_code != SOUP_STATUS_OK) {
-               g_warning ("Failed to download %s, ignoring: %s",
-                          url_data, soup_status_get_phrase (status_code));
-               return TRUE;
-       }
-
-       /* save to a file */
+       /* download the payload and save to file */
        basename_data = g_path_get_basename (url_data);
        cache_fn_data = g_build_filename (plugin->priv->cachedir, basename_data, NULL);
        g_debug ("saving new LVFS data to %s:", cache_fn_data);
-       if (!g_file_set_contents (cache_fn_data,
-                                 msg_data->response_body->data,
-                                 msg_data->response_body->length,
-                                 &error_local)) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "Failed to save firmware: %s",
-                            error_local->message);
+       if (!gs_plugin_download_file (plugin,
+                                     app_dl,
+                                     url_data,
+                                     cache_fn_data,
+                                     cancellable,
+                                     error))
                return FALSE;
-       }
 
        /* phew, lets send all this to fwupd */
        if (!fwupd_client_update_metadata (plugin->priv->client,
diff --git a/src/plugins/gs-plugin-shell-extensions.c b/src/plugins/gs-plugin-shell-extensions.c
index 924af4e..0651fbb 100644
--- a/src/plugins/gs-plugin-shell-extensions.c
+++ b/src/plugins/gs-plugin-shell-extensions.c
@@ -574,16 +574,16 @@ gs_plugin_shell_extensions_parse_apps (GsPlugin *plugin,
 static GPtrArray *
 gs_plugin_shell_extensions_get_apps (GsPlugin *plugin,
                                     guint cache_age,
+                                    GCancellable *cancellable,
                                     GError **error)
 {
        GPtrArray *apps;
-       guint status_code;
        g_autofree gchar *cachedir = NULL;
        g_autofree gchar *cachefn = NULL;
-       g_autofree gchar *data = NULL;
        g_autofree gchar *uri = NULL;
        g_autoptr(GFile) cachefn_file = NULL;
-       g_autoptr(SoupMessage) msg = NULL;
+       g_autoptr(GBytes) data = NULL;
+       g_autoptr(GsApp) dummy = gs_app_new (plugin->name);
 
        /* look in the cache */
        cachedir = gs_utils_get_cachedir ("extensions", error);
@@ -607,36 +607,29 @@ gs_plugin_shell_extensions_get_apps (GsPlugin *plugin,
                               "&page=1&n_per_page=1000",
                               SHELL_EXTENSIONS_API_URI,
                               plugin->priv->shell_version);
-       msg = soup_message_new (SOUP_METHOD_GET, uri);
-       status_code = soup_session_send_message (plugin->soup_session, msg);
-       if (status_code != SOUP_STATUS_OK) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "failed to get shell extensions: %s",
-                            msg->response_body->data);
+       data = gs_plugin_download_data (plugin, dummy, uri, cancellable, error);
+       if (data == NULL)
                return NULL;
-       }
        apps = gs_plugin_shell_extensions_parse_apps (plugin,
-                                                     msg->response_body->data,
-                                                     msg->response_body->length,
+                                                     g_bytes_get_data (data, NULL),
+                                                     g_bytes_get_size (data),
                                                      error);
        if (apps == NULL) {
-               guint len = msg->response_body->length;
+               guint len = g_bytes_get_size (data);
                g_autofree gchar *tmp = NULL;
 
                /* truncate the string if long */
                if (len > 100)
                        len = 100;
-               tmp = g_strndup (msg->response_body->data, len);
+               tmp = g_strndup (g_bytes_get_data (data, NULL), len);
                g_prefix_error (error, "Failed to parse '%s': ", tmp);
                return NULL;
        }
 
        /* save to the cache */
        if (!g_file_set_contents (cachefn,
-                                 msg->response_body->data,
-                                 msg->response_body->length,
+                                 g_bytes_get_data (data, NULL),
+                                 g_bytes_get_size (data),
                                  error))
                return NULL;
 
@@ -680,7 +673,10 @@ gs_plugin_refresh (GsPlugin *plugin,
        }
 
        /* get data */
-       apps = gs_plugin_shell_extensions_get_apps (plugin, cache_age, error);
+       apps = gs_plugin_shell_extensions_get_apps (plugin,
+                                                   cache_age,
+                                                   cancellable,
+                                                   error);
        if (apps == NULL)
                return FALSE;
 
diff --git a/src/plugins/gs-plugin-steam.c b/src/plugins/gs-plugin-steam.c
index b1dc8b1..570353b 100644
--- a/src/plugins/gs-plugin-steam.c
+++ b/src/plugins/gs-plugin-steam.c
@@ -38,50 +38,6 @@ gs_plugin_get_name (void)
 }
 
 /**
- * gs_plugin_steam_html_download:
- */
-static gboolean
-gs_plugin_steam_html_download (GsPlugin *plugin,
-                              const gchar *uri,
-                              gchar **data,
-                              gsize *data_len,
-                              GError **error)
-{
-       guint status_code;
-       g_autoptr(GInputStream) stream = NULL;
-       g_autoptr(SoupMessage) msg = NULL;
-
-       /* create the GET data */
-       msg = soup_message_new (SOUP_METHOD_GET, uri);
-       if (msg == NULL) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "%s is not a valid URL", uri);
-               return FALSE;
-       }
-
-       /* set sync request */
-       status_code = soup_session_send_message (plugin->soup_session, msg);
-       if (status_code != SOUP_STATUS_OK) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "Failed to download icon %s: %s",
-                            uri, soup_status_get_phrase (status_code));
-               return FALSE;
-       }
-
-       /* return data */
-       if (data != NULL)
-               *data = g_memdup (msg->response_body->data,
-                                 msg->response_body->length);
-       if (data_len != NULL)
-               *data_len = msg->response_body->length;
-       return TRUE;
-}
-
-/**
  * gs_plugin_order_after:
  */
 const gchar **
@@ -469,15 +425,14 @@ gs_plugin_steam_download_icon (GsPlugin *plugin,
                if (!g_file_get_contents (cache_fn, &data, &data_len, error))
                        return FALSE;
        } else {
-               if (!gs_plugin_steam_html_download (plugin,
-                                                   uri,
-                                                   &data,
-                                                   &data_len,
-                                                   error))
-                       return FALSE;
                if (!gs_mkdir_parent (cache_fn, error))
                        return FALSE;
-               if (!g_file_set_contents (cache_fn, data, data_len, error))
+               if (!gs_plugin_download_file (plugin,
+                                             NULL, /* GsApp */
+                                             uri,
+                                             cache_fn,
+                                             NULL, /* GCancellable */
+                                             error))
                        return FALSE;
        }
 
@@ -668,18 +623,21 @@ gs_plugin_steam_update_store_app (GsPlugin *plugin,
        if (cachedir == NULL)
                return FALSE;
        cache_fn = g_build_filename (cachedir, cache_basename, NULL);
-       if (g_file_test (cache_fn, G_FILE_TEST_EXISTS)) {
-               if (!g_file_get_contents (cache_fn, &html, NULL, error))
-                       return FALSE;
-       } else {
+       if (!g_file_test (cache_fn, G_FILE_TEST_EXISTS)) {
+               g_autoptr(GsApp) app_dl = gs_app_new (plugin->name);
                uri = g_strdup_printf ("http://store.steampowered.com/app/%s/";, gameid_str);
-               if (!gs_plugin_steam_html_download (plugin, uri, &html, NULL, error))
-                       return FALSE;
-               if (!g_file_set_contents (cache_fn, html, -1, error))
+               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))
+               return FALSE;
        if (!gs_plugin_steam_update_screenshots (item, html, error))
                return FALSE;
        if (!gs_plugin_steam_update_description (item, html, error))


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