gnome-session r5377 - in trunk: . gnome-session
- From: vuntz svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-session r5377 - in trunk: . gnome-session
- Date: Wed, 8 Apr 2009 13:42:27 +0000 (UTC)
Author: vuntz
Date: Wed Apr 8 13:42:27 2009
New Revision: 5377
URL: http://svn.gnome.org/viewvc/gnome-session?rev=5377&view=rev
Log:
2009-04-08 Vincent Untz <vuntz gnome org>
Make reboot and shutdown leave the session properly, by letting apps
exit before doing the real reboot/shutdown.
Note that because of the ConsoleKit policies, the ways it's handled
when there are more than one user logged in or when the policy always
require a password might be a bit different:
- in the usual case (single user, no password required), everything
works as expected.
- in the multiple users case (password generally required once), we
ask for the password before trying to exit the session.
- if the password is required each time the ConsoleKit action is
called, then we'll ask for the password only once, after having made
all apps exit. If this doesn't work (wrong password), since the
session is killed anyway, we log out and ask gdm to do the action.
* gnome-session/gsm-marshal.list: add new signature that we need
* gnome-session/gsm-consolekit.[ch]: add new privileges-completed
signal
(gsm_consolekit_class_init): add new signal
(gsm_consolekit_get_result_for_action): new, split from
gsm_consolekit_can_do_action()
(gsm_consolekit_can_do_action): ensure that the CK connection works
here (instead of requiring callers to do it), and use
gsm_consolekit_get_result_for_action()
(gsm_consolekit_is_session_for_other_user): new, ask ConsoleKit if a
session object is for a different user than the current user (ignoring
the login sessions)
(gsm_consolekit_is_single_user): new, determine if there's only a
single user logged in on this machine
(obtain_privileges_cb): new, PolicyKit callback when the privileges
were obtained/denied, to send the privileges-completed signal
(gsm_consolekit_obtain_privileges_for_action): new, obtain the
PolicyKit privileges for a specific action
(gsm_consolekit_get_privileges_for_actions): new, to know if we have
privileges for a set of actions, and request the privileges if needed
(gsm_consolekit_get_restart_privileges): new, trivial
(gsm_consolekit_get_stop_privileges): new, trivial
(gsm_consolekit_can_restart): do not ensure that the CK connection
works here, it will be done in gsm_consolekit_can_do_action()
(gsm_consolekit_can_stop): ditto
* gnome-session/gsm-manager.c: we add a logout type variable that lets
us remember what should be done when gnome-session exits.
(quit_request_completed): new, callback that will make gnome-session
exit after the ConsoleKit call to Stop/Restart has been done. If the
ConsoleKit call wasn't successful, we fallback on gdm (since we're in
the EXIT phase, and all apps have quitted, there's no point in not
asking gdm to do that).
(gsm_manager_quit): new, to do the right thing to log out depending on
what the user wanted to achieve when logging out.
(end_phase): use gsm_manager_quit() instead of directly calling
gtk_main_quit()
(cancel_end_session): reset the logout type to none
(do_attempt_reboot), (do_attempt_shutdown), (manager_attempt_reboot),
(manager_attempt_shutdown): killed/merged in
request_reboot/request_shutdown
(do_inhibit_dialog_action): renamed from do_dialog_action(); for
shutdown and reboot, we just do like logout and end the phase.
(inhibit_dialog_response): s/do_dialog_action/do_inhibit_dialog_action
(query_end_session_complete): add a comment about
gsm_inhibit_dialog_new to make it clear that the
GSM_LOGOUT_ACTION_LOGOUT parameter is fine for shutdown and reboot too
(request_reboot_privileges_completed): new, handle the fact that we got
the privileges from ConsoleKit to do the reboot.
(request_reboot): ask ConsoleKit for the privileges to reboot, and if
it doesn't work (no ConsoleKit), just end the phase
(request_shutdown_privileges_completed), (request_shutdown): see above
changes for reboot functions
(request_logout): set the logout type
Modified:
trunk/ChangeLog
trunk/gnome-session/gsm-consolekit.c
trunk/gnome-session/gsm-consolekit.h
trunk/gnome-session/gsm-manager.c
trunk/gnome-session/gsm-marshal.list
Modified: trunk/gnome-session/gsm-consolekit.c
==============================================================================
--- trunk/gnome-session/gsm-consolekit.c (original)
+++ trunk/gnome-session/gsm-consolekit.c Wed Apr 8 13:42:27 2009
@@ -35,6 +35,7 @@
#include <polkit-gnome/polkit-gnome.h>
#endif
+#include "gsm-marshal.h"
#include "gsm-consolekit.h"
#define CK_NAME "org.freedesktop.ConsoleKit"
@@ -64,6 +65,7 @@
enum {
REQUEST_COMPLETED = 0,
+ PRIVILEGES_COMPLETED,
LAST_SIGNAL
};
@@ -133,6 +135,17 @@
G_TYPE_NONE,
1, G_TYPE_POINTER);
+ signals [PRIVILEGES_COMPLETED] =
+ g_signal_new ("privileges-completed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmConsolekitClass, privileges_completed),
+ NULL,
+ NULL,
+ gsm_marshal_VOID__BOOLEAN_BOOLEAN_POINTER,
+ G_TYPE_NONE,
+ 3, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_POINTER);
+
g_type_class_add_private (manager_class, sizeof (GsmConsolekitPrivate));
}
@@ -889,9 +902,9 @@
}
#ifdef HAVE_POLKIT_GNOME
-static gboolean
-gsm_consolekit_can_do_action (GsmConsolekit *manager,
- const char *action_id)
+static PolKitResult
+gsm_consolekit_get_result_for_action (GsmConsolekit *manager,
+ const char *action_id)
{
PolKitGnomeContext *gnome_context;
PolKitAction *action;
@@ -903,11 +916,11 @@
gnome_context = polkit_gnome_context_get (NULL);
if (gnome_context == NULL) {
- return FALSE;
+ return POLKIT_RESULT_UNKNOWN;
}
if (gnome_context->pk_tracker == NULL) {
- return FALSE;
+ return POLKIT_RESULT_UNKNOWN;
}
dbus_error_init (&dbus_error);
@@ -917,17 +930,16 @@
dbus_error_free (&dbus_error);
if (caller == NULL) {
- return FALSE;
+ return POLKIT_RESULT_UNKNOWN;
}
action = polkit_action_new ();
if (!polkit_action_set_action_id (action, action_id)) {
polkit_action_unref (action);
polkit_caller_unref (caller);
- return FALSE;
+ return POLKIT_RESULT_UNKNOWN;
}
- result = POLKIT_RESULT_UNKNOWN;
error = NULL;
result = polkit_context_is_caller_authorized (gnome_context->pk_context,
action, caller, FALSE,
@@ -936,18 +948,196 @@
polkit_error_free (error);
}
polkit_action_unref (action);
- polkit_caller_unref (caller);
+ polkit_caller_unref (caller);
+
+ return result;
+}
+
+static gboolean
+gsm_consolekit_can_do_action (GsmConsolekit *manager,
+ const char *action_id)
+{
+ PolKitResult result;
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+ res = gsm_consolekit_ensure_ck_connection (manager, &error);
+ if (!res) {
+ g_warning ("Could not connect to ConsoleKit: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ result = gsm_consolekit_get_result_for_action (manager, action_id);
return result != POLKIT_RESULT_NO && result != POLKIT_RESULT_UNKNOWN;
}
-#endif
-gboolean
-gsm_consolekit_can_restart (GsmConsolekit *manager)
+static gboolean
+gsm_consolekit_is_session_for_other_user (GsmConsolekit *manager,
+ const char *object_path,
+ unsigned int current_uid)
+{
+ DBusGProxy *proxy;
+ gboolean res;
+ char *type;
+ unsigned int uid;
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->dbus_connection,
+ CK_NAME,
+ object_path,
+ CK_SESSION_INTERFACE);
+
+ res = dbus_g_proxy_call_with_timeout (proxy,
+ "GetUnixUser",
+ INT_MAX,
+ NULL,
+ /* parameters: */
+ G_TYPE_INVALID,
+ /* return values: */
+ G_TYPE_UINT, &uid,
+ G_TYPE_INVALID);
+
+ /* error is bad: we consider there's another user */
+ if (!res)
+ return TRUE;
+
+ if (uid == current_uid)
+ return FALSE;
+
+ /* filter out login sessions */
+ res = dbus_g_proxy_call_with_timeout (proxy,
+ "GetSessionType",
+ INT_MAX,
+ NULL,
+ /* parameters: */
+ G_TYPE_INVALID,
+ /* return values: */
+ G_TYPE_STRING, &type,
+ G_TYPE_INVALID);
+
+ /* error is bad: we consider there's another user */
+ if (!res)
+ return TRUE;
+
+ if (g_strcmp0 (type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) == 0) {
+ g_free (type);
+ return FALSE;
+ }
+
+ g_free (type);
+
+ return TRUE;
+}
+
+static gboolean
+gsm_consolekit_is_single_user (GsmConsolekit *manager)
{
-#ifdef HAVE_POLKIT_GNOME
- gboolean res;
- GError *error;
+ DBusGProxy *proxy;
+ GError *error;
+ gboolean res;
+ gboolean single;
+ GPtrArray *array;
+ unsigned int current_uid;
+ int i;
+
+ /* We use the same logic than the one used by ConsoleKit here -- it'd
+ * be nice to have a ConsoleKit API to help us, but well...
+ * If there's any error, we just assume it's multiple users. */
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->dbus_connection,
+ CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE);
+
+ error = NULL;
+ res = dbus_g_proxy_call_with_timeout (proxy,
+ "GetSessions",
+ INT_MAX,
+ &error,
+ /* parameters: */
+ G_TYPE_INVALID,
+ /* return values: */
+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &array,
+ G_TYPE_INVALID);
+
+ if (!res) {
+ g_warning ("Unable to list sessions: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ single = TRUE;
+ current_uid = getuid ();
+
+ for (i = 0; i < array->len; i++) {
+ char *object_path;
+
+ object_path = g_ptr_array_index (array, i);
+
+ if (gsm_consolekit_is_session_for_other_user (manager,
+ object_path,
+ current_uid)) {
+ single = FALSE;
+ break;
+ }
+ }
+
+ g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+ g_ptr_array_free (array, TRUE);
+
+ return single;
+}
+
+static void
+obtain_privileges_cb (PolKitAction *action,
+ gboolean gained_privilege,
+ GError *error,
+ GsmConsolekit *manager)
+{
+ g_signal_emit (G_OBJECT (manager),
+ signals [PRIVILEGES_COMPLETED],
+ 0, gained_privilege, FALSE, error);
+}
+
+static gboolean
+gsm_consolekit_obtain_privileges_for_action (GsmConsolekit *manager,
+ const char *action_id)
+{
+ PolKitAction *action;
+ pid_t pid;
+ guint xid;
+ gboolean res;
+
+ action = polkit_action_new ();
+ polkit_action_set_action_id (action, action_id);
+
+ xid = 0;
+ pid = getpid ();
+
+ res = polkit_gnome_auth_obtain (action,
+ xid,
+ pid,
+ (PolKitGnomeAuthCB) obtain_privileges_cb,
+ manager,
+ NULL);
+
+ polkit_action_unref (action);
+
+ return res;
+}
+
+static gboolean
+gsm_consolekit_get_privileges_for_actions (GsmConsolekit *manager,
+ const char *single_action_id,
+ const char *multiple_action_id)
+{
+ PolKitResult result;
+ gboolean res;
+ GError *error;
+ const char *action_id;
error = NULL;
res = gsm_consolekit_ensure_ck_connection (manager, &error);
@@ -958,6 +1148,82 @@
return FALSE;
}
+ if (gsm_consolekit_is_single_user (manager)) {
+ action_id = single_action_id;
+ } else {
+ action_id = multiple_action_id;
+ }
+
+ result = gsm_consolekit_get_result_for_action (manager, action_id);
+
+ switch (result) {
+ case POLKIT_RESULT_UNKNOWN:
+ case POLKIT_RESULT_NO:
+ return FALSE;
+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+ if (!gsm_consolekit_obtain_privileges_for_action (manager,
+ action_id)) {
+ /* if the call doesn't work, then we were not even able
+ * to do the call requesting the privileges: the setup
+ * is likely broken */
+ return FALSE;
+ }
+ break;
+ case POLKIT_RESULT_YES:
+ g_signal_emit (G_OBJECT (manager),
+ signals [PRIVILEGES_COMPLETED],
+ 0, TRUE, FALSE, NULL);
+ break;
+ case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+ case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+ g_signal_emit (G_OBJECT (manager),
+ signals [PRIVILEGES_COMPLETED],
+ 0, TRUE, TRUE, NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return TRUE;
+}
+#endif
+
+gboolean
+gsm_consolekit_get_restart_privileges (GsmConsolekit *manager)
+{
+#ifdef HAVE_POLKIT_GNOME
+ return gsm_consolekit_get_privileges_for_actions (manager,
+ "org.freedesktop.consolekit.system.restart",
+ "org.freedesktop.consolekit.system.restart-multiple-users");
+#else
+ g_debug ("GsmConsolekit: built without PolicyKit-gnome support");
+ return FALSE;
+#endif
+}
+
+gboolean
+gsm_consolekit_get_stop_privileges (GsmConsolekit *manager)
+{
+#ifdef HAVE_POLKIT_GNOME
+ return gsm_consolekit_get_privileges_for_actions (manager,
+ "org.freedesktop.consolekit.system.stop",
+ "org.freedesktop.consolekit.system.stop-multiple-users");
+#else
+ g_debug ("GsmConsolekit: built without PolicyKit-gnome support");
+ return FALSE;
+#endif
+}
+
+gboolean
+gsm_consolekit_can_restart (GsmConsolekit *manager)
+{
+#ifdef HAVE_POLKIT_GNOME
return gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.restart") ||
gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.restart-multiple-users");
#else
@@ -970,17 +1236,6 @@
gsm_consolekit_can_stop (GsmConsolekit *manager)
{
#ifdef HAVE_POLKIT_GNOME
- gboolean res;
- GError *error;
- error = NULL;
- res = gsm_consolekit_ensure_ck_connection (manager, &error);
- if (!res) {
- g_warning ("Could not connect to ConsoleKit: %s",
- error->message);
- g_error_free (error);
- return FALSE;
- }
-
return gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.stop") ||
gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.stop-multiple-users");
#else
Modified: trunk/gnome-session/gsm-consolekit.h
==============================================================================
--- trunk/gnome-session/gsm-consolekit.h (original)
+++ trunk/gnome-session/gsm-consolekit.h Wed Apr 8 13:42:27 2009
@@ -55,6 +55,11 @@
void (* request_completed) (GsmConsolekit *manager,
GError *error);
+
+ void (* privileges_completed) (GsmConsolekit *manager,
+ gboolean success,
+ gboolean ask_later,
+ GError *error);
};
enum _GsmConsolekitError {
@@ -72,6 +77,10 @@
gboolean gsm_consolekit_can_switch_user (GsmConsolekit *manager);
+gboolean gsm_consolekit_get_restart_privileges (GsmConsolekit *manager);
+
+gboolean gsm_consolekit_get_stop_privileges (GsmConsolekit *manager);
+
gboolean gsm_consolekit_can_stop (GsmConsolekit *manager);
gboolean gsm_consolekit_can_restart (GsmConsolekit *manager);
Modified: trunk/gnome-session/gsm-manager.c
==============================================================================
--- trunk/gnome-session/gsm-manager.c (original)
+++ trunk/gnome-session/gsm-manager.c Wed Apr 8 13:42:27 2009
@@ -84,6 +84,18 @@
#define IS_STRING_EMPTY(x) ((x)==NULL||(x)[0]=='\0')
+typedef enum
+{
+ GSM_MANAGER_LOGOUT_NONE,
+ GSM_MANAGER_LOGOUT_LOGOUT,
+ GSM_MANAGER_LOGOUT_REBOOT,
+ GSM_MANAGER_LOGOUT_REBOOT_INTERACT,
+ GSM_MANAGER_LOGOUT_REBOOT_GDM,
+ GSM_MANAGER_LOGOUT_SHUTDOWN,
+ GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT,
+ GSM_MANAGER_LOGOUT_SHUTDOWN_GDM
+} GsmManagerLogoutType;
+
struct GsmManagerPrivate
{
gboolean failsafe;
@@ -103,6 +115,8 @@
* since it uses a sublist of all running client that replied in a
* specific way */
GSList *next_query_clients;
+ /* This is the action that will be done just before we exit */
+ GsmManagerLogoutType logout_type;
GtkWidget *inhibit_dialog;
@@ -364,6 +378,70 @@
static void start_phase (GsmManager *manager);
static void
+quit_request_completed (GsmConsolekit *consolekit,
+ GError *error,
+ gpointer user_data)
+{
+ GdmLogoutAction fallback_action = GPOINTER_TO_INT (user_data);
+
+ if (error != NULL) {
+ gdm_set_logout_action (fallback_action);
+ }
+
+ g_object_unref (consolekit);
+
+ gtk_main_quit ();
+}
+
+static void
+gsm_manager_quit (GsmManager *manager)
+{
+ GsmConsolekit *consolekit;
+
+ /* See the comment in request_reboot() for some more details about how
+ * this works. */
+
+ switch (manager->priv->logout_type) {
+ case GSM_MANAGER_LOGOUT_LOGOUT:
+ gtk_main_quit ();
+ break;
+ case GSM_MANAGER_LOGOUT_REBOOT:
+ case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+
+ consolekit = gsm_get_consolekit ();
+ g_signal_connect (consolekit,
+ "request-completed",
+ G_CALLBACK (quit_request_completed),
+ GINT_TO_POINTER (GDM_LOGOUT_ACTION_REBOOT));
+ gsm_consolekit_attempt_restart (consolekit);
+ break;
+ case GSM_MANAGER_LOGOUT_REBOOT_GDM:
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
+ gtk_main_quit ();
+ break;
+ case GSM_MANAGER_LOGOUT_SHUTDOWN:
+ case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+
+ consolekit = gsm_get_consolekit ();
+ g_signal_connect (consolekit,
+ "request-completed",
+ G_CALLBACK (quit_request_completed),
+ GINT_TO_POINTER (GDM_LOGOUT_ACTION_SHUTDOWN));
+ gsm_consolekit_attempt_stop (consolekit);
+ break;
+ case GSM_MANAGER_LOGOUT_SHUTDOWN_GDM:
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
+ gtk_main_quit ();
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
end_phase (GsmManager *manager)
{
g_debug ("GsmManager: ending phase %s\n",
@@ -403,7 +481,7 @@
start_phase (manager);
break;
case GSM_MANAGER_PHASE_EXIT:
- gtk_main_quit ();
+ gsm_manager_quit (manager);
break;
default:
g_assert_not_reached ();
@@ -811,6 +889,9 @@
gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_RUNNING);
manager->priv->forceful_logout = FALSE;
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_NONE;
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+
start_phase (manager);
}
@@ -839,49 +920,6 @@
}
}
-
-static void
-do_attempt_reboot (GsmConsolekit *consolekit)
-{
- if (gsm_consolekit_can_restart (consolekit)) {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
- gsm_consolekit_attempt_restart (consolekit);
- } else {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
- }
-}
-
-static void
-do_attempt_shutdown (GsmConsolekit *consolekit)
-{
- if (gsm_consolekit_can_stop (consolekit)) {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
- gsm_consolekit_attempt_stop (consolekit);
- } else {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
- }
-}
-
-static void
-manager_attempt_reboot (GsmManager *manager)
-{
- GsmConsolekit *consolekit;
-
- consolekit = gsm_get_consolekit ();
- do_attempt_reboot (consolekit);
- g_object_unref (consolekit);
-}
-
-static void
-manager_attempt_shutdown (GsmManager *manager)
-{
- GsmConsolekit *consolekit;
-
- consolekit = gsm_get_consolekit ();
- do_attempt_shutdown (consolekit);
- g_object_unref (consolekit);
-}
-
static void
manager_attempt_hibernate (GsmManager *manager)
{
@@ -911,8 +949,8 @@
}
static void
-do_dialog_action (GsmManager *manager,
- int action)
+do_inhibit_dialog_action (GsmManager *manager,
+ int action)
{
switch (action) {
case GSM_LOGOUT_ACTION_SWITCH_USER:
@@ -924,12 +962,12 @@
case GSM_LOGOUT_ACTION_SLEEP:
manager_attempt_suspend (manager);
break;
+ /* If changing the code to make SHUTDOWN/REBOOT/LOGOUT cases different,
+ * then the call to gsm_inhibit_dialog_new() in
+ * query_end_session_complete() should be updated to pass the right
+ * action */
case GSM_LOGOUT_ACTION_SHUTDOWN:
- manager_attempt_shutdown (manager);
- break;
case GSM_LOGOUT_ACTION_REBOOT:
- manager_attempt_reboot (manager);
- break;
case GSM_LOGOUT_ACTION_LOGOUT:
manager->priv->forceful_logout = TRUE;
end_phase (manager);
@@ -971,7 +1009,7 @@
break;
case GTK_RESPONSE_ACCEPT:
g_debug ("GsmManager: doing action %d", action);
- do_dialog_action (manager, action);
+ do_inhibit_dialog_action (manager, action);
break;
default:
g_assert_not_reached ();
@@ -1002,6 +1040,10 @@
return;
}
+ /* Note: GSM_LOGOUT_ACTION_SHUTDOWN and GSM_LOGOUT_ACTION_REBOOT are
+ * actually handled the same way as GSM_LOGOUT_ACTION_LOGOUT in the
+ * inhibit dialog; the action, if the button is clicked, will be to
+ * simply go to the next phase. */
manager->priv->inhibit_dialog = gsm_inhibit_dialog_new (manager->priv->inhibitors,
manager->priv->clients,
GSM_LOGOUT_ACTION_LOGOUT);
@@ -2427,59 +2469,133 @@
}
static void
+request_reboot_privileges_completed (GsmConsolekit *consolekit,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
+{
+ /* make sure we disconnect the signal handler so that it's not called
+ * again next time the event is fired -- this can happen if the reboot
+ * is cancelled. */
+ g_signal_handlers_disconnect_by_func (consolekit,
+ request_reboot_privileges_completed,
+ manager);
+
+ g_object_unref (consolekit);
+
+ if (success) {
+ if (ask_later) {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_INTERACT;
+ } else {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT;
+ }
+
+ end_phase (manager);
+ }
+}
+
+static void
request_reboot (GsmManager *manager)
{
+ GsmConsolekit *consolekit;
+ gboolean success;
+
g_debug ("GsmManager: requesting reboot");
- /* shutdown uses logout inhibit */
- if (! gsm_manager_is_logout_inhibited (manager)) {
- manager_attempt_reboot (manager);
- return;
- }
+ /* We request the privileges before doing anything. There are a few
+ * different cases here:
+ *
+ * - no ConsoleKit: we fallback on GDM
+ * - no password required: everything is fine
+ * - password asked once: we ask for it now. If the user enters it
+ * fine, then all is great. If the user doesn't enter it fine, we
+ * don't do anything (so no logout).
+ * - password asked each time: we don't ask it for now since we don't
+ * want to ask for it twice. Instead we'll ask for it at the very
+ * end. If the user will enter it fine, then all is great again. If
+ * the user doesn't enter it fine, then we'll just fallback to GDM.
+ *
+ * The last case (password asked each time) is a bit broken, but
+ * there's really nothing we can do about it. Generally speaking,
+ * though, the password will only be asked once (unless the system is
+ * configured in paranoid mode), and most probably only if there are
+ * more than one user connected. So the general case is that it will
+ * just work fine.
+ */
- if (manager->priv->inhibit_dialog != NULL) {
- g_debug ("GsmManager: inhibit dialog already up");
- gtk_window_present (GTK_WINDOW (manager->priv->inhibit_dialog));
- return;
+ consolekit = gsm_get_consolekit ();
+ g_signal_connect (consolekit,
+ "privileges-completed",
+ G_CALLBACK (request_reboot_privileges_completed),
+ manager);
+ success = gsm_consolekit_get_restart_privileges (consolekit);
+
+ if (!success) {
+ g_signal_handlers_disconnect_by_func (consolekit,
+ request_reboot_privileges_completed,
+ manager);
+ g_object_unref (consolekit);
+
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_GDM;
+ end_phase (manager);
}
+}
- manager->priv->inhibit_dialog = gsm_inhibit_dialog_new (manager->priv->inhibitors,
- manager->priv->clients,
- GSM_LOGOUT_ACTION_REBOOT);
+static void
+request_shutdown_privileges_completed (GsmConsolekit *consolekit,
+ gboolean success,
+ gboolean ask_later,
+ GError *error,
+ GsmManager *manager)
+{
+ /* make sure we disconnect the signal handler so that it's not called
+ * again next time the event is fired -- this can happen if the reboot
+ * is cancelled. */
+ g_signal_handlers_disconnect_by_func (consolekit,
+ request_shutdown_privileges_completed,
+ manager);
- g_signal_connect (manager->priv->inhibit_dialog,
- "response",
- G_CALLBACK (inhibit_dialog_response),
- manager);
- gtk_widget_show (manager->priv->inhibit_dialog);
+ g_object_unref (consolekit);
+
+ if (success) {
+ if (ask_later) {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT;
+ } else {
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN;
+ }
+
+ end_phase (manager);
+ }
}
static void
request_shutdown (GsmManager *manager)
{
+ GsmConsolekit *consolekit;
+ gboolean success;
+
g_debug ("GsmManager: requesting shutdown");
- /* shutdown uses logout inhibit */
- if (! gsm_manager_is_logout_inhibited (manager)) {
- manager_attempt_shutdown (manager);
- return;
- }
+ /* See the comment in request_reboot() for some more details about how
+ * this works. */
- if (manager->priv->inhibit_dialog != NULL) {
- g_debug ("GsmManager: inhibit dialog already up");
- gtk_window_present (GTK_WINDOW (manager->priv->inhibit_dialog));
- return;
- }
+ consolekit = gsm_get_consolekit ();
+ g_signal_connect (consolekit,
+ "privileges-completed",
+ G_CALLBACK (request_shutdown_privileges_completed),
+ manager);
+ success = gsm_consolekit_get_stop_privileges (consolekit);
- manager->priv->inhibit_dialog = gsm_inhibit_dialog_new (manager->priv->inhibitors,
- manager->priv->clients,
- GSM_LOGOUT_ACTION_SHUTDOWN);
+ if (!success) {
+ g_signal_handlers_disconnect_by_func (consolekit,
+ request_shutdown_privileges_completed,
+ manager);
+ g_object_unref (consolekit);
- g_signal_connect (manager->priv->inhibit_dialog,
- "response",
- G_CALLBACK (inhibit_dialog_response),
- manager);
- gtk_widget_show (manager->priv->inhibit_dialog);
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_GDM;
+ end_phase (manager);
+ }
}
static void
@@ -2543,7 +2659,10 @@
gboolean forceful_logout)
{
g_debug ("GsmManager: requesting logout");
+
manager->priv->forceful_logout = forceful_logout;
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_LOGOUT;
+
end_phase (manager);
}
Modified: trunk/gnome-session/gsm-marshal.list
==============================================================================
--- trunk/gnome-session/gsm-marshal.list (original)
+++ trunk/gnome-session/gsm-marshal.list Wed Apr 8 13:42:27 2009
@@ -1,2 +1,3 @@
BOOLEAN:POINTER
VOID:BOOLEAN,BOOLEAN,BOOLEAN,STRING
+VOID:BOOLEAN,BOOLEAN,POINTER
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]