[gnome-session] manager: make Shutdown/Reboot D-Bus APIs failable



commit 2040b88847ed1ee11182caac96b0f09c553c646e
Author: Ray Strode <rstrode redhat com>
Date:   Tue Aug 27 17:24:48 2013 -0400

    manager: make Shutdown/Reboot D-Bus APIs failable
    
    Right now Shutdown and Reboot return as soon as the
    operations are initiated.  This means we get no notification
    if the operation is cancelled by the user later.
    
    This commit defers returning unless it's clear whether or not
    the operation will go through.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706676

 gnome-session/gsm-manager.c                |  102 ++++++++++++++++++++++------
 gnome-session/gsm-manager.h                |    4 +-
 gnome-session/org.gnome.SessionManager.xml |    2 +
 3 files changed, 86 insertions(+), 22 deletions(-)
---
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index dd47b69..d2f375d 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -156,6 +156,9 @@ struct GsmManagerPrivate
          * and shouldn't be automatically restarted */
         GSList                 *condition_clients;
 
+        GSList                 *pending_end_session_tasks;
+        GCancellable           *end_session_cancellable;
+
         GSettings              *settings;
         GSettings              *session_settings;
         GSettings              *screensaver_settings;
@@ -834,10 +837,30 @@ _client_end_session_helper (const char           *id,
 }
 
 static void
+complete_end_session_tasks (GsmManager *manager)
+{
+        GSList *l;
+
+        for (l = manager->priv->pending_end_session_tasks;
+             l != NULL;
+             l = l->next) {
+                GTask *task = G_TASK (l->data);
+                if (!g_task_return_error_if_cancelled (task))
+                    g_task_return_boolean (task, TRUE);
+        }
+
+        g_slist_free_full (manager->priv->pending_end_session_tasks,
+                           (GDestroyNotify) g_object_unref);
+        manager->priv->pending_end_session_tasks = NULL;
+}
+
+static void
 do_phase_end_session (GsmManager *manager)
 {
         ClientEndSessionData data;
 
+        complete_end_session_tasks (manager);
+
         data.manager = manager;
         data.flags = 0;
 
@@ -1052,6 +1075,8 @@ cancel_end_session (GsmManager *manager)
         /* switch back to running phase */
         g_debug ("GsmManager: Cancelling the end of session");
 
+        g_cancellable_cancel (manager->priv->end_session_cancellable);
+
         /* remove the dialog before we remove the inhibitors, else the dialog
          * will activate itself automatically when the last inhibitor will be
          * removed */
@@ -1525,6 +1550,10 @@ start_phase (GsmManager *manager)
                                  NULL);
 #endif
                 gsm_xsmp_server_start_accepting_new_clients (manager->priv->xsmp_server);
+                if (manager->priv->pending_end_session_tasks != NULL)
+                        complete_end_session_tasks (manager);
+                g_object_unref (manager->priv->end_session_cancellable);
+                manager->priv->end_session_cancellable = g_cancellable_new ();
                 g_signal_emit (manager, signals[SESSION_RUNNING], 0);
                 update_idle (manager);
                 break;
@@ -2545,6 +2574,7 @@ gsm_manager_dispose (GObject *object)
 
         g_debug ("GsmManager: disposing manager");
 
+        g_clear_object (&manager->priv->end_session_cancellable);
         g_clear_object (&manager->priv->xsmp_server);
 
         if (manager->priv->clients != NULL) {
@@ -2853,6 +2883,7 @@ gsm_manager_init (GsmManager *manager)
                           G_CALLBACK (on_gsm_system_active_changed), manager);
 
         manager->priv->shell = gsm_get_shell ();
+        manager->priv->end_session_cancellable = g_cancellable_new ();
 }
 
 GsmManager *
@@ -3459,32 +3490,54 @@ _switch_user_is_locked_down (GsmManager *manager)
                                        KEY_DISABLE_USER_SWITCHING);
 }
 
+static void
+complete_end_session_task (GsmManager            *manager,
+                           GAsyncResult          *result,
+                           DBusGMethodInvocation *context)
+{
+        GError *error = NULL;
+
+        if (!g_task_propagate_boolean (G_TASK (result), &error))
+                dbus_g_method_return_error (context, error);
+        else
+                dbus_g_method_return (context);
+}
+
 gboolean
-gsm_manager_shutdown (GsmManager *manager,
-                      GError    **error)
+gsm_manager_shutdown (GsmManager            *manager,
+                      DBusGMethodInvocation *context)
 {
+        GTask *task;
         gboolean shell_running;
+        GError *error = NULL;
 
         g_debug ("GsmManager: Shutdown called");
 
         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
 
         if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) {
-                g_set_error (error,
-                             GSM_MANAGER_ERROR,
-                             GSM_MANAGER_ERROR_NOT_IN_RUNNING,
-                             "Shutdown interface is only available during the Running phase");
+                error = g_error_new (GSM_MANAGER_ERROR,
+                                     GSM_MANAGER_ERROR_NOT_IN_RUNNING,
+                                     "Shutdown interface is only available during the Running phase");
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
                 return FALSE;
         }
 
         if (_log_out_is_locked_down (manager)) {
-                g_set_error (error,
-                             GSM_MANAGER_ERROR,
-                             GSM_MANAGER_ERROR_LOCKED_DOWN,
-                             "Logout has been locked down");
+                error = g_error_new (GSM_MANAGER_ERROR,
+                                     GSM_MANAGER_ERROR_LOCKED_DOWN,
+                                     "Logout has been locked down");
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
                 return FALSE;
         }
 
+        task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) 
complete_end_session_task, context);
+
+        manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks,
+                                                                    task);
+
         shell_running = gsm_shell_is_running (manager->priv->shell);
 
         if (!shell_running)
@@ -3496,31 +3549,40 @@ gsm_manager_shutdown (GsmManager *manager,
 }
 
 gboolean
-gsm_manager_reboot (GsmManager  *manager,
-                    GError     **error)
+gsm_manager_reboot (GsmManager            *manager,
+                    DBusGMethodInvocation *context)
 {
+        GTask *task;
         gboolean shell_running;
+        GError *error = NULL;
 
         g_debug ("GsmManager: Reboot called");
 
         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
 
         if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) {
-                g_set_error (error,
-                             GSM_MANAGER_ERROR,
-                             GSM_MANAGER_ERROR_NOT_IN_RUNNING,
-                             "Reboot interface is only available during the Running phase");
+                error = g_error_new (GSM_MANAGER_ERROR,
+                                     GSM_MANAGER_ERROR_NOT_IN_RUNNING,
+                                     "Reboot interface is only available during the Running phase");
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
                 return FALSE;
         }
 
         if (_log_out_is_locked_down (manager)) {
-                g_set_error (error,
-                             GSM_MANAGER_ERROR,
-                             GSM_MANAGER_ERROR_LOCKED_DOWN,
-                             "Logout has been locked down");
+                error = g_error_new (GSM_MANAGER_ERROR,
+                                     GSM_MANAGER_ERROR_LOCKED_DOWN,
+                                     "Logout has been locked down");
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
                 return FALSE;
         }
 
+        task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) 
complete_end_session_task, context);
+
+        manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks,
+                                                                    task);
+
         shell_running = gsm_shell_is_running (manager->priv->shell);
 
         if (!shell_running)
diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h
index f9632d7..1957851 100644
--- a/gnome-session/gsm-manager.h
+++ b/gnome-session/gsm-manager.h
@@ -157,9 +157,9 @@ gboolean            gsm_manager_is_inhibited                   (GsmManager
                                                                 GError                *error);
 
 gboolean            gsm_manager_shutdown                       (GsmManager     *manager,
-                                                                GError        **error);
+                                                                DBusGMethodInvocation *context);
 gboolean            gsm_manager_reboot                         (GsmManager     *manager,
-                                                                GError        **error);
+                                                                DBusGMethodInvocation *context);
 
 gboolean            gsm_manager_can_shutdown                   (GsmManager     *manager,
                                                                 gboolean       *shutdown_available,
diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml
index eb69180..8c31694 100644
--- a/gnome-session/org.gnome.SessionManager.xml
+++ b/gnome-session/org.gnome.SessionManager.xml
@@ -271,6 +271,7 @@
     </method>
 
     <method name="Shutdown">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
       <doc:doc>
         <doc:description>
           <doc:para>Request a shutdown dialog.</doc:para>
@@ -279,6 +280,7 @@
     </method>
 
     <method name="Reboot">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
       <doc:doc>
         <doc:description>
           <doc:para>Request a reboot dialog.</doc:para>


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