[gnome-software/wip/hughsie/fwupd] Support triggering firmware upgrades



commit 967f7b693ace183075bc532bf8f9ceef2a94adeb
Author: Richard Hughes <richard hughsie com>
Date:   Thu Mar 5 21:05:54 2015 +0000

    Support triggering firmware upgrades

 src/gs-plugin-loader.c        |    5 ++
 src/gs-plugin-loader.h        |    1 +
 src/gs-plugin.h               |    4 ++
 src/gs-shell-updates.c        |   37 ++++++++++++++++-
 src/gs-update-list.c          |   17 +++++++
 src/gs-update-list.h          |    1 +
 src/plugins/gs-plugin-fwupd.c |   93 +++++++++++++++++++++++++++++++++++++++-
 7 files changed, 154 insertions(+), 4 deletions(-)
---
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 5900fab..044ef2f 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -2718,6 +2718,11 @@ gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
                state->state_success = AS_APP_STATE_UNKNOWN;
                state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
+       case GS_PLUGIN_LOADER_ACTION_UPGRADE:
+               state->function_name = "gs_plugin_app_upgrade";
+               state->state_success = AS_APP_STATE_UNKNOWN;
+               state->state_failure = AS_APP_STATE_UNKNOWN;
+               break;
        default:
                g_assert_not_reached ();
                break;
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 1146e81..579d6d6 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -67,6 +67,7 @@ typedef enum {
        GS_PLUGIN_LOADER_ACTION_INSTALL,
        GS_PLUGIN_LOADER_ACTION_REMOVE,
        GS_PLUGIN_LOADER_ACTION_SET_RATING,
+       GS_PLUGIN_LOADER_ACTION_UPGRADE,
        GS_PLUGIN_LOADER_ACTION_LAST
 } GsPluginLoaderAction;
 
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index 94c5268..751d01a 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -247,6 +247,10 @@ gboolean    gs_plugin_app_set_rating               (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gboolean        gs_plugin_app_upgrade                  (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_refresh                      (GsPlugin       *plugin,
                                                         guint           cache_age,
                                                         GsPluginRefreshFlags flags,
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 51407b1..314dee6 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -839,11 +839,46 @@ gs_offline_updates_cancel (void)
                g_warning ("failed to cancel the offline update: %s", error->message);
 }
 
+/**
+ * gs_shell_updates_upgrade_cb:
+ **/
+static void
+gs_shell_updates_upgrade_cb (GsPluginLoader *plugin_loader,
+                            GAsyncResult *res,
+                            GsShellUpdates *shell_updates)
+{
+       _cleanup_error_free_ GError *error = NULL;
+
+       /* get the results */
+       if (!gs_plugin_loader_app_action_finish (plugin_loader, res, &error))
+               g_warning ("Failed to upgrade: %s", error->message);
+}
+
 static void
 gs_shell_updates_button_update_all_cb (GtkButton      *button,
-                                      GsShellUpdates *updates)
+                                      GsShellUpdates *shell_updates)
 {
+       GsApp *app;
+       GsShellUpdatesPrivate *priv = shell_updates->priv;
+       guint i;
        _cleanup_error_free_ GError *error = NULL;
+       _cleanup_ptrarray_unref_ GPtrArray *apps = NULL;
+
+       /* any firmware updates? */
+       apps = gs_update_list_get_apps (GS_UPDATE_LIST (priv->list_box_updates));
+       for (i = 0; i < apps->len; i++) {
+               app = g_ptr_array_index (apps, i);
+               if (gs_app_get_id_kind (app) != AS_ID_KIND_FIRMWARE)
+                       continue;
+               gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                                  app,
+                                                  GS_PLUGIN_LOADER_ACTION_UPGRADE,
+                                                  priv->cancellable,
+                                                  (GAsyncReadyCallback) gs_shell_updates_upgrade_cb,
+                                                  shell_updates);
+       }
+
+       /* normal packages */
        if (!pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, NULL, &error)) {
                g_warning ("failed to trigger an offline update: %s", error->message);
                return;
diff --git a/src/gs-update-list.c b/src/gs-update-list.c
index ba05632..a900bce 100644
--- a/src/gs-update-list.c
+++ b/src/gs-update-list.c
@@ -56,6 +56,23 @@ gs_update_list_add_app (GsUpdateList *update_list,
        gtk_widget_show (app_row);
 }
 
+GPtrArray *
+gs_update_list_get_apps (GsUpdateList *update_list)
+{
+       GList *l;
+       GPtrArray *apps;
+       GsAppRow *app_row;
+       _cleanup_list_free_ GList *children = NULL;
+
+       apps = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+       children = gtk_container_get_children (GTK_CONTAINER (update_list));
+       for (l = children; l != NULL; l = l->next) {
+               app_row = GS_APP_ROW (l->data);
+               g_ptr_array_add (apps, g_object_ref (gs_app_row_get_app (app_row)));
+       }
+       return apps;
+}
+
 static gboolean
 is_addon_id_kind (GsApp *app)
 {
diff --git a/src/gs-update-list.h b/src/gs-update-list.h
index ff2611b..aa954aa 100644
--- a/src/gs-update-list.h
+++ b/src/gs-update-list.h
@@ -53,6 +53,7 @@ GType          gs_update_list_get_type        (void);
 GtkWidget      *gs_update_list_new             (void);
 void            gs_update_list_add_app         (GsUpdateList   *update_list,
                                                 GsApp          *app);
+GPtrArray      *gs_update_list_get_apps        (GsUpdateList   *update_list);
 
 G_END_DECLS
 
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 543ad13..462b382 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -20,14 +20,17 @@
  */
 
 #include <config.h>
+
+#include <appstream-glib.h>
+#include <fcntl.h>
 #include <gio/gio.h>
+#include <gio/gunixfdlist.h>
 #include <libsoup/soup.h>
 
-#include "gs-cleanup.h"
-
-#include <appstream-glib.h>
 #include <gs-plugin.h>
 
+#include "gs-cleanup.h"
+
 #define FWUPD_DBUS_PATH                        "/"
 #define FWUPD_DBUS_SERVICE             "org.freedesktop.fwupd"
 #define FWUPD_DBUS_INTERFACE           "org.freedesktop.fwupd"
@@ -178,6 +181,7 @@ gs_plugin_fwupd_add_required_location (GsPlugin *plugin, const gchar *location)
  */
 static gboolean
 gs_plugin_fwupd_add_device (GsPlugin *plugin,
+                           const gchar *device_id,
                            const gchar *guid,
                            const gchar *version,
                            GList **list,
@@ -277,6 +281,7 @@ gs_plugin_fwupd_add_device (GsPlugin *plugin,
        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_app_set_metadata (app, "fwupd::DeviceID", device_id);
        gs_plugin_add_app (list, app);
        return TRUE;
 }
@@ -336,6 +341,7 @@ gs_plugin_add_updates (GsPlugin *plugin,
                if (guid != NULL && version != NULL) {
                        _cleanup_error_free_ GError *error_local = NULL;
                        if (!gs_plugin_fwupd_add_device (plugin,
+                                                        id,
                                                         guid,
                                                         version,
                                                         list,
@@ -408,3 +414,84 @@ gs_plugin_refresh (GsPlugin *plugin,
 
        return TRUE;
 }
+
+/**
+ * gs_plugin_app_upgrade:
+ */
+gboolean
+gs_plugin_app_upgrade (GsPlugin *plugin,
+                      GsApp *app,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       GVariant *body;
+       GVariantBuilder builder;
+       const gchar *device_id;
+       const gchar *filename;
+       gint fd;
+       gint retval;
+       _cleanup_object_unref_ GDBusConnection *conn = NULL;
+       _cleanup_object_unref_ GDBusMessage *message = NULL;
+       _cleanup_object_unref_ GDBusMessage *request = NULL;
+       _cleanup_object_unref_ GUnixFDList *fd_list = NULL;
+
+       conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+       if (conn == NULL)
+               return FALSE;
+
+       /* set options */
+       g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+       g_variant_builder_add (&builder, "{sv}",
+                              "reason", g_variant_new_string ("system-update"));
+       filename = gs_app_get_source_id_default (app);
+       g_variant_builder_add (&builder, "{sv}",
+                              "filename", g_variant_new_string (filename));
+       g_variant_builder_add (&builder, "{sv}",
+                              "offline", g_variant_new_boolean (TRUE));
+
+       /* open file */
+       fd = open (filename, O_RDONLY);
+       if (fd < 0) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "failed to open %s",
+                            filename);
+               return FALSE;
+       }
+
+       /* set out of band file descriptor */
+       fd_list = g_unix_fd_list_new ();
+       retval = g_unix_fd_list_append (fd_list, fd, NULL);
+       g_assert (retval != -1);
+       request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
+                                                 FWUPD_DBUS_PATH,
+                                                 FWUPD_DBUS_INTERFACE,
+                                                 "Update");
+       g_dbus_message_set_unix_fd_list (request, fd_list);
+
+       /* g_unix_fd_list_append did a dup() already */
+       close (fd);
+
+       /* send message */
+       device_id = gs_app_get_metadata_item (app, "fwupd::DeviceID");
+       body = g_variant_new ("(sha{sv})", device_id, fd > -1 ? 0 : -1, &builder);
+       g_dbus_message_set_body (request, body);
+       message = g_dbus_connection_send_message_with_reply_sync (conn,
+                                                                 request,
+                                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                                 -1,
+                                                                 NULL,
+                                                                 NULL,
+                                                                 error);
+       if (message == NULL) {
+               g_dbus_error_strip_remote_error (*error);
+               return FALSE;
+       }
+       if (g_dbus_message_to_gerror (message, error)) {
+               g_dbus_error_strip_remote_error (*error);
+               return FALSE;
+       }
+
+       return TRUE;
+}


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