[gnome-software] Do offline update notification here



commit 232bf1fd91fad4caae61b60a778754085ef21beb
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Oct 26 00:25:20 2013 -0400

    Do offline update notification here
    
    This moves more code from the gsd updates plugin here: We now
    also do the notification at login after an offline update.
    
    At the same time, move the code that deals very specifically
    with the internals of offline updates to its own file.

 src/Makefile.am          |    3 +
 src/gs-application.c     |   19 +++
 src/gs-offline-updates.c |  317 ++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-offline-updates.h |   43 ++++++
 src/gs-shell-updates.c   |   59 +--------
 src/gs-update-monitor.c  |   77 +++++++++++-
 src/gs-utils.c           |   45 +++++++
 src/gs-utils.h           |    1 +
 8 files changed, 505 insertions(+), 59 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index bb38eab..7b2b8df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -134,6 +134,8 @@ gnome_software_service_SOURCES =                    \
        gs-shell-search.h                               \
        gs-update-monitor.c                             \
        gs-update-monitor.h                             \
+       gs-offline-updates.c                            \
+       gs-offline-updates.h                            \
        gs-plugin-loader.c                              \
        gs-plugin-loader.h                              \
        gs-plugin-loader-sync.c                         \
@@ -161,6 +163,7 @@ gnome_software_service_LDADD =                              \
        -lm
 
 gnome_software_service_CFLAGS =                                \
+       -DLIBEXECDIR=\"$(libexecdir)\"                  \
        $(WARNINGFLAGS_C)
 
 gs-shell-search-provider-generated.h gs-shell-search-provider-generated.c: Makefile.am 
$(srcdir)/shell-search-provider-dbus-interfaces.xml
diff --git a/src/gs-application.c b/src/gs-application.c
index 988d667..75e328f 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -35,6 +35,7 @@
 #include "gs-plugin-loader.h"
 #include "gs-profile.h"
 #include "gs-shell-search-provider.h"
+#include "gs-offline-updates.h"
 
 
 struct _GsApplication {
@@ -369,6 +370,22 @@ out:
        g_free (desktop_id);
 }
 
+static void
+clear_offline_updates (GSimpleAction *action,
+                      GVariant      *parameter,
+                      gpointer       data)
+{
+       gs_offline_updates_clear_status ();
+}
+
+static void
+show_offline_updates_error (GSimpleAction *action,
+                           GVariant      *parameter,
+                           gpointer       data)
+{
+       gs_offline_updates_show_error ();
+}
+
 static GActionEntry actions[] = {
        { "about", about_activated, NULL, NULL, NULL },
        { "quit", quit_activated, NULL, NULL, NULL },
@@ -378,6 +395,8 @@ static GActionEntry actions[] = {
        { "set-debug-level", set_debug_level_activated, "i", NULL, NULL },
        { "details", details_activated, "(ss)", NULL, NULL },
        { "launch", launch_activated, "s", NULL, NULL },
+        { "clear-offline-updates", clear_offline_updates, NULL, NULL, NULL },
+        { "show-offline-update-error", show_offline_updates_error, NULL, NULL, NULL },
        { "nop", NULL, NULL, NULL }
 };
 
diff --git a/src/gs-offline-updates.c b/src/gs-offline-updates.c
new file mode 100644
index 0000000..d427c58
--- /dev/null
+++ b/src/gs-offline-updates.c
@@ -0,0 +1,317 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "gs-offline-updates.h"
+
+static void
+child_exit_cb (GPid pid, gint status, gpointer user_data)
+{
+       g_spawn_close_pid (pid);
+}
+
+void
+gs_offline_updates_clear_status (void)
+{
+       gboolean ret;
+       GError *error = NULL;
+       const gchar *argv[3];
+       GPid pid;
+
+       argv[0] = "pkexec";
+       argv[1] = LIBEXECDIR "/pk-clear-offline-update";
+       argv[2] = NULL;
+       ret = g_spawn_async (NULL, (gchar**)argv, NULL,
+                            G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+                            NULL, NULL, &pid, &error);
+       if (!ret) {
+               g_warning ("Failure clearing offline update message: %s",
+                          error->message);
+               g_error_free (error);
+               return;
+       }
+       g_child_watch_add (pid, child_exit_cb, NULL);
+}
+
+void
+gs_offline_updates_trigger (void)
+{
+       gboolean ret;
+       GError *error = NULL;
+       const gchar *argv[3];
+
+       argv[0] = "pkexec";
+       argv[1] = LIBEXECDIR "/pk-trigger-offline-update";
+       argv[2] = NULL;
+
+       g_debug ("calling %s %s", argv[0], argv[1]);
+
+       ret = g_spawn_sync (NULL, (gchar**)argv, NULL,
+                           G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+                           NULL, NULL, NULL, NULL, NULL, &error);
+       if (!ret) {
+               g_warning ("Failure triggering offline update: %s",
+                          error->message);
+               g_error_free (error);
+       }
+}
+
+void
+gs_offline_updates_cancel (void)
+{
+       gboolean ret;
+       GError *error = NULL;
+       const gchar *argv[4];
+
+       argv[0] = "pkexec";
+       argv[1] = LIBEXECDIR "/pk-trigger-offline-update";
+       argv[2] = "--cancel";
+       argv[3] = NULL;
+
+       g_debug ("calling %s %s %s", argv[0], argv[1], argv[2]);
+
+       ret = g_spawn_sync (NULL, (gchar**)argv, NULL,
+                           G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+                           NULL, NULL, NULL, NULL, NULL, &error);
+       if (!ret) {
+               g_warning ("Failure cancelling offline update: %s",
+                          error->message);
+               g_error_free (error);
+       }
+}
+
+#define PK_OFFLINE_UPDATE_RESULTS_GROUP         "PackageKit Offline Update Results"
+#define PK_OFFLINE_UPDATE_RESULTS_FILENAME      "/var/lib/PackageKit/offline-update-completed"
+
+gboolean
+gs_offline_updates_get_status (gboolean  *success,
+                              guint     *num_packages,
+                              gchar    **error_code,
+                              gchar    **error_details)
+{
+       GKeyFile *key_file = NULL;
+       gchar *packages = NULL;
+       gchar *code = NULL;
+       gchar *details = NULL;
+       gboolean result = FALSE;
+       gboolean ret;
+       GError *error = NULL;
+       gint i;
+
+       g_debug ("get offline update status");
+
+       *success = FALSE;
+       *num_packages = 0;
+       if (error_code)
+               *error_code = 0;
+       if (error_details)
+               *error_details = NULL;
+
+       if (!g_file_test (PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_FILE_TEST_EXISTS))
+               goto out;
+
+        key_file = g_key_file_new ();
+        ret = g_key_file_load_from_file (key_file,
+                                         PK_OFFLINE_UPDATE_RESULTS_FILENAME,
+                                         G_KEY_FILE_NONE,
+                                         &error);
+        if (!ret) {
+                g_warning ("failed to open %s: %s",
+                           PK_OFFLINE_UPDATE_RESULTS_FILENAME,
+                           error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+       *success = g_key_file_get_boolean (key_file,
+                                          PK_OFFLINE_UPDATE_RESULTS_GROUP,
+                                          "Success",
+                                          NULL);
+
+       if (*success) {
+               packages = g_key_file_get_string (key_file,
+                                                 PK_OFFLINE_UPDATE_RESULTS_GROUP,
+                                                 "Packages",
+                                                 NULL);
+
+               if (packages == NULL) {
+                       g_warning ("No 'Packages' in %s",
+                                  PK_OFFLINE_UPDATE_RESULTS_FILENAME);
+                       goto out;
+               }
+
+               for (i = 0; packages[i] != '\0'; i++) {
+                       if (packages[i] == ',')
+                               (*num_packages)++;
+               }
+
+       } else {
+
+               code = g_key_file_get_string (key_file,
+                                             PK_OFFLINE_UPDATE_RESULTS_GROUP,
+                                             "ErrorCode",
+                                             NULL);
+               details = g_key_file_get_string (key_file,
+                                                PK_OFFLINE_UPDATE_RESULTS_GROUP,
+                                                "ErrorDetails",
+                                                NULL);
+       }       
+
+       result = TRUE;
+
+ out:
+
+       g_debug ("success %d, packages %s, error %s %s",
+                *success, packages, code, details);
+       if (error_code)
+               *error_code = code;
+       else
+               g_free (code);
+       if (error_details)
+               *error_details = details;
+       else
+               g_free (details);
+       g_free (packages);
+       if (key_file != NULL)
+               g_key_file_free (key_file);
+
+       return result;
+}
+
+void
+gs_offline_updates_show_error (void)
+{
+       const gchar *title;
+       gboolean show_geeky = FALSE;
+       GString *msg;
+       GtkWidget *dialog;
+       gboolean success;
+       guint num_packages;
+       gchar *error_code;
+       gchar *error_details;
+       PkErrorEnum error_enum = PK_ERROR_ENUM_UNKNOWN;
+
+       if (!gs_offline_updates_get_status (&success, &num_packages, &error_code, &error_details))
+               return;
+
+       if (error_code != NULL)
+               error_enum = pk_error_enum_from_string (error_code);
+
+       /* TRANSLATORS: this is when the offline update failed */
+       title = _("Failed To Update");
+       msg = g_string_new ("");
+        switch (error_enum) {
+        case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
+                /* TRANSLATORS: the transaction could not be completed
+                * as a previous transaction was unfinished */
+                g_string_append (msg, _("A previous update was unfinished."));
+                show_geeky = TRUE;
+                break;
+        case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
+        case PK_ERROR_ENUM_NO_CACHE:
+        case PK_ERROR_ENUM_NO_NETWORK:
+        case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY:
+        case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
+                /* TRANSLATORS: the package manager needed to download
+ *                  * something with no network available */
+                g_string_append (msg, _("Network access was required but not available."));
+                break;
+        case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
+        case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
+        case PK_ERROR_ENUM_GPG_FAILURE:
+        case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE:
+        case PK_ERROR_ENUM_PACKAGE_CORRUPT:
+                /* TRANSLATORS: if the package is not signed correctly
+ *                  *  */
+                g_string_append (msg, _("An update was not signed in the correct way."));
+                show_geeky = TRUE;
+                break;
+        case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
+        case PK_ERROR_ENUM_FILE_CONFLICTS:
+        case PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE:
+        case PK_ERROR_ENUM_PACKAGE_CONFLICTS:
+                /* TRANSLATORS: the transaction failed in a way the user
+ *                  * probably cannot comprehend. Package management systems
+ *                                   * really are teh suck.*/
+                g_string_append (msg, _("The update could not be completed."));
+                show_geeky = TRUE;
+                break;
+        case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+                /* TRANSLATORS: the user aborted the update manually */
+                g_string_append (msg, _("The update was cancelled."));
+                break;
+        case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
+        case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
+                /* TRANSLATORS: the user must have updated manually after
+ *                  * the updates were prepared */
+                g_string_append (msg, _("An offline update was requested but no packages required 
updating."));
+                break;
+        case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
+                /* TRANSLATORS: we ran out of disk space */
+                g_string_append (msg, _("No space was left on the drive."));
+                break;
+        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD:
+        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL:
+        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE:
+                /* TRANSLATORS: the update process failed in a general
+ *                  * way, usually this message will come from source distros
+ *                                   * like gentoo */
+                g_string_append (msg, _("An update failed to install correctly."));
+                show_geeky = TRUE;
+                break;
+        default:
+                /* TRANSLATORS: We didn't handle the error type */
+                g_string_append (msg, _("The offline update failed in an unexpected way."));
+                show_geeky = TRUE;
+                break;
+        }
+        if (show_geeky) {
+                g_string_append_printf (msg, "\n%s\n\n%s",
+                                        /* TRANSLATORS: these are geeky messages from the
+ *                                          * package manager no mortal is supposed to understand,
+ *                                                                                   * but google might know 
what they mean */
+                                        _("Detailed errors from the package manager follow:"),
+                                        error_details);
+        }
+        dialog = gtk_message_dialog_new (NULL,
+                                         0,
+                                         GTK_MESSAGE_INFO,
+                                         GTK_BUTTONS_CLOSE,
+                                         "%s", title);
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                  "%s", msg->str);
+        g_signal_connect_swapped (dialog, "response",
+                                  G_CALLBACK (gtk_widget_destroy),
+                                  dialog);
+        gtk_widget_show (dialog);
+
+        gs_offline_updates_clear_status ();
+        g_string_free (msg, TRUE);
+
+       g_free (error_code);
+       g_free (error_details);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-offline-updates.h b/src/gs-offline-updates.h
new file mode 100644
index 0000000..ed7bc16
--- /dev/null
+++ b/src/gs-offline-updates.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GS_OFFLINE_UPDATES_H
+#define __GS_OFFLINE_UPDATES_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void    gs_offline_updates_trigger       (void);
+void    gs_offline_updates_cancel        (void);
+void    gs_offline_updates_clear_status  (void);
+gboolean gs_offline_updates_get_status    (gboolean  *success,
+                                          guint     *num_packages,
+                                          gchar    **error_code,
+                                          gchar    **error_details);
+void    gs_offline_updates_show_error    (void);
+
+
+G_END_DECLS
+
+#endif /* __GS_OFFLINE_UPDATES_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index caeca99..07bab2f 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -26,6 +26,7 @@
 #include "gs-shell.h"
 #include "gs-shell-updates.h"
 #include "gs-utils.h"
+#include "gs-offline-updates.h"
 #include "gs-app.h"
 #include "gs-app-widget.h"
 
@@ -451,65 +452,11 @@ gs_shell_updates_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
 }
 
 static void
-reboot_failed (GObject      *source,
-              GAsyncResult *res,
-              gpointer      data)
-{
-       GVariant *ret;
-       const gchar *command;
-       GError *error = NULL;
-
-       ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
-       if (ret) {
-               g_variant_unref (ret);
-               return;
-       }
-
-       if (error) {
-               g_warning ("Calling org.gnome.SessionManager.Reboot failed: %s\n", error->message);
-               g_error_free (error);
-               return;
-       }
-
-       command = "pkexec /usr/libexec/pk-trigger-offline-update --cancel";
-       g_debug ("calling '%s'", command);
-       if (!g_spawn_command_line_sync (command, NULL, NULL, NULL, &error)) {
-               g_warning ("Failed to call '%s': %s\n", command, error->message);
-               g_error_free (error);
-       }
-}
-
-static void
 gs_shell_updates_button_update_all_cb (GtkButton      *button,
                                       GsShellUpdates *updates)
 {
-       GDBusConnection *bus;
-       const gchar *command;
-       GError *error = NULL;
-
-       command = "pkexec /usr/libexec/pk-trigger-offline-update";
-       g_debug ("calling '%s'", command);
-       if (!g_spawn_command_line_sync (command, NULL, NULL, NULL, &error)) {
-               g_warning ("Failed to call '%s': %s\n", command, error->message);
-               g_error_free (error);
-               return;
-       }
-
-       g_debug ("calling org.gnome.SessionManager.Reboot");
-       bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-       g_dbus_connection_call (bus,
-                               "org.gnome.SessionManager",
-                               "/org/gnome/SessionManager",
-                               "org.gnome.SessionManager",
-                               "Reboot",
-                               NULL,
-                               NULL,
-                               G_DBUS_CALL_FLAGS_NONE,
-                               G_MAXINT,
-                               NULL,
-                               reboot_failed,
-                               NULL);
-       g_object_unref (bus);
+       gs_offline_updates_trigger ();
+       gs_reboot (gs_offline_updates_cancel);
 }
 
 static void
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
index 3efe6d0..450c88a 100644
--- a/src/gs-update-monitor.c
+++ b/src/gs-update-monitor.c
@@ -26,8 +26,14 @@
 #include <glib/gi18n.h>
 
 #include "gs-update-monitor.h"
+#include "gs-utils.h"
+#include "gs-offline-updates.h"
 
-#define GSD_UPDATES_ICON_NORMAL "software-update-available-symbolic"
+#define GS_UPDATES_CHECK_OFFLINE_TIMEOUT    30 /* seconds */
+#define GS_REENABLE_OFFLINE_UPDATE_TIMEOUT 300 /* seconds */
+
+#define GS_UPDATES_ICON_NORMAL "software-update-available-symbolic"
+#define GS_UPDATES_ICON_URGENT "software-update-urgent-symbolic"
 
 struct _GsUpdateMonitor {
        GObject          parent;
@@ -36,6 +42,8 @@ struct _GsUpdateMonitor {
        GFile           *offline_update_file;
        GFileMonitor    *offline_update_monitor;
        gboolean         offline_update_notified;
+
+       guint            check_offline_update_id;
 };
 
 struct _GsUpdateMonitorClass {
@@ -71,7 +79,7 @@ notify_offline_update_available (GsUpdateMonitor *monitor)
        monitor->offline_update_notified = TRUE;
 
        /* don't notify more often than every 5 minutes */
-       id = g_timeout_add_seconds (300, reenable_offline_update, monitor);
+       id = g_timeout_add_seconds (GS_REENABLE_OFFLINE_UPDATE_TIMEOUT, reenable_offline_update, monitor);
        g_source_set_name_by_id (id, "[gnome-software] reenable_offline_update");
 
        title = _("Software Updates Available");
@@ -105,6 +113,58 @@ initial_offline_update_check (gpointer data)
         return G_SOURCE_REMOVE;
 }
 
+static gboolean
+check_offline_update_cb (gpointer user_data)
+{
+       GsUpdateMonitor *monitor = user_data;
+       const gchar *message;
+       const gchar *title;
+       gboolean success;
+       guint num_packages = 1;
+       GNotification *notification;
+       GIcon *icon;
+
+       if (!gs_offline_updates_get_status (&success, &num_packages, NULL, NULL))
+               goto out;
+
+       if (success) {
+               title = ngettext ("Software Update Installed",
+                                 "Software Updates Installed",
+                                 num_packages);
+                /* TRANSLATORS: message when we've done offline updates */
+               message = ngettext ("An important OS update has been installed.",
+                                   "Important OS updates have been installed.",
+                                   num_packages);
+
+                gs_offline_updates_clear_status ();
+
+        } else {
+
+               title = _("Software Updates Failed");
+               /* TRANSLATORS: message when we offline updates have failed */
+               message = _("An important OS update failed to be installed.");
+       }
+
+       notification = g_notification_new (title);
+       g_notification_set_body (notification, message);
+       icon = g_themed_icon_new (GS_UPDATES_ICON_URGENT);
+       g_notification_set_icon (notification, icon);
+       g_object_unref (icon);
+       if (success)
+               g_notification_add_button_with_target (notification, _("Review"), "app.set-mode", "s", 
"updated");
+       else
+               g_notification_add_button (notification, _("Show Details"), "app.show-offline-update-error");
+       g_notification_add_button (notification, _("OK"), "app.clear-offline-updates");
+
+       g_application_send_notification (g_application_get_default (), "offline-updates", notification);
+       g_object_unref (notification);
+
+out:
+        monitor->check_offline_update_id = 0;
+
+        return G_SOURCE_REMOVE;
+}
+
 static void
 gs_update_monitor_init (GsUpdateMonitor *monitor)
 {
@@ -116,10 +176,17 @@ gs_update_monitor_init (GsUpdateMonitor *monitor)
        g_signal_connect (monitor->offline_update_monitor, "changed",
                          G_CALLBACK (offline_update_cb), monitor);
 
-       id = g_timeout_add_seconds (300,
+       id = g_timeout_add_seconds (GS_REENABLE_OFFLINE_UPDATE_TIMEOUT,
                                    initial_offline_update_check,
                                    monitor);
        g_source_set_name_by_id (id, "[gnome-software] initial_offline_update_check");
+
+       monitor->check_offline_update_id = 
+               g_timeout_add_seconds (GS_UPDATES_CHECK_OFFLINE_TIMEOUT,
+                                       check_offline_update_cb,
+                                       monitor);
+       g_source_set_name_by_id (monitor->check_offline_update_id,
+                                "[gnpome-software] check_offline_update_cb");
 }
 
 static void
@@ -127,6 +194,10 @@ gs_update_monitor_finalize (GObject *object)
 {
        GsUpdateMonitor *monitor = GS_UPDATE_MONITOR (object);
 
+       if (monitor->check_offline_update_id != 0) {
+               g_source_remove (monitor->check_offline_update_id);
+               monitor->check_offline_update_id = 0;
+       }
        g_clear_object (&monitor->offline_update_file);
        g_clear_object (&monitor->offline_update_monitor);
        g_application_release (G_APPLICATION (monitor->application));
diff --git a/src/gs-utils.c b/src/gs-utils.c
index 027a12b..0824de3 100644
--- a/src/gs-utils.c
+++ b/src/gs-utils.c
@@ -280,4 +280,49 @@ gs_pixbuf_load (const gchar *icon_name, guint icon_size, GError **error)
        return pixbuf;
 }
 
+static void
+reboot_done (GObject *source, GAsyncResult *res, gpointer data)
+{
+       GCallback reboot_failed = data;
+       GVariant *ret;
+       GError *error = NULL;
+
+       ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
+       if (ret) {
+               g_variant_unref (ret);
+               return;
+       }
+
+       if (error) {
+               g_warning ("Calling org.gnome.SessionManager.Reboot failed: %s\n", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       reboot_failed ();
+}
+
+void
+gs_reboot (GCallback reboot_failed)
+{
+       GDBusConnection *bus;
+
+       g_debug ("calling org.gnome.SessionManager.Reboot");
+
+       bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+       g_dbus_connection_call (bus,
+                               "org.gnome.SessionManager",
+                               "/org/gnome/SessionManager",
+                               "org.gnome.SessionManager",
+                               "Reboot",
+                               NULL,
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               G_MAXINT,
+                               NULL,
+                               reboot_done,
+                               reboot_failed);
+       g_object_unref (bus);
+}
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-utils.h b/src/gs-utils.h
index 07b0c0e..ecfdd84 100644
--- a/src/gs-utils.h
+++ b/src/gs-utils.h
@@ -48,6 +48,7 @@ gboolean gs_mkdir_parent              (const gchar    *path,
 GdkPixbuf *gs_pixbuf_load              (const gchar    *icon_name,
                                         guint           icon_size,
                                         GError         **error);
+void     gs_reboot                      (GCallback       reboot_failed);
 
 G_END_DECLS
 


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