[gnome-software/wip/hughsie/fwupd] Actually download the firmware updates



commit b0e9afd4c6e080b4e6c58e8e0be1ef26cd36ef39
Author: Richard Hughes <richard hughsie com>
Date:   Thu Mar 5 20:31:35 2015 +0000

    Actually download the firmware updates

 src/plugins/gs-plugin-fwupd.c |  165 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 163 insertions(+), 2 deletions(-)
---
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 00a6cd7..543ad13 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -21,6 +21,7 @@
 
 #include <config.h>
 #include <gio/gio.h>
+#include <libsoup/soup.h>
 
 #include "gs-cleanup.h"
 
@@ -34,10 +35,42 @@
 struct GsPluginPrivate {
        gsize                    done_init;
        GDBusProxy              *proxy;
+       GPtrArray               *to_download;
        AsStore                 *store;
+       GPtrArray               *to_ignore;
+       SoupSession             *session;
+       gchar                   *cachedir;
 };
 
 /**
+ * gs_plugin_fwupd_setup_networking:
+ */
+static gboolean
+gs_plugin_fwupd_setup_networking (GsPlugin *plugin, GError **error)
+{
+       /* already set up */
+       if (plugin->priv->session != NULL)
+               return TRUE;
+
+       /* set up a session */
+       plugin->priv->session = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT,
+                                                                   "gnome-software",
+                                                                   SOUP_SESSION_TIMEOUT, 5000,
+                                                                   NULL);
+       if (plugin->priv->session == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "%s: failed to setup networking",
+                            plugin->name);
+               return FALSE;
+       }
+       soup_session_add_feature_by_type (plugin->priv->session,
+                                         SOUP_TYPE_PROXY_RESOLVER_DEFAULT);
+       return TRUE;
+}
+
+/**
  * gs_plugin_get_name:
  */
 const gchar *
@@ -54,6 +87,8 @@ gs_plugin_initialize (GsPlugin *plugin)
 {
        plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
        plugin->priv->store = as_store_new ();
+       plugin->priv->to_download = g_ptr_array_new_with_free_func (g_free);
+       plugin->priv->to_ignore = g_ptr_array_new_with_free_func (g_free);
 }
 
 /**
@@ -62,9 +97,14 @@ gs_plugin_initialize (GsPlugin *plugin)
 void
 gs_plugin_destroy (GsPlugin *plugin)
 {
+       g_free (plugin->priv->cachedir);
        g_object_unref (plugin->priv->store);
+       g_ptr_array_unref (plugin->priv->to_download);
+       g_ptr_array_unref (plugin->priv->to_ignore);
        if (plugin->priv->proxy != NULL)
                g_object_unref (plugin->priv->proxy);
+       if (plugin->priv->session != NULL)
+               g_object_unref (plugin->priv->session);
 }
 
 /**
@@ -73,6 +113,7 @@ gs_plugin_destroy (GsPlugin *plugin)
 static gboolean
 gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
+       gint rc;
        _cleanup_object_unref_ GDBusConnection *conn = NULL;
        conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
        if (conn == NULL)
@@ -88,6 +129,20 @@ gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
        if (plugin->priv->proxy == NULL)
                return FALSE;
 
+       /* create the cache location */
+       plugin->priv->cachedir = g_build_filename (g_get_user_cache_dir (),
+                                                  "gnome-software",
+                                                  "firmware",
+                                                  NULL);
+       rc = g_mkdir_with_parents (plugin->priv->cachedir, 0700);
+       if (rc != 0) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "Could not create firmware cache");
+               return FALSE;
+       }
+
        /* this is hugely wasteful */
        if (!as_store_load (plugin->priv->store,
                            AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM,
@@ -98,6 +153,27 @@ gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 }
 
 /**
+ * gs_plugin_fwupd_add_required_location:
+ */
+static void
+gs_plugin_fwupd_add_required_location (GsPlugin *plugin, const gchar *location)
+{
+       const gchar *tmp;
+       guint i;
+       for (i = 0; i < plugin->priv->to_ignore->len; i++) {
+               tmp = g_ptr_array_index (plugin->priv->to_ignore, i);
+               if (g_strcmp0 (tmp, location) == 0)
+                       return;
+       }
+       for (i = 0; i < plugin->priv->to_download->len; i++) {
+               tmp = g_ptr_array_index (plugin->priv->to_download, i);
+               if (g_strcmp0 (tmp, location) == 0)
+                       return;
+       }
+       g_ptr_array_add (plugin->priv->to_download, g_strdup (location));
+}
+
+/**
  * gs_plugin_fwupd_add_device:
  */
 static gboolean
@@ -112,6 +188,9 @@ gs_plugin_fwupd_add_device (GsPlugin *plugin,
        GPtrArray *releases;
        const gchar *tmp;
        guint i;
+       _cleanup_free_ gchar *basename = NULL;
+       _cleanup_free_ gchar *filename_cache = NULL;
+       _cleanup_free_ gchar *update_location = NULL;
        _cleanup_free_ gchar *update_version = NULL;
        _cleanup_object_unref_ GsApp *app = NULL;
        _cleanup_string_free_ GString *update_desc = NULL;
@@ -140,8 +219,10 @@ gs_plugin_fwupd_add_device (GsPlugin *plugin,
                        continue;
 
                /* get the update text, if it exists */
-               if (update_version == NULL)
+               if (update_version == NULL) {
                        update_version = g_strdup (as_release_get_version (rel));
+                       update_location = g_strdup (as_release_get_location_default (rel));
+               }
                tmp = as_release_get_description (rel, NULL);
                if (tmp == NULL)
                        continue;
@@ -161,6 +242,28 @@ gs_plugin_fwupd_add_device (GsPlugin *plugin,
                return FALSE;
        }
 
+       /* nowhere to download the update from */
+       if (update_location == NULL) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "no location available for firmware");
+               return FALSE;
+       }
+
+       /* does the firmware already exist in the cache? */
+       basename = g_path_get_basename (update_location);
+       filename_cache = g_build_filename (plugin->priv->cachedir, basename, NULL);
+       if (!g_file_test (filename_cache, G_FILE_TEST_EXISTS)) {
+               gs_plugin_fwupd_add_required_location (plugin, update_location);
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "%s does not yet exist, wait patiently",
+                            filename_cache);
+               return FALSE;
+       }
+
        /* remove trailing newline */
        if (update_desc->len > 0)
                g_string_truncate (update_desc, update_desc->len - 1);
@@ -171,7 +274,7 @@ gs_plugin_fwupd_add_device (GsPlugin *plugin,
        gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
        gs_app_set_update_details (app, update_desc->str);
        gs_app_set_update_version (app, update_version);
-//     gs_app_add_source_id (app, package_ids[i]);
+       gs_app_add_source_id (app, filename_cache);
        gs_app_add_source (app, as_app_get_name (item, NULL));
        gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
        gs_plugin_add_app (list, app);
@@ -247,3 +350,61 @@ gs_plugin_add_updates (GsPlugin *plugin,
 
        return TRUE;
 }
+
+/**
+ * gs_plugin_refresh:
+ */
+gboolean
+gs_plugin_refresh (GsPlugin *plugin,
+                  guint cache_age,
+                  GsPluginRefreshFlags flags,
+                  GCancellable *cancellable,
+                  GError **error)
+{
+       const gchar *tmp;
+       guint i;
+
+       /* ensure networking is set up */
+       if (!gs_plugin_fwupd_setup_networking (plugin, error))
+               return FALSE;
+
+       /* download the files to the cachedir */
+       for (i = 0; i < plugin->priv->to_download->len; i++) {
+               guint status_code;
+               _cleanup_error_free_ GError *error_local = NULL;
+               _cleanup_free_ gchar *basename = NULL;
+               _cleanup_free_ gchar *filename_cache = NULL;
+               _cleanup_object_unref_ SoupMessage *msg = NULL;
+
+               tmp = g_ptr_array_index (plugin->priv->to_download, i);
+               basename = g_path_get_basename (tmp);
+               filename_cache = g_build_filename (plugin->priv->cachedir, basename, NULL);
+               g_debug ("downloading %s to %s", tmp, filename_cache);
+
+               /* set sync request */
+               msg = soup_message_new (SOUP_METHOD_GET, tmp);
+               status_code = soup_session_send_message (plugin->priv->session, msg);
+               if (status_code != SOUP_STATUS_OK) {
+                       g_warning ("Failed to download %s, ignoring: %s",
+                                  tmp, soup_status_get_phrase (status_code));
+                       g_ptr_array_remove (plugin->priv->to_download, (gpointer) tmp);
+                       g_ptr_array_add (plugin->priv->to_ignore, g_strdup (tmp));
+                       continue;
+               }
+
+               /* save binary file */
+               if (!g_file_set_contents (filename_cache,
+                                         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;
+}


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