aboutsummaryrefslogtreecommitdiff
path: root/src/backend-dbus
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend-dbus')
-rw-r--r--src/backend-dbus/CMakeLists.txt86
-rw-r--r--src/backend-dbus/actions.c730
-rw-r--r--src/backend-dbus/actions.h73
-rw-r--r--src/backend-dbus/backend-dbus.c117
-rw-r--r--src/backend-dbus/backend-dbus.h38
-rw-r--r--src/backend-dbus/com.canonical.indicators.webcredentials.xml82
-rw-r--r--src/backend-dbus/display-manager.xml30
-rw-r--r--src/backend-dbus/guest.c570
-rw-r--r--src/backend-dbus/guest.h72
-rw-r--r--src/backend-dbus/org.freedesktop.Accounts.User.xml744
-rw-r--r--src/backend-dbus/org.freedesktop.Accounts.xml194
-rw-r--r--src/backend-dbus/org.freedesktop.ConsoleKit.Manager.xml353
-rw-r--r--src/backend-dbus/org.freedesktop.ConsoleKit.Seat.xml164
-rw-r--r--src/backend-dbus/org.freedesktop.ConsoleKit.Session.xml435
-rw-r--r--src/backend-dbus/org.gnome.ScreenSaver.xml16
-rw-r--r--src/backend-dbus/org.gnome.SessionManager.EndSessionDialog.xml53
-rw-r--r--src/backend-dbus/org.gnome.SessionManager.xml451
-rw-r--r--src/backend-dbus/session-dbus.xml20
-rw-r--r--src/backend-dbus/upower.xml309
-rw-r--r--src/backend-dbus/users.c810
-rw-r--r--src/backend-dbus/users.h71
-rw-r--r--src/backend-dbus/utils.c399
-rw-r--r--src/backend-dbus/utils.h53
23 files changed, 5870 insertions, 0 deletions
diff --git a/src/backend-dbus/CMakeLists.txt b/src/backend-dbus/CMakeLists.txt
new file mode 100644
index 0000000..a477cfe
--- /dev/null
+++ b/src/backend-dbus/CMakeLists.txt
@@ -0,0 +1,86 @@
+# autogenerate source code files for our DBus proxies
+function(gdbus_codegen XML_FILE INTERFACE_PREFIX SOURCE_PREFIX)
+
+ set (SRC_C, ${SOURCE_PREFIX}.c)
+ set (SRC_H, ${SOURCE_PREFIX}.h)
+
+ # check for the app
+ find_program (GDBUS_CODEGEN_EXECUTABLE NAMES gdbus-codegen DOC "gdbus-codegen executable")
+ if(NOT GDBUS_CODEGEN_EXECUTABLE)
+ message(FATAL_ERROR "Executable gdbus-codegen not found")
+ endif()
+
+ # generate the code
+ add_custom_command (
+ OUTPUT ${SOURCE_PREFIX}.c ${SOURCE_PREFIX}.h
+ COMMAND gdbus-codegen ARGS --interface-prefix ${INTERFACE_PREFIX} --generate-c-code ${SOURCE_PREFIX} ${CMAKE_CURRENT_SOURCE_DIR}/${XML_FILE}
+ DEPENDS ${XML_FILE})
+
+ # update our variables
+ set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${SRC_C})
+ set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${SRC_H})
+ set_property (SOURCE ${SRC_C} ${SRC_H} PROPERTY GENERATED)
+
+ # cleanup
+ unset (SRC_C)
+ unset (SRC_H)
+
+endfunction(gdbus_codegen)
+gdbus_codegen ("display-manager.xml" "org.freedesktop" "dbus-display-manager")
+gdbus_codegen ("com.canonical.indicators.webcredentials.xml" "com.canonical.indicators" "dbus-webcredentials")
+gdbus_codegen ("org.freedesktop.Accounts.xml" "org.freedesktop" "dbus-accounts")
+gdbus_codegen ("org.freedesktop.Accounts.User.xml" "org.freedesktop" "dbus-user")
+gdbus_codegen ("org.freedesktop.ConsoleKit.Manager.xml" "org.freedesktop" "dbus-consolekit-manager")
+gdbus_codegen ("org.freedesktop.ConsoleKit.Seat.xml" "org.freedesktop" "dbus-consolekit-seat")
+gdbus_codegen ("org.freedesktop.ConsoleKit.Session.xml" "org.freedesktop" "dbus-consolekit-session")
+gdbus_codegen ("org.gnome.ScreenSaver.xml" "org" "gnome-screen-saver")
+gdbus_codegen ("org.gnome.SessionManager.xml" "org" "gnome-session-manager")
+gdbus_codegen ("org.gnome.SessionManager.EndSessionDialog.xml" "org.gnome.SessionManager" "dbus-end-session-dialog")
+gdbus_codegen ("upower.xml" "org.freedesktop" "dbus-upower")
+
+# add warnings/coverage info on handwritten files
+# but not the autogenerated ones...
+set_source_files_properties (actions.c
+ backend-dbus.c
+ guest.c
+ users.c
+ utils.c
+ PROPERTIES COMPILE_FLAGS " -g ${CC_WARNING_ARGS} ${GCOV_FLAGS}")
+
+# add the bin dir to our include path s.t. our code can find the autogenerated header files
+include_directories (${CMAKE_CURRENT_BINARY_DIR} ${SERVICE_INCLUDE_DIRS})
+
+add_library (backenddbus STATIC
+ gnome-screen-saver.c
+ gnome-screen-saver.h
+ gnome-session-manager.c
+ gnome-session-manager.h
+ dbus-display-manager.c
+ dbus-display-manager.h
+ dbus-consolekit-manager.c
+ dbus-consolekit-manager.h
+ dbus-consolekit-seat.c
+ dbus-consolekit-seat.h
+ dbus-consolekit-session.c
+ dbus-consolekit-session.h
+ dbus-accounts.c
+ dbus-accounts.h
+ dbus-upower.c
+ dbus-upower.h
+ dbus-user.c
+ dbus-user.h
+ dbus-webcredentials.c
+ dbus-webcredentials.h
+ dbus-end-session-dialog.c
+ dbus-end-session-dialog.h
+ actions.c
+ actions.h
+ backend-dbus.c
+ backend-dbus.h
+ guest.c
+ guest.h
+ users.c
+ users.h
+ utils.c
+ utils.h)
+
diff --git a/src/backend-dbus/actions.c b/src/backend-dbus/actions.c
new file mode 100644
index 0000000..8994710
--- /dev/null
+++ b/src/backend-dbus/actions.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include "dbus-end-session-dialog.h"
+#include "dbus-upower.h"
+#include "dbus-webcredentials.h"
+#include "gnome-screen-saver.h"
+#include "gnome-session-manager.h"
+
+#include "actions.h"
+
+enum
+{
+ END_SESSION_TYPE_LOGOUT = 0,
+ END_SESSION_TYPE_SHUTDOWN,
+ END_SESSION_TYPE_REBOOT
+};
+
+struct _IndicatorSessionActionsDbusPriv
+{
+ GCancellable * cancellable;
+
+ GSettings * lockdown_settings;
+ UPower * upower;
+ GnomeScreenSaver * screen_saver;
+ GnomeSessionManager * session_manager;
+ ConsoleKitManager * ck_manager;
+ ConsoleKitSeat * ck_seat;
+ DisplayManagerSeat * dm_seat;
+ Webcredentials * webcredentials;
+ EndSessionDialog * end_session_dialog;
+
+ gboolean suspend_allowed;
+ gboolean hibernate_allowed;
+ gboolean seat_allows_activation;
+};
+
+typedef IndicatorSessionActionsDbusPriv priv_t;
+
+G_DEFINE_TYPE (IndicatorSessionActionsDbus,
+ indicator_session_actions_dbus,
+ INDICATOR_TYPE_SESSION_ACTIONS)
+
+/***
+****
+***/
+
+static void
+log_and_clear_error (GError ** err, const char * loc, const char * func)
+{
+ if (*err)
+ {
+ g_warning ("%s %s: %s", loc, func, (*err)->message);
+ g_clear_error (err);
+ }
+}
+
+static void
+on_can_activate_sessions (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gboolean can_activate_sessions;
+
+ err = NULL;
+ can_activate_sessions = FALSE;
+ console_kit_seat_call_can_activate_sessions_finish (CONSOLE_KIT_SEAT(o),
+ &can_activate_sessions,
+ res,
+ &err);
+ if (err == NULL)
+ {
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv;
+ p->seat_allows_activation = can_activate_sessions;
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+set_ck_seat (IndicatorSessionActionsDbus * self, ConsoleKitSeat * seat)
+{
+ priv_t * p = self->priv;
+
+ g_clear_object (&p->ck_seat);
+
+ if (seat != NULL)
+ {
+ p->ck_seat = g_object_ref (seat);
+
+ console_kit_seat_call_can_activate_sessions (seat,
+ p->cancellable,
+ on_can_activate_sessions,
+ self);
+ }
+}
+
+/***
+****
+***/
+
+static void
+set_dm_seat (IndicatorSessionActionsDbus * self, DisplayManagerSeat * seat)
+{
+ priv_t * p = self->priv;
+
+ if (p->dm_seat != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (p->dm_seat, self);
+ g_clear_object (&p->dm_seat);
+ }
+
+ if (seat != NULL)
+ {
+ p->dm_seat = g_object_ref (seat);
+ /*g_signal_connect (seat, "notify::has-actions-account", G_CALLBACK(on_notify_has_actions_account), self);*/
+ }
+}
+
+static void
+on_screensaver_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ GnomeScreenSaver * ss;
+
+ err = NULL;
+ ss = gnome_screen_saver_proxy_new_for_bus_finish (res, &err);
+ if (err == NULL)
+ {
+ INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv->screen_saver = ss;
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_suspend_allowed_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gboolean allowed = FALSE;
+
+ err = NULL;
+ upower_call_suspend_allowed_finish (UPOWER(o), &allowed, res, &err);
+ if (err == NULL)
+ {
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv;
+
+ if (p->suspend_allowed != allowed)
+ {
+ p->suspend_allowed = allowed;
+ indicator_session_actions_notify_can_suspend (gself);
+ }
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_hibernate_allowed_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gboolean allowed = FALSE;
+
+ err = NULL;
+ upower_call_hibernate_allowed_finish (UPOWER(o), &allowed, res, &err);
+ if (err == NULL)
+ {
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv;
+
+ if (p->hibernate_allowed != allowed)
+ {
+ p->hibernate_allowed = allowed;
+ indicator_session_actions_notify_can_hibernate (gself);
+ }
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_upower_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ UPower * upower;
+
+ err = NULL;
+ upower = upower_proxy_new_for_bus_finish (res, &err);
+ if (err == NULL)
+ {
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv;
+
+ p->upower = upower;
+
+ g_signal_connect_swapped (upower, "notify::can-suspend",
+ G_CALLBACK(indicator_session_actions_notify_can_suspend), gself);
+
+ g_signal_connect_swapped (upower, "notify::can-hibernate",
+ G_CALLBACK(indicator_session_actions_notify_can_hibernate), gself);
+
+ upower_call_suspend_allowed (upower, p->cancellable, on_suspend_allowed_ready, gself);
+
+ upower_call_hibernate_allowed (upower, p->cancellable, on_hibernate_allowed_ready, gself);
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_session_manager_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ GnomeSessionManager * sm;
+
+ err = NULL;
+ sm = gnome_session_manager_proxy_new_for_bus_finish (res, &err);
+ if (err == NULL)
+ {
+ INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv->session_manager = sm;
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_webcredentials_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ Webcredentials * webcredentials;
+
+ err = NULL;
+ webcredentials = webcredentials_proxy_new_for_bus_finish (res, &err);
+ if (err == NULL)
+ {
+ INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv->webcredentials = webcredentials;
+
+ g_signal_connect_swapped (webcredentials, "notify::error-status",
+ G_CALLBACK(indicator_session_actions_notify_has_online_account_error), gself);
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+on_end_session_dialog_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ EndSessionDialog * end_session_dialog;
+
+ err = NULL;
+ end_session_dialog = end_session_dialog_proxy_new_for_bus_finish (res, &err);
+ if (err == NULL)
+ {
+ INDICATOR_SESSION_ACTIONS_DBUS(gself)->priv->end_session_dialog = end_session_dialog;
+
+ indicator_session_actions_notify_can_prompt (INDICATOR_SESSION_ACTIONS(gself));
+ }
+
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+/***
+**** Virtual Functions
+***/
+
+static gboolean
+my_can_lock (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return !g_settings_get_boolean (p->lockdown_settings, "disable-lock-screen");
+}
+
+static gboolean
+my_can_logout (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return !g_settings_get_boolean (p->lockdown_settings, "disable-log-out");
+}
+
+static gboolean
+my_can_switch (IndicatorSessionActions * self)
+{
+ const priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return p->seat_allows_activation
+ && !g_settings_get_boolean (p->lockdown_settings, "disable-user-switching");
+}
+
+static gboolean
+my_can_suspend (IndicatorSessionActions * self)
+{
+ const priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return p && p->upower && p->suspend_allowed && upower_get_can_suspend (p->upower);
+}
+
+static gboolean
+my_can_hibernate (IndicatorSessionActions * self)
+{
+ const priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return p && p->upower && p->hibernate_allowed && upower_get_can_hibernate (p->upower);
+}
+
+static gboolean
+my_can_prompt (IndicatorSessionActions * self)
+{
+ const priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return (p != NULL)
+ && (p->end_session_dialog != NULL)
+ && (g_dbus_proxy_get_name_owner (G_DBUS_PROXY(p->end_session_dialog)) != NULL);
+}
+
+static gboolean
+my_has_online_account_error (IndicatorSessionActions * self)
+{
+ const priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ return p && (p->webcredentials) && (webcredentials_get_error_status (p->webcredentials));
+}
+
+static void
+my_suspend (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->upower != NULL);
+
+ upower_call_suspend (p->upower, p->cancellable, NULL, NULL);
+}
+
+static void
+my_hibernate (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->upower != NULL);
+
+ upower_call_hibernate (p->upower, p->cancellable, NULL, NULL);
+}
+
+/***
+**** End Session Dialog
+***/
+
+static void
+logout_now (IndicatorSessionActions * self, gboolean try_to_prompt)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+ const int type = try_to_prompt ? 0 : 1;
+
+ g_return_if_fail (p->session_manager != NULL);
+
+ gnome_session_manager_call_logout (p->session_manager,
+ type,
+ p->cancellable,
+ NULL,
+ NULL);
+}
+
+static void
+logout_now_with_prompt (IndicatorSessionActions * self)
+{
+ logout_now (self, TRUE);
+}
+
+static void
+logout_now_quietly (IndicatorSessionActions * self)
+{
+ logout_now (self, FALSE);
+}
+
+static void
+restart_now (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->ck_manager != NULL);
+
+ console_kit_manager_call_restart (p->ck_manager, p->cancellable, NULL, NULL);
+}
+
+static void
+shutdown_now (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->ck_manager != NULL);
+
+ console_kit_manager_call_stop (p->ck_manager, p->cancellable, NULL, NULL);
+}
+
+static void
+stop_listening_to_dialog (IndicatorSessionActionsDbus * self)
+{
+ g_signal_handlers_disconnect_by_data (self->priv->end_session_dialog, self);
+}
+static void
+on_end_session_dialog_canceled (IndicatorSessionActionsDbus * self)
+{
+ stop_listening_to_dialog (self);
+}
+static void
+on_end_session_dialog_closed (IndicatorSessionActionsDbus * self)
+{
+ stop_listening_to_dialog (self);
+}
+
+static void
+on_open_end_session_dialog_ready (GObject * o,
+ GAsyncResult * res,
+ gpointer gself G_GNUC_UNUSED)
+{
+ GError * err = NULL;
+ end_session_dialog_call_open_finish (END_SESSION_DIALOG(o), res, &err);
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+show_end_session_dialog (IndicatorSessionActionsDbus * self, int type)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+ gpointer o = p->end_session_dialog;
+ const char * inhibitor_paths[] = { NULL };
+
+ g_assert (o != NULL);
+
+ g_signal_connect_swapped (o, "confirmed-logout", G_CALLBACK(logout_now_quietly), self);
+ g_signal_connect_swapped (o, "confirmed-reboot", G_CALLBACK(restart_now), self);
+ g_signal_connect_swapped (o, "confirmed-shutdown", G_CALLBACK(shutdown_now), self);
+ g_signal_connect_swapped (o, "canceled", G_CALLBACK(on_end_session_dialog_canceled), self);
+ g_signal_connect_swapped (o, "closed", G_CALLBACK(on_end_session_dialog_closed), self);
+
+ end_session_dialog_call_open (p->end_session_dialog, type, 0, 0, inhibitor_paths,
+ p->cancellable,
+ on_open_end_session_dialog_ready,
+ self);
+}
+
+static void
+my_logout (IndicatorSessionActions * self)
+{
+ if (my_can_prompt (self))
+ show_end_session_dialog (INDICATOR_SESSION_ACTIONS_DBUS(self), END_SESSION_TYPE_LOGOUT);
+ else
+ logout_now_with_prompt (self);
+}
+
+
+static void
+my_restart (IndicatorSessionActions * self)
+{
+ if (my_can_prompt (self))
+ show_end_session_dialog (INDICATOR_SESSION_ACTIONS_DBUS(self), END_SESSION_TYPE_REBOOT);
+ else
+ restart_now (self);
+}
+
+static void
+my_shutdown (IndicatorSessionActions * self)
+{
+ /* NB: TYPE_REBOOT instead of TYPE_SHUTDOWN because
+ the latter adds lock & logout options in Unity... */
+ if (my_can_prompt (self))
+ show_end_session_dialog (INDICATOR_SESSION_ACTIONS_DBUS(self), END_SESSION_TYPE_REBOOT);
+ else
+ shutdown_now (self);
+}
+
+/***
+****
+***/
+
+static void
+run_outside_app (const char * cmd)
+{
+ GError * err = NULL;
+ g_debug ("%s calling \"%s\"", G_STRFUNC, cmd);
+ g_spawn_command_line_async (cmd, &err);
+ log_and_clear_error (&err, G_STRLOC, G_STRFUNC);
+}
+
+static void
+my_help (IndicatorSessionActions * self G_GNUC_UNUSED)
+{
+ run_outside_app ("yelp");
+}
+
+static void
+my_settings (IndicatorSessionActions * self G_GNUC_UNUSED)
+{
+ run_outside_app ("gnome-control-center");
+}
+
+static void
+my_about (IndicatorSessionActions * self G_GNUC_UNUSED)
+{
+ run_outside_app ("gnome-control-center info");
+}
+
+/***
+****
+***/
+
+static void
+my_switch_to_screensaver (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->screen_saver != NULL);
+
+ gnome_screen_saver_call_lock (p->screen_saver, p->cancellable, NULL, NULL);
+}
+
+static void
+my_switch_to_greeter (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->dm_seat != NULL);
+
+ display_manager_seat_call_switch_to_greeter (p->dm_seat, p->cancellable,
+ NULL, NULL);
+}
+
+static void
+my_switch_to_guest (IndicatorSessionActions * self)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->dm_seat != NULL);
+
+ display_manager_seat_call_switch_to_guest (p->dm_seat, "",
+ p->cancellable,
+ NULL, NULL);
+}
+
+static void
+my_switch_to_username (IndicatorSessionActions * self, const char * username)
+{
+ priv_t * p = INDICATOR_SESSION_ACTIONS_DBUS(self)->priv;
+
+ g_return_if_fail (p->dm_seat != NULL);
+
+ display_manager_seat_call_switch_to_user (p->dm_seat, username, "",
+ p->cancellable,
+ NULL, NULL);
+}
+
+static void
+my_dispose (GObject * o)
+{
+ IndicatorSessionActionsDbus * self = INDICATOR_SESSION_ACTIONS_DBUS (o);
+ priv_t * p = self->priv;
+
+ if (p->cancellable != NULL)
+ {
+ g_cancellable_cancel (p->cancellable);
+ g_clear_object (&p->cancellable);
+ }
+
+ g_clear_object (&p->lockdown_settings);
+ g_clear_object (&p->ck_manager);
+ g_clear_object (&p->upower);
+ g_clear_object (&p->screen_saver);
+ g_clear_object (&p->session_manager);
+ g_clear_object (&p->webcredentials);
+ g_clear_object (&p->end_session_dialog);
+ set_dm_seat (self, NULL);
+ set_ck_seat (self, NULL);
+
+ G_OBJECT_CLASS (indicator_session_actions_dbus_parent_class)->dispose (o);
+}
+
+static void
+my_finalize (GObject * o)
+{
+ /*IndicatorSessionActionsDbus * u = INDICATOR_SESSION_ACTIONS_DBUS (o);*/
+
+ G_OBJECT_CLASS (indicator_session_actions_dbus_parent_class)->finalize (o);
+}
+
+/***
+**** GObject Boilerplate
+***/
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_actions_dbus_class_init (IndicatorSessionActionsDbusClass * klass)
+{
+ GObjectClass * object_class;
+ IndicatorSessionActionsClass * actions_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = my_dispose;
+ object_class->finalize = my_finalize;
+
+ actions_class = INDICATOR_SESSION_ACTIONS_CLASS (klass);
+ actions_class->can_lock = my_can_lock;
+ actions_class->can_logout = my_can_logout;
+ actions_class->can_switch = my_can_switch;
+ actions_class->can_suspend = my_can_suspend;
+ actions_class->can_hibernate = my_can_hibernate;
+ actions_class->can_prompt = my_can_prompt;
+ actions_class->has_online_account_error = my_has_online_account_error;
+ actions_class->logout = my_logout;
+ actions_class->suspend = my_suspend;
+ actions_class->hibernate = my_hibernate;
+ actions_class->restart = my_restart;
+ actions_class->shutdown = my_shutdown;
+ actions_class->settings = my_settings;
+ actions_class->help = my_help;
+ actions_class->about = my_about;
+ actions_class->switch_to_screensaver = my_switch_to_screensaver;
+ actions_class->switch_to_greeter = my_switch_to_greeter;
+ actions_class->switch_to_guest = my_switch_to_guest;
+ actions_class->switch_to_username = my_switch_to_username;
+
+ g_type_class_add_private (klass, sizeof (IndicatorSessionActionsDbusPriv));
+}
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_actions_dbus_init (IndicatorSessionActionsDbus * self)
+{
+ priv_t * p;
+ GSettings * s;
+
+ p = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ INDICATOR_TYPE_SESSION_ACTIONS_DBUS,
+ IndicatorSessionActionsDbusPriv);
+ p->cancellable = g_cancellable_new ();
+ p->seat_allows_activation = TRUE;
+ self->priv = p;
+
+ s = g_settings_new ("org.gnome.desktop.lockdown");
+ g_signal_connect_swapped (s, "changed::disable-lock-screen",
+ G_CALLBACK(indicator_session_actions_notify_can_lock), self);
+ g_signal_connect_swapped (s, "changed::disable-log-out",
+ G_CALLBACK(indicator_session_actions_notify_can_logout), self);
+ g_signal_connect_swapped (s, "changed::disable-user-switching",
+ G_CALLBACK(indicator_session_actions_notify_can_switch), self);
+ p->lockdown_settings = s;
+
+ gnome_screen_saver_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.ScreenSaver",
+ "/org/gnome/ScreenSaver",
+ p->cancellable,
+ on_screensaver_proxy_ready,
+ self);
+
+ upower_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.UPower",
+ "/org/freedesktop/UPower",
+ p->cancellable,
+ on_upower_proxy_ready,
+ self);
+
+ gnome_session_manager_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ p->cancellable,
+ on_session_manager_proxy_ready,
+ self);
+
+ webcredentials_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ "com.canonical.indicators.webcredentials",
+ "/com/canonical/indicators/webcredentials",
+ p->cancellable,
+ on_webcredentials_proxy_ready,
+ self);
+
+ end_session_dialog_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ "com.canonical.Unity",
+ "/org/gnome/SessionManager/EndSessionDialog",
+ p->cancellable,
+ on_end_session_dialog_proxy_ready,
+ self);
+}
+
+/***
+**** Public
+***/
+
+IndicatorSessionActions *
+indicator_session_actions_dbus_new (void)
+{
+ gpointer o = g_object_new (INDICATOR_TYPE_SESSION_ACTIONS_DBUS, NULL);
+
+ return INDICATOR_SESSION_ACTIONS (o);
+}
+
+void
+indicator_session_actions_dbus_set_proxies (IndicatorSessionActionsDbus * self,
+ ConsoleKitManager * ck_manager,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * ck_seat)
+{
+ g_return_if_fail (INDICATOR_IS_SESSION_ACTIONS_DBUS(self));
+
+ self->priv->ck_manager = g_object_ref (ck_manager);
+
+ set_dm_seat (self, dm_seat);
+
+ set_ck_seat (self, ck_seat);
+}
diff --git a/src/backend-dbus/actions.h b/src/backend-dbus/actions.h
new file mode 100644
index 0000000..997dd73
--- /dev/null
+++ b/src/backend-dbus/actions.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __INDICATOR_SESSION_ACTIONS_DBUS_H__
+#define __INDICATOR_SESSION_ACTIONS_DBUS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../actions.h" /* parent class */
+#include "dbus-accounts.h"
+#include "dbus-consolekit-manager.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-session.h"
+#include "dbus-display-manager.h"
+
+
+G_BEGIN_DECLS
+
+#define INDICATOR_TYPE_SESSION_ACTIONS_DBUS (indicator_session_actions_dbus_get_type())
+#define INDICATOR_SESSION_ACTIONS_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_SESSION_ACTIONS_DBUS, IndicatorSessionActionsDbus))
+#define INDICATOR_SESSION_ACTIONS_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_SESSION_ACTIONS_DBUS, IndicatorSessionActionsDbusClass))
+#define INDICATOR_IS_SESSION_ACTIONS_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_SESSION_ACTIONS_DBUS))
+
+typedef struct _IndicatorSessionActionsDbus IndicatorSessionActionsDbus;
+typedef struct _IndicatorSessionActionsDbusPriv IndicatorSessionActionsDbusPriv;
+typedef struct _IndicatorSessionActionsDbusClass IndicatorSessionActionsDbusClass;
+
+/**
+ * An implementation of IndicatorSessionActions that gets its user information
+ * from org.freedesktop.ConsoleKit and org.freedesktop.Accounts over DBus.
+ */
+struct _IndicatorSessionActionsDbus
+{
+ /*< private >*/
+ IndicatorSessionActions parent;
+ IndicatorSessionActionsDbusPriv * priv;
+};
+
+struct _IndicatorSessionActionsDbusClass
+{
+ IndicatorSessionActionsClass parent_class;
+};
+
+GType indicator_session_actions_dbus_get_type (void);
+
+IndicatorSessionActions * indicator_session_actions_dbus_new (void);
+
+void indicator_session_actions_dbus_set_proxies (IndicatorSessionActionsDbus * self,
+ ConsoleKitManager * ck_manager,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * ck_seat);
+
+
+G_END_DECLS
+
+#endif /* __INDICATOR_SESSION_ACTIONS_DBUS_H__ */
diff --git a/src/backend-dbus/backend-dbus.c b/src/backend-dbus/backend-dbus.c
new file mode 100644
index 0000000..ea8f0ec
--- /dev/null
+++ b/src/backend-dbus/backend-dbus.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "actions.h"
+#include "backend-dbus.h"
+#include "guest.h"
+#include "users.h"
+#include "utils.h"
+
+struct dbus_world_data
+{
+ GCancellable * cancellable;
+ IndicatorSessionActionsDbus * actions;
+ IndicatorSessionUsersDbus * users;
+ IndicatorSessionGuestDbus * guest;
+};
+
+static void
+on_proxies_ready (ConsoleKitManager * ck_manager,
+ Accounts * account_manager,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * ck_seat,
+ ConsoleKitSession * ck_session,
+ AccountsUser * active_user G_GNUC_UNUSED,
+ const GError * error,
+ gpointer gdata)
+{
+ struct dbus_world_data * data = gdata;
+
+ if (error == NULL)
+ {
+ if (data->actions != NULL)
+ indicator_session_actions_dbus_set_proxies (data->actions,
+ ck_manager,
+ dm_seat,
+ ck_seat);
+
+ if (data->users != NULL)
+ indicator_session_users_dbus_set_proxies (data->users,
+ account_manager,
+ dm_seat,
+ ck_seat);
+
+ if (data->guest != NULL)
+ indicator_session_guest_dbus_set_proxies (data->guest,
+ account_manager,
+ dm_seat,
+ ck_seat,
+ ck_session);
+ }
+
+ g_free (data);
+}
+
+/***
+****
+***/
+
+void
+backend_get (GCancellable * cancellable,
+ IndicatorSessionActions ** setme_actions,
+ IndicatorSessionUsers ** setme_users,
+ IndicatorSessionGuest ** setme_guest)
+{
+ struct dbus_world_data * data;
+
+ data = g_new0 (struct dbus_world_data, 1);
+
+ if (setme_actions != NULL)
+ {
+ IndicatorSessionActions * actions;
+ actions = indicator_session_actions_dbus_new ();
+ data->actions = INDICATOR_SESSION_ACTIONS_DBUS (actions);
+
+ *setme_actions = actions;
+ }
+
+ if (setme_users != NULL)
+ {
+ IndicatorSessionUsers * users;
+ users = indicator_session_users_dbus_new ();
+ data->users = INDICATOR_SESSION_USERS_DBUS (users);
+
+ *setme_users = users;
+ }
+
+ if (setme_guest != NULL)
+ {
+ IndicatorSessionGuest * guest;
+ guest = indicator_session_guest_dbus_new ();
+ data->guest = INDICATOR_SESSION_GUEST_DBUS (guest);
+
+ *setme_guest = guest;
+ }
+
+ data->cancellable = g_object_ref (cancellable);
+
+ indicator_session_util_get_session_proxies (on_proxies_ready,
+ data->cancellable,
+ data);
+}
diff --git a/src/backend-dbus/backend-dbus.h b/src/backend-dbus/backend-dbus.h
new file mode 100644
index 0000000..daf6ac3
--- /dev/null
+++ b/src/backend-dbus/backend-dbus.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __INDICATOR_SESSION_BACKEND_DESKTOP_H__
+#define __INDICATOR_SESSION_BACKEND_DESKTOP_H__
+
+#include <gio/gio.h> /* GCancellable */
+
+#include "../actions.h"
+#include "../guest.h"
+#include "../users.h"
+
+G_BEGIN_DECLS
+
+void backend_get (GCancellable * cancellable,
+ IndicatorSessionActions ** setme_actions,
+ IndicatorSessionUsers ** setme_users,
+ IndicatorSessionGuest ** setme_guest);
+
+G_END_DECLS
+
+#endif
diff --git a/src/backend-dbus/com.canonical.indicators.webcredentials.xml b/src/backend-dbus/com.canonical.indicators.webcredentials.xml
new file mode 100644
index 0000000..d215081
--- /dev/null
+++ b/src/backend-dbus/com.canonical.indicators.webcredentials.xml
@@ -0,0 +1,82 @@
+<node>
+<!--
+ com.canonical.indicators.webcredentials:
+ @short_description: interface for handling login failures.
+
+ The service implementing this interface keeps track of login failures.
+ Failures are reported (usually by signon-ui) using the ReportFailure method,
+ are listed in the Failures property and can be removed by calling
+ RemoveFailures.
+
+ The ClearErrorStatus method can be called to clear the error indicator from
+ the system user menu.
+-->
+<interface name="com.canonical.indicators.webcredentials">
+ <!--
+ ReportFailure:
+ @account-id: the libaccounts ID of the account which failed to login.
+ @notification: dictionary of parameters for the OSD notification.
+
+ Inform the service about a failing account. The @account-id is added to the
+ list of the accounts in the Failures property, and a notification might be
+ displayed to the user.
+
+ The parameters currently recognized for the @notification argument are:
+ - DisplayName: string, description of the account (usually it's the
+ username)
+ -->
+ <method name="ReportFailure">
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ <arg name="account_id" type="u" direction="in"/>
+ <arg name="notification" type="a{sv}" direction="in"/>
+ </method>
+
+ <!--
+ RemoveFailures:
+ @account-ids: the libaccounts IDs of the accounts.
+
+ Remove the given account IDs from the list of the failed accounts.
+ -->
+ <method name="RemoveFailures">
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSet&lt;uint>"/>
+ <arg name="account_ids" type="au" direction="in"/>
+ </method>
+
+ <!--
+ ReauthenticateAccount:
+ @account-id: the libaccounts ID of the account.
+ @extra-parameters: dictionary of extra parameters (typically used to
+ specify a XWindowID).
+ @reauthenticated: %TRUE if the account could be reauthenticated and the
+ failure status has been cleared, %FALSE otherwise.
+
+ Tries to replay the failed authentications on the account. If all of them
+ succeed, then the account failure is cleared.
+ -->
+ <method name="ReauthenticateAccount">
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ <arg name="account_id" type="u" direction="in"/>
+ <arg name="extra_parameters" type="a{sv}" direction="in"/>
+ <arg name="reauthenticated" type="b" direction="out"/>
+ </method>
+
+ <!--
+ ClearErrorStatus:
+
+ Unsets the error indicator (if any) from the system user menu.
+ -->
+ <method name="ClearErrorStatus"/>
+
+ <!--
+ Failures: list of the libaccounts IDs of the failing accounts.
+ -->
+ <property name="Failures" type="au" access="read">
+ <annotation name="com.trolltech.QtDBus.QtTypeName" value="QSet&lt;uint>"/>
+ </property>
+
+ <!--
+ ErrorStatus: true if the indicator should display an error status.
+ -->
+ <property name="ErrorStatus" type="b" access="read"/>
+</interface>
+</node>
diff --git a/src/backend-dbus/display-manager.xml b/src/backend-dbus/display-manager.xml
new file mode 100644
index 0000000..07b5f29
--- /dev/null
+++ b/src/backend-dbus/display-manager.xml
@@ -0,0 +1,30 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node>
+ <interface name="org.freedesktop.DisplayManager.Seat">
+
+ <property name="CanSwitch" type="b" access="read"/>
+
+ <property name="HasGuestAccount" type="b" access="read"/>
+
+ <property name="Sessions" type="ao" access="read"/>
+
+ <!-- Show greeter to allow new login / switch users -->
+ <method name="SwitchToGreeter"/>
+
+ <!-- Switch to a user, starting a new display if required -->
+ <method name="SwitchToUser">
+ <arg name="username" direction="in" type="s"/>
+ <arg name="session_name" direction="in" type="s"/>
+ </method>
+
+ <!-- Switch to the guest user -->
+ <method name="SwitchToGuest">
+ <arg name="session_name" direction="in" type="s"/>
+ </method>
+
+ <method name='Lock'/>
+
+ </interface>
+
+</node>
diff --git a/src/backend-dbus/guest.c b/src/backend-dbus/guest.c
new file mode 100644
index 0000000..516ba00
--- /dev/null
+++ b/src/backend-dbus/guest.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include "dbus-accounts.h"
+#include "dbus-display-manager.h"
+#include "dbus-user.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-manager.h"
+#include "dbus-consolekit-session.h"
+
+#include "guest.h"
+
+struct _IndicatorSessionGuestDbusPriv
+{
+ GCancellable * cancellable;
+
+ Accounts * accounts;
+ AccountsUser * guest;
+ DisplayManagerSeat * display_manager_seat;
+
+ ConsoleKitSeat * seat;
+ ConsoleKitSession * active_session;
+ guint active_uid;
+
+ gboolean guest_is_active;
+ gboolean guest_is_allowed;
+};
+
+typedef IndicatorSessionGuestDbusPriv priv_t;
+
+G_DEFINE_TYPE (IndicatorSessionGuestDbus,
+ indicator_session_guest_dbus,
+ INDICATOR_TYPE_SESSION_GUEST)
+
+/***
+****
+***/
+
+static void
+check_for_active_guest (IndicatorSessionGuestDbus * self)
+{
+ gboolean guest_is_active;
+ priv_t * p = self->priv;
+
+ guest_is_active = (p->active_uid)
+ && (p->guest != NULL)
+ && (p->active_uid == accounts_user_get_uid (p->guest));
+
+ if (p->guest_is_active != guest_is_active)
+ {
+ p->guest_is_active = guest_is_active;
+
+ indicator_session_guest_notify_active (INDICATOR_SESSION_GUEST(self));
+ }
+}
+
+static void
+set_active_uid (IndicatorSessionGuestDbus * self, guint uid)
+{
+ self->priv->active_uid = uid;
+
+ check_for_active_guest (self);
+}
+
+static void
+on_active_uid_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ guint uid;
+ GError * err;
+ IndicatorSessionGuestDbus * self;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ uid = 0;
+ err = NULL;
+ self = INDICATOR_SESSION_GUEST_DBUS (gself);
+ console_kit_session_call_get_unix_user_finish (self->priv->active_session, &uid, res, &err);
+
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ set_active_uid (self, uid);
+ }
+}
+
+
+static void
+set_active_session (IndicatorSessionGuestDbus * self,
+ ConsoleKitSession * session)
+{
+ priv_t * p = self->priv;
+
+ if (p->active_session != NULL)
+ {
+ g_debug ("%s %s active_session refcount is %d before we unref", G_STRLOC, G_STRFUNC, G_OBJECT(self->priv->active_session)->ref_count);
+
+ g_clear_object (&p->active_session);
+ }
+
+ if (session != NULL)
+ {
+ p->active_session = g_object_ref (session);
+
+ console_kit_session_call_get_unix_user (session,
+ p->cancellable,
+ on_active_uid_ready,
+ self);
+ }
+}
+
+static void
+on_active_session_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ ConsoleKitSession * session;
+
+ err = NULL;
+ session = console_kit_session_proxy_new_finish (res, &err);
+
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ }
+ else
+ {
+ set_active_session (gself, session);
+ }
+
+ g_clear_object (&session);
+}
+
+
+static void
+on_active_session_changed (ConsoleKitSeat * seat G_GNUC_UNUSED,
+ const gchar * ssid,
+ IndicatorSessionGuestDbus * self)
+{
+ console_kit_session_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.ConsoleKit",
+ ssid,
+ self->priv->cancellable,
+ on_active_session_proxy_ready,
+ self);
+}
+
+static void
+set_seat (IndicatorSessionGuestDbus * self,
+ ConsoleKitSeat * seat)
+{
+ priv_t * p = self->priv;
+
+ if (p->seat != NULL)
+ {
+g_debug ("%s %s guest-dbus disconnecting from %p", G_STRLOC, G_STRFUNC, (void*)p->seat);
+ g_signal_handlers_disconnect_by_data (p->seat, self);
+g_debug ("%s %s seat refcount is %d before our unref", G_STRLOC, G_STRFUNC, G_OBJECT(p->seat)->ref_count);
+
+ g_clear_object (&p->seat);
+ }
+
+ if (seat != NULL)
+ {
+ p->seat = g_object_ref (seat);
+g_debug ("%s %s guest-dbus connecting to %p", G_STRLOC, G_STRFUNC, (void*)p->seat);
+
+ g_signal_connect (seat, "active-session-changed",
+ G_CALLBACK(on_active_session_changed), self);
+ }
+}
+
+/***
+****
+***/
+
+static void
+set_guest (IndicatorSessionGuestDbus * self,
+ AccountsUser * guest)
+{
+ priv_t * p = self->priv;
+
+ if (p->guest != NULL)
+ {
+ g_debug ("%s %s guest refcount is %d before we unref", G_STRLOC, G_STRFUNC, G_OBJECT(p->guest)->ref_count);
+
+ g_clear_object (&p->guest);
+ }
+
+ if (guest != NULL)
+ {
+ p->guest = g_object_ref (guest);
+ }
+
+ g_debug ("%s %s guest proxy is now %p", G_STRLOC, G_STRFUNC, (void*)guest);
+ indicator_session_guest_notify_logged_in (INDICATOR_SESSION_GUEST(self));
+
+ check_for_active_guest (self);
+}
+
+static void
+on_user_deleted (IndicatorSessionGuestDbus * self,
+ const gchar * path)
+{
+ AccountsUser * guest = self->priv->guest;
+ g_debug ("%s %s %s", G_STRLOC, G_STRFUNC, path);
+
+ if (guest != NULL)
+ if (!g_strcmp0 (path, g_dbus_proxy_get_object_path (G_DBUS_PROXY(guest))))
+ set_guest (self, NULL);
+}
+
+static gboolean
+is_guest (AccountsUser * user)
+{
+ /* a guest will look like this:
+ username:[guest-jjbEVV] realname:[Guest] system:[1] */
+ return IS_ACCOUNTS_USER(user)
+ && accounts_user_get_system_account (user)
+ && !g_ascii_strcasecmp (accounts_user_get_real_name(user), "Guest");
+}
+
+static void
+on_user_proxy_ready (GObject * o G_GNUC_UNUSED,
+ GAsyncResult * res,
+ gpointer self)
+{
+ GError * err;
+ AccountsUser * user;
+
+ err = NULL;
+ user = accounts_user_proxy_new_for_bus_finish (res, &err);
+
+ if (err != NULL)
+ {
+ g_warning ("%s: %s", G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else if (is_guest (user))
+ {
+ g_debug ("%s %s got guest", G_STRLOC, G_STRFUNC);
+ set_guest (INDICATOR_SESSION_GUEST_DBUS(self), user);
+ }
+
+ g_clear_object (&user);
+}
+
+static void
+create_user_proxy_for_path (IndicatorSessionGuestDbus * self,
+ const char * path)
+{
+ const char * name = "org.freedesktop.Accounts";
+ const GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES;
+ g_debug ("%s %s creating proxy for %s", G_STRLOC, G_STRFUNC, path);
+
+ accounts_user_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ flags, name, path,
+ self->priv->cancellable,
+ on_user_proxy_ready, self);
+}
+
+static void
+on_user_list_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gchar ** paths;
+
+ err = NULL;
+ paths = NULL;
+ accounts_call_list_cached_users_finish (ACCOUNTS(o), &paths, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ int i;
+
+ for (i=0; paths && paths[i]; ++i)
+ create_user_proxy_for_path (gself, paths[i]);
+
+ g_strfreev (paths);
+ }
+}
+
+static void
+set_account_manager (IndicatorSessionGuestDbus * self,
+ Accounts * a)
+{
+ g_debug ("%s %s setting account manager to %p", G_STRLOC, G_STRFUNC, (void*)a);
+
+ if (self->priv->accounts != NULL)
+ {
+g_debug ("%s %s guest-dbus disconnecting from %p", G_STRLOC, G_STRFUNC, (void*)self->priv->accounts);
+ g_signal_handlers_disconnect_by_data (self->priv->accounts, self);
+g_debug ("%s %s account manager refcount is %d before our unref", G_STRLOC, G_STRFUNC, G_OBJECT(self->priv->accounts)->ref_count);
+ g_clear_object (&self->priv->accounts);
+ }
+
+ if (a != NULL)
+ {
+ self->priv->accounts = g_object_ref (a);
+
+g_debug ("%s %s guest-dbus connecting to %p", G_STRLOC, G_STRFUNC, (void*)self->priv->accounts);
+ g_signal_connect_swapped (a, "user-added",
+ G_CALLBACK(create_user_proxy_for_path), self);
+
+ g_signal_connect_swapped (a, "user-deleted",
+ G_CALLBACK(on_user_deleted), self);
+
+ accounts_call_list_cached_users (a,
+ self->priv->cancellable,
+ on_user_list_ready,
+ self);
+ }
+}
+
+static void
+set_guest_is_allowed (IndicatorSessionGuestDbus * self, gboolean guest_is_allowed)
+{
+ priv_t * p = self->priv;
+ g_debug ("%s %s guest_is_allowed: %d", G_STRLOC, G_STRFUNC, (int)guest_is_allowed);
+
+ if (p->guest_is_allowed != guest_is_allowed)
+ {
+ p->guest_is_allowed = guest_is_allowed;
+
+ indicator_session_guest_notify_allowed (INDICATOR_SESSION_GUEST (self));
+ }
+}
+
+static void
+on_notify_has_guest_account (GObject * seat, GParamSpec * pspec G_GNUC_UNUSED, gpointer gself)
+{
+ set_guest_is_allowed (INDICATOR_SESSION_GUEST_DBUS (gself),
+ display_manager_seat_get_has_guest_account (DISPLAY_MANAGER_SEAT(seat)));
+}
+
+static void
+set_display_manager_seat (IndicatorSessionGuestDbus * self, DisplayManagerSeat * seat)
+{
+ priv_t * p = self->priv;
+
+ if (p->display_manager_seat != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (p->display_manager_seat, self);
+ g_debug ("%s %s before we unref, dm seat's refcount is %d", G_STRLOC, G_STRFUNC, G_OBJECT(p->display_manager_seat)->ref_count);
+ g_clear_object (&p->display_manager_seat);
+ }
+
+ if (seat != NULL)
+ {
+ p->display_manager_seat = g_object_ref (seat);
+
+ g_signal_connect (seat, "notify::has-guest-account", G_CALLBACK(on_notify_has_guest_account), self);
+
+ on_notify_has_guest_account (G_OBJECT(seat), NULL, self);
+ }
+}
+
+#if 0
+static void
+on_display_manager_seat_proxy_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ DisplayManagerSeat * seat;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ err = NULL;
+ seat = display_manager_seat_proxy_new_for_bus_finish (res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ set_display_manager_seat (INDICATOR_SESSION_GUEST_DBUS(gself), seat);
+ }
+
+ g_clear_object (&seat);
+}
+#endif
+
+static void
+on_switch_to_guest_done (GObject * o, GAsyncResult * res, gpointer unused G_GNUC_UNUSED)
+{
+ GError * err;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ err = NULL;
+ display_manager_seat_call_switch_to_guest_finish (DISPLAY_MANAGER_SEAT(o), res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+}
+
+/***
+**** Virtual Functions
+***/
+
+static void
+my_dispose (GObject * o)
+{
+ IndicatorSessionGuestDbus * self = INDICATOR_SESSION_GUEST_DBUS (o);
+
+ if (self->priv->cancellable != NULL)
+ {
+ g_cancellable_cancel (self->priv->cancellable);
+ g_clear_object (&self->priv->cancellable);
+ }
+
+ set_seat (self, NULL);
+ set_active_session (self, NULL);
+ set_account_manager (self, NULL);
+ set_display_manager_seat (self, NULL);
+ g_clear_object (&self->priv->guest);
+
+ G_OBJECT_CLASS (indicator_session_guest_dbus_parent_class)->dispose (o);
+}
+
+static void
+my_finalize (GObject * o)
+{
+ /*IndicatorSessionGuestDbus * u = INDICATOR_SESSION_GUEST_DBUS (o);*/
+
+ G_OBJECT_CLASS (indicator_session_guest_dbus_parent_class)->finalize (o);
+}
+
+static gboolean
+my_is_allowed (IndicatorSessionGuest * self)
+{
+ g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
+
+ return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest_is_allowed;
+}
+
+static gboolean
+my_is_logged_in (IndicatorSessionGuest * self)
+{
+ g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
+
+ return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest != NULL;
+}
+
+static gboolean
+my_is_active (IndicatorSessionGuest * self)
+{
+ g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
+
+ return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest_is_active;
+}
+
+static void
+my_switch_to_guest (IndicatorSessionGuest * self)
+{
+ priv_t * p;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ g_return_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self));
+
+ p = INDICATOR_SESSION_GUEST_DBUS(self)->priv;
+
+ if (p->display_manager_seat != NULL)
+ {
+ display_manager_seat_call_switch_to_guest (p->display_manager_seat,
+ "",
+ p->cancellable,
+ on_switch_to_guest_done,
+ self);
+ }
+}
+
+/***
+**** GObject Boilerplate
+***/
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_guest_dbus_class_init (IndicatorSessionGuestDbusClass * klass)
+{
+ GObjectClass * object_class;
+ IndicatorSessionGuestClass * guest_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = my_dispose;
+ object_class->finalize = my_finalize;
+
+ guest_class = INDICATOR_SESSION_GUEST_CLASS (klass);
+ guest_class->is_allowed = my_is_allowed;
+ guest_class->is_logged_in = my_is_logged_in;
+ guest_class->is_active = my_is_active;
+ guest_class->switch_to_guest = my_switch_to_guest;
+
+ g_type_class_add_private (klass, sizeof (IndicatorSessionGuestDbusPriv));
+}
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_guest_dbus_init (IndicatorSessionGuestDbus * self)
+{
+ priv_t * p;
+
+ p = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ INDICATOR_TYPE_SESSION_GUEST_DBUS,
+ IndicatorSessionGuestDbusPriv);
+ p->cancellable = g_cancellable_new ();
+ self->priv = p;
+
+#if 0
+ display_manager_seat_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.DisplayManager",
+ g_getenv ("XDG_SEAT_PATH"),
+ self->priv->cancellable,
+ on_display_manager_seat_proxy_ready,
+ self);
+#endif
+}
+
+/***
+**** Public
+***/
+
+IndicatorSessionGuest *
+indicator_session_guest_dbus_new (void)
+{
+ gpointer o = g_object_new (INDICATOR_TYPE_SESSION_GUEST_DBUS, NULL);
+
+ return INDICATOR_SESSION_GUEST (o);
+}
+
+void
+indicator_session_guest_dbus_set_proxies (IndicatorSessionGuestDbus * self,
+ Accounts * accounts,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * seat,
+ ConsoleKitSession * session)
+{
+ g_return_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self));
+ g_debug ("%s %s accounts %p seat %p session %p", G_STRLOC, G_STRFUNC, (void*)accounts, (void*)seat, (void*)session);
+
+ set_account_manager (self, accounts);
+ set_display_manager_seat (self, dm_seat);
+ set_seat (self, seat);
+ set_active_session (self, session);
+}
diff --git a/src/backend-dbus/guest.h b/src/backend-dbus/guest.h
new file mode 100644
index 0000000..03b6b28
--- /dev/null
+++ b/src/backend-dbus/guest.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GUEST_DBUS_H__
+#define __GUEST_DBUS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../guest.h" /* parent class */
+#include "dbus-accounts.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-session.h"
+#include "dbus-display-manager.h"
+
+
+G_BEGIN_DECLS
+
+#define INDICATOR_TYPE_SESSION_GUEST_DBUS (indicator_session_guest_dbus_get_type())
+#define INDICATOR_SESSION_GUEST_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_SESSION_GUEST_DBUS, IndicatorSessionGuestDbus))
+#define INDICATOR_SESSION_GUEST_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_SESSION_GUEST_DBUS, IndicatorSessionGuestDbusClass))
+#define INDICATOR_IS_SESSION_GUEST_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_SESSION_GUEST_DBUS))
+
+typedef struct _IndicatorSessionGuestDbus IndicatorSessionGuestDbus;
+typedef struct _IndicatorSessionGuestDbusPriv IndicatorSessionGuestDbusPriv;
+typedef struct _IndicatorSessionGuestDbusClass IndicatorSessionGuestDbusClass;
+
+/**
+ * An implementation of IndicatorSessionGuest that gets its user information
+ * from org.freedesktop.ConsoleKit and org.freedesktop.Accounts over DBus.
+ */
+struct _IndicatorSessionGuestDbus
+{
+ /*< private >*/
+ IndicatorSessionGuest parent;
+ IndicatorSessionGuestDbusPriv * priv;
+};
+
+struct _IndicatorSessionGuestDbusClass
+{
+ IndicatorSessionGuestClass parent_class;
+};
+
+GType indicator_session_guest_dbus_get_type (void);
+
+IndicatorSessionGuest * indicator_session_guest_dbus_new (void);
+
+void indicator_session_guest_dbus_set_proxies (IndicatorSessionGuestDbus *,
+ Accounts *,
+ DisplayManagerSeat *,
+ ConsoleKitSeat *,
+ ConsoleKitSession *);
+
+G_END_DECLS
+
+#endif
diff --git a/src/backend-dbus/org.freedesktop.Accounts.User.xml b/src/backend-dbus/org.freedesktop.Accounts.User.xml
new file mode 100644
index 0000000..53f54d4
--- /dev/null
+++ b/src/backend-dbus/org.freedesktop.Accounts.User.xml
@@ -0,0 +1,744 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" >
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.Accounts.User">
+
+ <method name="SetUserName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="name" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new username.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users username. Note that it is usually not allowed
+ to have multiple users with the same username.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the username of any user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetRealName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="name" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new name, typically in the form "Firstname Lastname".
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users real name.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own name</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the name of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetEmail">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="email" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new email address.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users email address.
+ </doc:para>
+ <doc:para>
+ Note that setting an email address in the AccountsService is
+ not the same as configuring a mail client. Mail clients might
+ default to email address that is configured here, though.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own email address</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the email address of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetLanguage">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="language" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new language, as a locale specification like "de_DE.UTF-8".
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users language.
+ </doc:para>
+ <doc:para>
+ The expectation is that display managers will start the
+ users session with this locale.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own language</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the language of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetXSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_x_session"/>
+ <arg name="x_session" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new xsession to start (e.g. "gnome")
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users x session.
+ </doc:para>
+ <doc:para>
+ The expectation is that display managers will log the user in to this
+ specified session, if available.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own language</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the language of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetLocation">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="location" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new location as a freeform string.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users location.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own location</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the location of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetHomeDirectory">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="homedir" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new homedir as an absolute path.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users home directory.
+ </doc:para>
+ <doc:para>
+ Note that changing the users home directory moves all the content
+ from the old location to the new one, and is potentially an
+ expensive operation.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the home directory of a user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetShell">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="shell" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The new user shell.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users shell.
+ </doc:para>
+ <doc:para>
+ Note that setting the shell to a non-allowed program may
+ prevent the user from logging in.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the shell of a user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetIconFile">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="filename" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The absolute filename of a png file to use as the users icon.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets the users icon.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+ <doc:definition>To change his own icon</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the icon of another user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetLocked">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="locked" direction="in" type="b">
+ <doc:doc>
+ <doc:summary>
+ Whether to lock or unlock the users account.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Locks or unlocks a users account.
+ </doc:para>
+ <doc:para>
+ Locking an account prevents the user from logging in.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To lock or unlock user accounts</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetAccountType">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="accountType" direction="in" type="i">
+ <doc:doc>
+ <doc:summary>
+ The new account type, encoded as an integer:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Standard user</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Administrator</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Changes the users account type.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change an account type</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetPasswordMode">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="mode" direction="in" type="i">
+ <doc:doc>
+ <doc:summary>
+ The new password mode, encoded as an integer:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Regular password</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Password must be set at next login</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>No password</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Changes the users password mode.
+ </doc:para>
+ <doc:para>
+ Note that changing the password mode has the side-effect of
+ unlocking the account.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change a users password mode</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetPassword">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="password" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The crypted password.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="hint" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>
+ The password hint.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Sets a new password for this user.
+ </doc:para>
+ <doc:para>
+ Note that setting a password has the side-effect of
+ unlocking the account.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+ <doc:definition>To change the password of a user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="SetAutomaticLogin">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="enabled" direction="in" type="b">
+ <doc:doc>
+ <doc:summary>
+ Whether to enable automatic login for this user.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enables or disables automatic login for a user.
+ </doc:para>
+ <doc:para>
+ Note that usually only one user can have automatic login
+ enabled, so turning it on for a user will disable it for
+ the previously configured autologin user.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs one of the following PolicyKit authorizations:
+ <doc:list>
+ <doc:item>
+ <doc:term>org.freedesktop.accounts.set-login-option</doc:term>
+ <doc:definition>To change the login screen configuration</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <property name="Uid" type="t" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The uid of the user.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="UserName" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The username of the user.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="RealName" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users real name.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="AccountType" type="i" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users account type, encoded as an integer:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Standard user</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Administrator</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="HomeDirectory" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users home directory.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="Shell" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users shell.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="Email" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The email address.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="Language" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users language, as a locale specification like "de_DE.UTF-8".
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="XSession" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users x session.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="Location" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The users location.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="LoginFrequency" type="t" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ How often the user has logged in.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="IconFile" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The filename of a png file containing the users icon.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="Locked" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether the users account is locked.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="PasswordMode" type="i" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The password mode for the user account, encoded as an integer:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Regular password</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Password must be set at next login</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>No password</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="PasswordHint" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The password hint for the user.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="AutomaticLogin" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether automatic login is enabled for the user.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="SystemAccount" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether this is a 'system' account, like 'root' or 'nobody'.
+ System accounts should normally not appear in lists of
+ users, and ListCachedUsers will not include such accounts.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <signal name="Changed">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when the user is changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.freedesktop.Accounts.xml b/src/backend-dbus/org.freedesktop.Accounts.xml
new file mode 100644
index 0000000..9c19761
--- /dev/null
+++ b/src/backend-dbus/org.freedesktop.Accounts.xml
@@ -0,0 +1,194 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" >
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="org.freedesktop.Accounts">
+
+ <!-- ************************************************************ -->
+
+ <method name="ListCachedUsers">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="users" direction="out" type="ao">
+ <doc:doc><doc:summary>Object paths of cached users</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Lists users which have logged into the system locally before.
+ This is not meant to return an exhaustive list of all users.
+ It is possible for <doc:ref type="method" to="Accounts.FindUserByName">FindUserByName()</doc:ref>
+ to return a user that's not on the list.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="FindUserById">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="id" direction="in" type="x">
+ <doc:doc><doc:summary>The uid to look up</doc:summary></doc:doc>
+ </arg>
+ <arg name="user" direction="out" type="o">
+ <doc:doc><doc:summary>Object path of user</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Finds a user by uid.
+ </doc:para>
+ </doc:description>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if no user with the given uid exists</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="FindUserByName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="name" direction="in" type="s">
+ <doc:doc><doc:summary>The username to look up</doc:summary></doc:doc>
+ </arg>
+ <arg name="user" direction="out" type="o">
+ <doc:doc><doc:summary>Object path of user</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Finds a user by its username.
+ </doc:para>
+ </doc:description>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if no user with the given username exists</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="CreateUser">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="name" direction="in" type="s">
+ <doc:doc><doc:summary>The username for the new user</doc:summary></doc:doc>
+ </arg>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="fullname" direction="in" type="s">
+ <doc:doc><doc:summary>The real name for the new user</doc:summary></doc:doc>
+ </arg>
+ <arg name="user" direction="out" type="o">
+ <doc:doc><doc:summary>Object path of the new user</doc:summary></doc:doc>
+ </arg>
+ <arg name="accountType" direction="in" type="i">
+ <doc:doc>
+ <doc:summary>The account type, encoded as an integer</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Creates a new user account.
+ </doc:para>
+ <doc:para>
+ The accountType argument can take the following values:
+ </doc:para>
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Standard user</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Administrator</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>Supervised user</doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:description>
+ <doc:permission>
+ The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="DeleteUser">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="id" direction="in" type="x">
+ <doc:doc><doc:summary>The uid to delete</doc:summary></doc:doc>
+ </arg>
+ <arg name="removeFiles" direction="in" type="b">
+ <doc:doc><doc:summary>Whether to remove the users files</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Deletes a user account.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <signal name="UserAdded">
+ <arg name="user" type="o">
+ <doc:doc><doc:summary>Object path of the user that was added.</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a user is added.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <signal name="UserDeleted">
+ <arg name="user" type="o">
+ <doc:doc><doc:summary>Object path of the user that was deleted.</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a user is deleted.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <signal name="UserChanged">
+ <arg name="user" type="o">
+ <doc:doc><doc:summary>Object path of the user that was changed.</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a user is changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <property name="DaemonVersion" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The version of the running daemon.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.freedesktop.ConsoleKit.Manager.xml b/src/backend-dbus/org.freedesktop.ConsoleKit.Manager.xml
new file mode 100644
index 0000000..f903b55
--- /dev/null
+++ b/src/backend-dbus/org.freedesktop.ConsoleKit.Manager.xml
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/org/freedesktop/ConsoleKit/Manager"
+ xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
+>
+
+ <interface name="org.freedesktop.ConsoleKit.Manager">
+ <method name="Restart">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method initiates a request to restart (ie. reboot) the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="CanRestart">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="can_restart" type="b" direction="out"/>
+ </method>
+
+ <method name="Stop">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method initiates a request to stop (ie. shutdown) the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="CanStop">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="can_stop" type="b" direction="out"/>
+ </method>
+
+ <method name="OpenSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The secret cookie that is used to identify the new session</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method requests that a new <doc:ref type="interface" to="Session">Session</doc:ref>
+ be created for the calling process. The properties of this new Session are set automatically
+ from information collected about the calling process.
+ </doc:para>
+ <doc:para>This new session exists until the calling process disconnects from the system bus or
+ calls <doc:ref type="method" to="Manager.CloseSession">CloseSession()</doc:ref>.
+ </doc:para>
+ <doc:para>It is the responsibility of the calling process to set the environment variable
+ XDG_SESSION_COOKIE to the value of the returned cookie. This cookie should only
+ be made available to child processes of the caller so that they may be identified
+ as members of this session.
+ </doc:para>
+ <doc:para>See this simple example:
+ <doc:example language="c" title="simple example"><doc:code>
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+
+ message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ "org.freedesktop.ConsoleKit.Manager",
+ "OpenSession");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&amp;error);
+ reply = dbus_connection_send_with_reply_and_block (connector->connection,
+ message,
+ -1,
+ &amp;error);
+ if (reply == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&amp;error);
+ if (! dbus_message_get_args (reply,
+ &amp;error,
+ DBUS_TYPE_STRING, &amp;cookie,
+ DBUS_TYPE_INVALID)) {
+ goto out;
+ }
+
+ </doc:code></doc:example></doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="method" to="Manager.OpenSessionWithParameters">OpenSessionWithParameters()</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="OpenSessionWithParameters">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="parameters" direction="in" type="a(sv)">
+ <doc:doc>
+ <doc:summary>An array of sets of property names and values</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="cookie" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The secret cookie that is used to identify the new session</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method requests that a new <doc:ref type="interface" to="Session">Session</doc:ref>
+ be created for the calling process. The properties of this new Session are from the
+ parameters provided.
+ </doc:para>
+ <doc:para>This new session exists until the calling process disconnects from the system bus or
+ calls <doc:ref type="method" to="Manager.CloseSession">CloseSession()</doc:ref>.
+ </doc:para>
+ <doc:para>It is the responsibility of the calling process to set the environment variable
+ XDG_SESSION_COOKIE to the value of the returned cookie. This cookie should only
+ be made available to child processes of the caller so that they may be identified
+ as members of this session.
+ </doc:para>
+ <doc:para>See the <doc:ref type="interface" to="Session">Session</doc:ref> properties for a list of valid parameters.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="Session">org.freedesktop.ConsoleKit.Session</doc:ref></doc:seealso>
+ <doc:permission>This method is restricted to privileged users by D-Bus policy.</doc:permission>
+ </doc:doc>
+ </method>
+ <method name="CloseSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>The secret cookie that is used to identify the session</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="result" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>Whether the session was successfully closed</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method is used to close the session identified by the supplied cookie.
+ </doc:para>
+ <doc:para>The session can only be closed by the same process that opened the session.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetSeats">
+ <arg name="seats" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of Seat IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="Seat">Seats</doc:ref>
+ that are currently present on the system.</doc:para>
+ <doc:para>Each Seat ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="Seat">Seat</doc:ref> interface.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="Seat">org.freedesktop.ConsoleKit.Seat</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <method name="GetSessions">
+ <arg name="sessions" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of Session IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="Session">Sessions</doc:ref>
+ that are currently present on the system.</doc:para>
+ <doc:para>Each Session ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="Session">Session</doc:ref> interface.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="Session">org.freedesktop.ConsoleKit.Session</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <method name="GetSessionForCookie">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>The secret cookie that is used to identify the session</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>The object identifier for the current session</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns the session ID that is associated with the specified cookie.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSessionForUnixProcess">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="pid" direction="in" type="u">
+ <doc:doc>
+ <doc:summary>The POSIX process ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>The object identifier for the current session</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Attempts to determine the session ID for the specified
+ POSIX process ID (pid).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetCurrentSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>The object identifier for the current session</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Attempts to determine the session ID that the caller belongs to.
+ </doc:para>
+ <doc:para>See this example of using dbus-send:
+ <doc:example language="shell" title="shell example"><doc:code>
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetCurrentSession
+ </doc:code></doc:example></doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSessionsForUnixUser">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="uid" direction="in" type="u">
+ <doc:doc>
+ <doc:summary>POSIX User identification</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="sessions" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of Session IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="Session">Sessions</doc:ref>
+ that are currently open for the specified user.</doc:para>
+ <doc:para>Each Session ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="Session">Session</doc:ref> interface.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSessionsForUser">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="uid" direction="in" type="u">
+ <doc:doc>
+ <doc:summary>User identification</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="sessions" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of Session IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="Session">Sessions</doc:ref>
+ that are currently open for the specified user.</doc:para>
+ <doc:para>Each Session ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="Session">Session</doc:ref> interface.</doc:para>
+ </doc:description>
+ <doc:deprecated version="0.1.3" instead="GetSessionsForUnixUser"/>
+ </doc:doc>
+ </method>
+
+ <method name="GetSystemIdleHint">
+ <arg name="idle_hint" type="b" direction="out">
+ <doc:doc>
+ <doc:summary>The value of the system-idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns TRUE if the <doc:ref type="property" to="Session:idle-hint">idle-hint</doc:ref>
+ property of every open session is TRUE or if there are no open sessions.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSystemIdleSinceHint">
+ <arg name="iso8601_datetime" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>An ISO 8601 format date-type string</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns an ISO 8601 date-time string that corresponds to
+ the time of the last change of the system-idle-hint.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <signal name="SeatAdded">
+ <arg name="sid" type="o">
+ <doc:doc>
+ <doc:summary>The Seat ID for the added seat</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a Seat has been added to the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="SeatRemoved">
+ <arg name="sid" type="o">
+ <doc:doc>
+ <doc:summary>The Seat ID for the removed seat</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a Seat has been removed from the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="SystemIdleHintChanged">
+ <arg name="hint" type="b">
+ <doc:doc>
+ <doc:summary>The value of the system-idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the value of the system-idle-hint has changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.freedesktop.ConsoleKit.Seat.xml b/src/backend-dbus/org.freedesktop.ConsoleKit.Seat.xml
new file mode 100644
index 0000000..58c2ce7
--- /dev/null
+++ b/src/backend-dbus/org.freedesktop.ConsoleKit.Seat.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.ConsoleKit.Seat">
+ <doc:doc>
+ <doc:description>
+ <doc:para>A seat is a collection of sessions and a set of hardware (usually at
+least a keyboard and mouse). Only one session may be active on a
+seat at a time.</doc:para>
+ </doc:description>
+ </doc:doc>
+
+ <method name="GetId">
+ <arg name="sid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Seat ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns the ID for Seat.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetSessions">
+ <arg name="sessions" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of Session IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="Session">Sessions</doc:ref>
+ that are currently attached to this seat.</doc:para>
+ <doc:para>Each Session ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="Session">Session</doc:ref> interface.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetDevices">
+ <arg name="devices" direction="out" type="a(ss)">
+ <doc:doc>
+ <doc:summary>an array of devices</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the devices
+ that are currently associated with this seat.</doc:para>
+ <doc:para>Each device is an D-Bus structure that represents
+ the device type and the device id.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetActiveSession">
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Gets the Session ID that is currently active on this Seat.</doc:para>
+ <doc:para>Returns NULL if there is no active session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="CanActivateSessions">
+ <arg name="can_activate" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if seat supports session activation</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Used to determine whether the seat supports session activation.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="ActivateSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="ssid" direction="in" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Attempt to activate the specified session. In most
+ cases, if successful, this will cause the session to
+ become visible and take control of the hardware that is
+ associated with this seat.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="method" to="Session.Activate">Activate()</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <signal name="ActiveSessionChanged">
+ <arg name="ssid" type="s">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the active session has changed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="SessionAdded">
+ <arg name="ssid" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a session has been added to the seat.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="SessionRemoved">
+ <arg name="ssid" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a session has been removed from the seat.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="DeviceAdded">
+ <arg name="device" type="(ss)">
+ <doc:doc>
+ <doc:summary>Device structure</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a device has been associated with the seat.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="DeviceRemoved">
+ <arg name="device" type="(ss)">
+ <doc:doc>
+ <doc:summary>Device structure</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a device has been dissociated from the seat.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.freedesktop.ConsoleKit.Session.xml b/src/backend-dbus/org.freedesktop.ConsoleKit.Session.xml
new file mode 100644
index 0000000..b6e1cdb
--- /dev/null
+++ b/src/backend-dbus/org.freedesktop.ConsoleKit.Session.xml
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.ConsoleKit.Session">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Session objects represent and store information
+ related to a user session.
+ </doc:para>
+ <doc:para>The properties associated with the Session
+ specifically refer to the properties of the "session leader".
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ <method name="GetId">
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the ID for Session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSeatId">
+ <arg name="sid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Seat ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the ID for the Seat the Session is
+ attached to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="Seat">org.freedesktop.ConsoleKit.Seat</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetSessionType">
+ <arg name="type" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>Session type</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns the type of the session.</doc:para>
+ <doc:para>Warning: we haven't yet defined the allowed values for this property.
+ It is probably best to avoid this until we do.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:session-type">session-type</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetUser">
+ <arg name="uid" direction="out" type="u">
+ <doc:doc>
+ <doc:summary>User ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the user that the session belongs to.</doc:para>
+ </doc:description>
+ <doc:deprecated version="0.1.3" instead="GetUnixUser"/>
+ <doc:seealso><doc:ref type="property" to="Session:user">user</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetUnixUser">
+ <arg name="uid" direction="out" type="u">
+ <doc:doc>
+ <doc:summary>POSIX User ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the POSIX user ID that the session belongs to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:unix-user">unix-user</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetX11Display">
+ <arg name="display" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the X11 display</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the X11 DISPLAY for this session
+ if one is present.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:x11-display">x11-display</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetX11DisplayDevice">
+ <arg name="x11_display_device" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the X11 display device</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the display device (aka TTY) that the
+ X11 display for the session is connected to. If there is no x11-display set then this value
+ is undefined.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:x11-display-device">x11-display-device</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetDisplayDevice">
+ <arg name="display_device" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the display device</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the display device (aka TTY) that the
+ session is connected to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:display-device">display-device</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetRemoteHostName">
+ <arg name="remote_host_name" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The remote host name</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the remote host name for the session.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:remote-host-name">remote-host-name</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetLoginSessionId">
+ <arg name="login_session_id" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the native system login session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the login session ID that the
+ underlying system uses to enforce session boundaries. If there is no login session ID
+ set then this value is an empty string.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="IsActive">
+ <arg name="active" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is active, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns whether the session is active on the Seat that
+ it is attached to.</doc:para>
+ <doc:para>If the session is not attached to a seat this value is undefined.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:active">active</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="IsLocal">
+ <arg name="local" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is local, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns whether the session is local</doc:para>
+ <doc:para>FIXME: we need to come up with a concrete definition for this value.
+ It was originally used as a way to identify XDMCP sessions that originate
+ from a remote system.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:is-local">is-local</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetCreationTime">
+ <arg name="iso8601_datetime" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>An ISO 8601 format date-type string</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns an ISO 8601 date-time string that corresponds to
+ the time that the session was opened.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Activate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Attempt to activate the this session. In most
+ cases, if successful, this will cause the session to
+ become visible and become active on the seat that it
+ is attached to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="method" to="Seat.ActivateSession">Seat.ActivateSession()</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="Lock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This will cause a <doc:ref type="signal" to="Session::Lock">Lock</doc:ref>
+ signal to be emitted for this session.
+ </doc:para>
+ </doc:description>
+ <doc:permission>This method is restricted to privileged users by D-Bus policy.</doc:permission>
+ <doc:seealso><doc:ref type="signal" to="Session::Lock">Lock signal</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="Unlock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This will cause an <doc:ref type="signal" to="Session::Unlock">Unlock</doc:ref>
+ signal to be emitted for this session.
+ </doc:para>
+ <doc:para>This can be used by login managers to unlock a session before it is
+ re-activated during fast-user-switching.
+ </doc:para>
+ </doc:description>
+ <doc:permission>This method is restricted to privileged users by D-Bus policy.</doc:permission>
+ <doc:seealso><doc:ref type="signal" to="Session::Unlock">Unlock signal</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <method name="GetIdleHint">
+ <arg name="idle_hint" type="b" direction="out">
+ <doc:doc>
+ <doc:summary>The value of the idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Gets the value of the <doc:ref type="property" to="Session:idle-hint">idle-hint</doc:ref>
+ property.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:idle-hint">idle-hint</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetIdleSinceHint">
+ <arg name="iso8601_datetime" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>An ISO 8601 format date-type string</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns an ISO 8601 date-time string that corresponds to
+ the time of the last change of the idle-hint.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="SetIdleHint">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="idle_hint" type="b" direction="in">
+ <doc:doc>
+ <doc:summary>boolean value to set the idle-hint to</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This may be used by the session to indicate that
+ it is idle.
+ </doc:para>
+ <doc:para>Use of this method is restricted to the user
+ that owns the session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <signal name="ActiveChanged">
+ <arg name="is_active" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is active, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the active property has changed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="IdleHintChanged">
+ <arg name="hint" type="b">
+ <doc:doc>
+ <doc:summary>the new value of idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the idle-hint property has changed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="Lock">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted in response to a call to the <doc:ref type="method" to="Session.Lock">Lock()</doc:ref> method.</doc:para>
+ <doc:para>It is intended that the screensaver for the session should lock the screen in response to this signal.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="Unlock">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted in response to a call to the <doc:ref type="method" to="Session.Unlock">Unlock()</doc:ref> method.</doc:para>
+ <doc:para>It is intended that the screensaver for the session should unlock the screen in response to this signal.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <property name="unix-user" type="u" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The user assigned to the session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="user" type="u" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The user assigned to the session.</doc:para>
+ </doc:description>
+ <doc:deprecated version="0.1.3" instead="unix-user"/>
+ </doc:doc>
+ </property>
+ <property name="session-type" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The type of the session.</doc:para>
+ <doc:para>Warning: we haven't yet defined the allowed values for this property.
+ It is probably best to avoid this until we do.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="remote-host-name" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The remote host name for the session.
+ </doc:para>
+ <doc:para>This will be set in situations where the session is
+ opened and controlled from a remote system.
+ </doc:para>
+ <doc:para>For example, this value will be set when the
+ session is created from an SSH or XDMCP connection.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="display-device" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The display device (aka TTY) that the
+ session is connected to.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="x11-display" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Value of the X11 DISPLAY for this session
+ if one is present.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="x11-display-device" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The display device (aka TTY) that the X11 display for the
+ session is connected to. If there is no x11-display set then
+ this value is undefined.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="active" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether the session is active on the Seat that
+ it is attached to.</doc:para>
+ <doc:para>If the session is not attached to a seat this value is undefined.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="is-local" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether the session is local</doc:para>
+ <doc:para>FIXME: we need to come up with a concrete definition for this value.
+ It was originally used as a way to identify XDMCP sessions that originate
+ from a remote system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="idle-hint" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This is a hint used to indicate that the session may be idle.
+ </doc:para>
+ <doc:para>
+ For sessions with a <doc:ref type="property" to="Session:x11-display">x11-display</doc:ref> set (ie. graphical
+ sessions), it is up to each session to delegate the
+ responsibility for updating this value. Typically, the
+ screensaver will set this.
+ </doc:para>
+ <doc:para>However, for non-graphical sessions with a <doc:ref type="property" to="Session:display-device">display-device</doc:ref> set
+ the Session object itself will periodically update this value based
+ on the activity detected on the display-device itself.
+ </doc:para>
+ <doc:para>
+ This should not be considered authoritative.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.gnome.ScreenSaver.xml b/src/backend-dbus/org.gnome.ScreenSaver.xml
new file mode 100644
index 0000000..c21fdc5
--- /dev/null
+++ b/src/backend-dbus/org.gnome.ScreenSaver.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.gnome.ScreenSaver">
+
+ <method name="Lock">
+ </method>
+
+ <method name="SimulateUserActivity">
+ </method>
+
+ </interface>
+
+</node>
diff --git a/src/backend-dbus/org.gnome.SessionManager.EndSessionDialog.xml b/src/backend-dbus/org.gnome.SessionManager.EndSessionDialog.xml
new file mode 100644
index 0000000..5392de0
--- /dev/null
+++ b/src/backend-dbus/org.gnome.SessionManager.EndSessionDialog.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="org.gnome.SessionManager.EndSessionDialog">
+ <method name="Open">
+ <arg type="u" name="type" direction="in">
+ <doc:doc>
+ <doc:summary>
+ The type of dialog to show.
+ 0 for logout, 1 for shutdown, 2 for restart.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="u" name="timestamp" direction="in">
+ <doc:doc>
+ <doc:summary>
+ Timestamp of the user-initiated event which triggered
+ the call, or 0 if the call was not triggered by an event.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="u" name="seconds_to_stay_open" direction="in">
+ <doc:doc>
+ <doc:summary>
+ The number of seconds which the dialog should stay open
+ before automatic action is taken.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="ao" name="inhibitor_object_paths" direction="in">
+ <doc:doc>
+ <doc:summary>
+ The object paths of all inhibitors that are registered
+ for the action.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:summary>
+ This function opens a dialog which asks the user for confirmation
+ of a logout, poweroff or reboot action. The dialog has a timeout
+ after which the action is automatically taken, and it should show
+ the inhibitors to the user.
+ </doc:summary>
+ </doc:doc>
+ </method>
+ <signal name="ConfirmedLogout" />
+ <signal name="ConfirmedReboot" />
+ <signal name="ConfirmedShutdown" />
+ <signal name="Canceled" />
+ <signal name="Closed" />
+ </interface>
+</node>
diff --git a/src/backend-dbus/org.gnome.SessionManager.xml b/src/backend-dbus/org.gnome.SessionManager.xml
new file mode 100644
index 0000000..eb69180
--- /dev/null
+++ b/src/backend-dbus/org.gnome.SessionManager.xml
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="org.gnome.SessionManager">
+
+ <!-- Initialization phase interfaces -->
+
+ <method name="Setenv">
+ <arg name="variable" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>The variable name</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="value" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>The value</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Adds the variable name to the application launch environment with the specified value. May only be used during the Session Manager initialization phase.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetLocale">
+ <arg name="category" type="i" direction="in">
+ <doc:doc>
+ <doc:summary>The locale category</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="value" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>The value</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Reads the current state of the specific locale category.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="InitializationError">
+ <arg name="message" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>The error message</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="fatal" type="b" direction="in">
+ <doc:doc>
+ <doc:summary>Whether the error should be treated as fatal</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>May be used by applications launched during the Session Manager initialization phase to indicate there was a problem.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- Running phase interfaces -->
+
+ <method name="RegisterClient">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="app_id" direction="in">
+ <doc:doc>
+ <doc:summary>The application identifier</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="s" name="client_startup_id" direction="in">
+ <doc:doc>
+ <doc:summary>Client startup identifier</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="o" name="client_id" direction="out">
+ <doc:doc>
+ <doc:summary>The object path of the newly registered client</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Register the caller as a Session Management client.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="UnregisterClient">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="o" name="client_id" direction="in">
+ <doc:doc>
+ <doc:summary>The object path of the client</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Unregister the specified client from Session Management.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Inhibit">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="app_id" direction="in">
+ <doc:doc>
+ <doc:summary>The application identifier</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="u" name="toplevel_xid" direction="in">
+ <doc:doc>
+ <doc:summary>The toplevel X window identifier</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="s" name="reason" direction="in">
+ <doc:doc>
+ <doc:summary>The reason for the inhibit</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="u" name="flags" direction="in">
+ <doc:doc>
+ <doc:summary>Flags that specify what should be inhibited</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="u" name="inhibit_cookie" direction="out">
+ <doc:doc>
+ <doc:summary>The cookie</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:summary>
+ Proactively indicates that the calling application is performing an action that should not be interrupted and sets a reason to be displayed to the user when an interruption is about to take placea.
+ </doc:summary>
+ <doc:description>
+ <doc:para>Applications should invoke this method when they begin an operation that
+ should not be interrupted, such as creating a CD or DVD. The types of actions
+ that may be blocked are specified by the flags parameter. When the application
+ completes the operation it should call <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref>
+ or disconnect from the session bus.
+ </doc:para>
+ <doc:para>
+ Applications should not expect that they will always be able to block the
+ action. In most cases, users will be given the option to force the action
+ to take place.
+ </doc:para>
+ <doc:para>
+ Reasons should be short and to the point.
+ </doc:para>
+ <doc:para>
+ The flags parameter must include at least one of the following:
+ <doc:list>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>Inhibit logging out</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>Inhibit user switching</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>4</doc:term>
+ <doc:definition>Inhibit suspending the session or computer</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>8</doc:term>
+ <doc:definition>Inhibit the session being marked as idle</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>16</doc:term>
+ <doc:definition>Inhibit auto-mounting removable media for the session</doc:definition>
+ </doc:item>
+ </doc:list>
+ Values for flags may be bitwise or'ed together.
+ </doc:para>
+ <doc:para>
+ The returned cookie is used to uniquely identify this request. It should be used
+ as an argument to <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref> in
+ order to remove the request.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Uninhibit">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="inhibit_cookie" direction="in">
+ <doc:doc>
+ <doc:summary>The cookie</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Cancel a previous call to <doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref> identified by the cookie.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="IsInhibited">
+ <arg type="u" name="flags" direction="in">
+ <doc:doc>
+ <doc:summary>Flags that spefify what should be inhibited</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg type="b" name="is_inhibited" direction="out">
+ <doc:doc>
+ <doc:summary>Returns TRUE if any of the operations in the bitfield flags are inhibited</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Determine if operation(s) specified by the flags
+ are currently inhibited. Flags are same as those accepted
+ by the
+ <doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref>
+ method.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="GetClients">
+ <arg name="clients" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of client IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Client">Clients</doc:ref>
+ that are currently known to the session manager.</doc:para>
+ <doc:para>Each Client ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="org.gnome.SessionManager.Client">Client</doc:ref> interface.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Client">org.gnome.SessionManager.Client</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <method name="GetInhibitors">
+ <arg name="inhibitors" direction="out" type="ao">
+ <doc:doc>
+ <doc:summary>an array of inhibitor IDs</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitors</doc:ref>
+ that are currently known to the session manager.</doc:para>
+ <doc:para>Each Inhibitor ID is an D-Bus object path for the object that implements the
+ <doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitor</doc:ref> interface.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">org.gnome.SessionManager.Inhibitor</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+
+ <method name="IsAutostartConditionHandled">
+ <arg name="condition" direction="in" type="s">
+ <doc:doc>
+ <doc:summary>The autostart condition string</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="handled" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>True if condition is handled, false otherwise</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Allows the caller to determine whether the session manager is
+ handling changes to the specified autostart condition.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Shutdown">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Request a shutdown dialog.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Reboot">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Request a reboot dialog.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="CanShutdown">
+ <arg name="is_available" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>True if shutdown is available to the user, false otherwise</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Allows the caller to determine whether or not it's okay to show
+ a shutdown option in the UI</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Logout">
+ <arg name="mode" type="u" direction="in">
+ <doc:doc>
+ <doc:summary>The type of logout that is being requested</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Request a logout dialog</doc:para>
+ <doc:para>
+ Allowed values for the mode parameter are:
+ <doc:list>
+ <doc:item>
+ <doc:term>0</doc:term>
+ <doc:definition>Normal.</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>1</doc:term>
+ <doc:definition>No confirmation inferface should be shown.</doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>2</doc:term>
+ <doc:definition>Forcefully logout. No confirmation will be shown and any inhibitors will be ignored.</doc:definition>
+ </doc:item>
+ </doc:list>
+ Values for flags may be bitwise or'ed together.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="IsSessionRunning">
+ <arg name="running" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>True if the session has entered the Running phase, false otherwise</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Allows the caller to determine whether the session manager
+ has entered the Running phase, in case the client missed the
+ SessionRunning signal.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- Signals -->
+
+ <signal name="ClientAdded">
+ <arg name="id" type="o">
+ <doc:doc>
+ <doc:summary>The object path for the added client</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a client has been added to the session manager.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="ClientRemoved">
+ <arg name="id" type="o">
+ <doc:doc>
+ <doc:summary>The object path for the removed client</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when a client has been removed from the session manager.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <signal name="InhibitorAdded">
+ <arg name="id" type="o">
+ <doc:doc>
+ <doc:summary>The object path for the added inhibitor</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when an inhibitor has been added to the session manager.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="InhibitorRemoved">
+ <arg name="id" type="o">
+ <doc:doc>
+ <doc:summary>The object path for the removed inhibitor</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when an inhibitor has been removed from the session manager.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <signal name="SessionRunning">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Indicates the session has entered the Running phase.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <signal name="SessionOver">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Indicates the session is about to end.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- Properties -->
+
+ <property name="SessionName" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The name of the session that has been loaded.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="SessionIsActive" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>If true, the session is currently in the
+ foreground and available for user input.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="InhibitedActions" type="u" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>A bitmask of flags to indicate which actions
+ are inhibited. See the Inhibit() function's description
+ for a list of possible values.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
diff --git a/src/backend-dbus/session-dbus.xml b/src/backend-dbus/session-dbus.xml
new file mode 100644
index 0000000..96e9837
--- /dev/null
+++ b/src/backend-dbus/session-dbus.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/com/canonical/indicator/session/service">
+ <interface name="com.canonical.indicator.session.service">
+
+ <method name="GetUserRealName">
+ <arg name="name" direction="out" type="s"/>
+ </method>
+ <method name="GetUserMenuVisibility">
+ <arg name="update" direction="out" type="b"/>
+ </method>
+ <signal name="UserRealNameUpdated">
+ <arg name="name" type="s"/>
+ </signal>
+ <signal name="UserMenuIsVisible">
+ <arg name="update" type="b"/>
+ </signal>
+ <signal name="RestartRequired">
+ </signal>
+ </interface>
+</node>
diff --git a/src/backend-dbus/upower.xml b/src/backend-dbus/upower.xml
new file mode 100644
index 0000000..18d5fbd
--- /dev/null
+++ b/src/backend-dbus/upower.xml
@@ -0,0 +1,309 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.UPower">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The DeviceKit-power service is available via the system message
+ bus. To access the service, use
+ the <doc:tt>org.freedesktop.UPower</doc:tt> interface on
+ the <doc:tt>/org/freedesktop/UPower</doc:tt> object on
+ the D-Bus system bus service with the well-known
+ name <doc:tt>org.freedesktop.UPower</doc:tt>.
+ </doc:para>
+ <doc:para>
+ <doc:example language="shell" title="simple example">
+ <doc:code>
+$ dbus-send --print-reply \
+ --system \
+ --dest=org.freedesktop.UPower \
+ /org/freedesktop/UPower \
+ org.freedesktop.UPower.EnumerateDevices
+
+method return sender=:1.386 -> dest=:1.451 reply_serial=2
+ array [
+ object path "/org/freedesktop/UPower/devices/line_power_AC"
+ object path "/org/freedesktop/UPower/devices/battery_BAT0"
+ ]
+ </doc:code>
+ </doc:example>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+
+ <!-- ************************************************************ -->
+
+ <method name="EnumerateDevices">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="devices" direction="out" type="ao">
+ <doc:doc><doc:summary>An array of object paths for devices.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enumerate all power objects on the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceAdded">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was added.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is added.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceRemoved">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was removed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is removed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceChanged">
+ <arg name="device" type="s">
+ <doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Changed">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when one or more properties on the object changes.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Sleeping">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session is about to be suspended or
+ hibernated.
+ Session and system programs have one second to do anything required
+ before the sleep action is taken (such as sending out Avahi or
+ Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Resuming">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session has just returned from
+ Suspend() or Hibernate().
+ Session and system programs can then do anything required (such as
+ sending out Avahi or Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <method name="AboutToSleep">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This method tells UPower that the Suspend() or Hibernate() method
+ is about to be called.
+ This allows UPower to emit the Suspending signal whilst
+ session activities are happening that have to be done before the
+ suspend process is started.
+ </doc:para>
+ <doc:para>
+ This method would typically be called by the session power
+ management daemon, before it locks the screen and waits for the
+ screen to fade to black.
+ The session power management component would then call Suspend() or
+ Hibernate() when these syncronous tasks have completed.
+ </doc:para>
+ <doc:para>
+ If this method is not called than nothing bad will happen and
+ Suspend() or Hibernate() will block for the required second.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Suspend">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Suspends the computer into a low power state.
+ System state is not preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="SuspendAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Suspend">Suspend</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Hibernate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Hibernates the computer into a low power state.
+ System state is preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="HibernateAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Hibernate">Hibernate</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <property name="DaemonVersion" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Version of the running daemon, e.g. <doc:tt>002</doc:tt>.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanSuspend" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to suspend.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanHibernate" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to hibernate.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnLowBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power and if the battery is critically low.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="LidIsClosed" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Indicates if the laptop lid is closed where the display cannot be seen.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="LidIsPresent" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ If the system has a lid device.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+
+</node>
diff --git a/src/backend-dbus/users.c b/src/backend-dbus/users.c
new file mode 100644
index 0000000..4798d33
--- /dev/null
+++ b/src/backend-dbus/users.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dbus-accounts.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-session.h"
+#include "dbus-consolekit-manager.h"
+#include "dbus-user.h"
+
+#include "users.h"
+
+struct _IndicatorSessionUsersDbusPriv
+{
+ char * active_session_id;
+
+ Accounts * accounts;
+
+ DisplayManagerSeat * dm_seat;
+
+ ConsoleKitSeat * seat_proxy;
+
+ /* user's dbus object path -> AccountsUser* */
+ GHashTable * path_to_user;
+
+ /* uint32 user-id --> user's dbus object path */
+ GHashTable * uid_to_user_path;
+
+ /* uint32 user-id --> hashset of ssid strings */
+ GHashTable * uid_to_sessions;
+
+ /* ssid string --> uint32 user-id */
+ GHashTable * session_to_uid;
+
+ GCancellable * cancellable;
+};
+
+typedef IndicatorSessionUsersDbusPriv priv_t;
+
+G_DEFINE_TYPE (IndicatorSessionUsersDbus,
+ indicator_session_users_dbus,
+ INDICATOR_TYPE_SESSION_USERS)
+
+/***
+****
+***/
+
+static void create_user_proxy_for_path (IndicatorSessionUsersDbus * self,
+ const char * path);
+
+static void create_session_proxy_for_ssid (IndicatorSessionUsersDbus * self,
+ const char * ssid);
+
+static void
+emit_user_changed_for_path (IndicatorSessionUsersDbus * self, const char * path)
+{
+ AccountsUser * user = g_hash_table_lookup (self->priv->path_to_user, path);
+
+ if (user && !accounts_user_get_system_account (user))
+ indicator_session_users_changed (INDICATOR_SESSION_USERS(self), path);
+}
+
+static void
+emit_user_changed_for_uid (IndicatorSessionUsersDbus * self, guint uid)
+{
+ const char * path;
+
+ if ((path = g_hash_table_lookup (self->priv->uid_to_user_path, GUINT_TO_POINTER(uid))))
+ emit_user_changed_for_path (self, path);
+}
+
+/***
+**** ACCOUNT MANAGER / USER TRACKING
+***/
+
+/* called when a user proxy gets the 'Changed' signal */
+static void
+on_user_changed (AccountsUser * user, gpointer gself)
+{
+ /* Accounts.User doesn't update properties in the standard way,
+ * so create a new proxy to pull in the new properties.
+ * The older proxy is freed when it's removed from our path_to_user hash */
+ const char * path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(user));
+ create_user_proxy_for_path (gself, path);
+}
+
+static void
+track_user (IndicatorSessionUsersDbus * self,
+ AccountsUser * user)
+{
+ priv_t * p;
+ const char * path;
+ gboolean already_had_user;
+
+ p = self->priv;
+
+ path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(user));
+ already_had_user = g_hash_table_contains (p->path_to_user, path);
+
+ g_signal_connect (user, "changed", G_CALLBACK(on_user_changed), self);
+ g_hash_table_insert (p->path_to_user, g_strdup(path), user);
+
+ if (already_had_user)
+ {
+ emit_user_changed_for_path (self, path);
+ }
+ else
+ {
+ const guint uid = (guint) accounts_user_get_uid (user);
+
+ g_hash_table_insert (p->uid_to_user_path,
+ GUINT_TO_POINTER(uid),
+ g_strdup(path));
+
+ if (!accounts_user_get_system_account (user))
+ indicator_session_users_added (INDICATOR_SESSION_USERS(self), path);
+ }
+}
+
+static void
+untrack_user (IndicatorSessionUsersDbus * self,
+ const gchar * path)
+{
+ g_hash_table_remove (self->priv->path_to_user, path);
+
+ indicator_session_users_removed (INDICATOR_SESSION_USERS(self), path);
+}
+
+
+static void
+on_user_proxy_ready (GObject * o G_GNUC_UNUSED,
+ GAsyncResult * res,
+ gpointer self)
+{
+ GError * err;
+ AccountsUser * user;
+
+ err = NULL;
+ user = accounts_user_proxy_new_for_bus_finish (res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s: %s", G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ track_user (self, user);
+ }
+}
+
+static void
+create_user_proxy_for_path (IndicatorSessionUsersDbus * self,
+ const char * path)
+{
+ const char * name = "org.freedesktop.Accounts";
+ const GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES;
+
+ accounts_user_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ flags, name, path,
+ self->priv->cancellable,
+ on_user_proxy_ready, self);
+}
+
+static void
+on_user_list_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gchar ** paths;
+
+ err = NULL;
+ paths = NULL;
+ accounts_call_list_cached_users_finish (ACCOUNTS(o), &paths, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ int i;
+
+ for (i=0; paths && paths[i]; ++i)
+ create_user_proxy_for_path (gself, paths[i]);
+
+ g_strfreev (paths);
+ }
+}
+
+static void
+set_account_manager (IndicatorSessionUsersDbus * self, Accounts * a)
+{
+ priv_t * p = self->priv;
+
+ if (p->accounts != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (p->accounts, self);
+ g_clear_object (&p->accounts);
+ }
+
+ if (a != NULL)
+ {
+ p->accounts = g_object_ref (a);
+
+ accounts_call_list_cached_users (a,
+ self->priv->cancellable,
+ on_user_list_ready,
+ self);
+
+ g_signal_connect_swapped (a, "user-added",
+ G_CALLBACK(create_user_proxy_for_path), self);
+
+ g_signal_connect_swapped (a, "user-deleted",
+ G_CALLBACK(untrack_user), self);
+ }
+}
+
+#if 0
+static void
+create_accounts_proxy (IndicatorSessionUsersDbus * self)
+{
+ const char * name = "org.freedesktop.Accounts";
+ const char * path = "/org/freedesktop/Accounts";
+ GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES;
+
+ accounts_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ flags, name, path,
+ self->priv->cancellable,
+ on_accounts_proxy_ready, self);
+}
+#endif
+
+/**
+ * SEAT / SESSION TRACKING
+ *
+ * There are two simple goals here:
+ *
+ * 1. Keep track of how many GUI sessions each user has
+ * so that we can set the 'is_logged_in' flag correctly
+ *
+ * 2. Also track which is the current session,
+ * so that we can compare it to those GUI sessions to
+ * set the 'is_current_session' flag correctly.
+ *
+ * Now that you know the goals, these steps may make more sense:
+ *
+ * 1. create a ConsoleKitManager proxy
+ * 2. ask it for the current session
+ * 3. create a corresponding Session proxy
+ * 4. ask that Session proxy for its seat
+ * 5. create a corresponding Seat proxy
+ * 6. connect to that seat's session-added / session-removed signals
+ * 7. ask the seat for a list of its current sessions
+ * 8. create corresponding Session proxies
+ * 9. of them, look for the GUI sessions by checking their X11 properties
+ * 10. for each GUI session, get the corresponding uid
+ * 11. use the information to update our uid <--> GUI sessions tables
+ */
+
+static void
+track_session (IndicatorSessionUsersDbus * self,
+ const char * ssid,
+ guint uid)
+{
+ gpointer uid_key;
+ GHashTable * sessions;
+
+ uid_key = GUINT_TO_POINTER (uid);
+ sessions = g_hash_table_lookup (self->priv->uid_to_sessions, uid_key);
+ if (sessions == NULL)
+ {
+ sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_hash_table_insert (self->priv->uid_to_sessions, uid_key, sessions);
+ }
+
+ g_hash_table_add (sessions, g_strdup (ssid));
+ g_hash_table_insert (self->priv->session_to_uid, g_strdup(ssid), uid_key);
+
+ g_debug ("%s %s now tracking ssid:%s uid:%u. uid has %u tracked ssids.",
+ G_STRLOC, G_STRFUNC, ssid, uid, g_hash_table_size (sessions));
+
+ emit_user_changed_for_uid (self, uid);
+}
+
+static void
+untrack_session (IndicatorSessionUsersDbus * self,
+ const char * ssid)
+{
+ gpointer uidptr;
+ priv_t * p = self->priv;
+
+ if (g_hash_table_lookup_extended (p->session_to_uid, ssid, NULL, &uidptr))
+ {
+ const guint uid = GPOINTER_TO_UINT (uidptr);
+ GHashTable * sessions = g_hash_table_lookup (p->uid_to_sessions, uidptr);
+
+ g_hash_table_remove (p->session_to_uid, ssid);
+ g_hash_table_remove (sessions, ssid);
+ g_debug ("%s %s not tracking ssid:%s uid:%u. uid has %u tracked ssids.",
+ G_STRLOC, G_STRFUNC, ssid, uid,
+ sessions ? g_hash_table_size (sessions) : 0);
+
+ emit_user_changed_for_uid (self, uid);
+ }
+}
+
+static void
+on_session_proxy_uid_ready (GObject * o,
+ GAsyncResult * res,
+ gpointer gself)
+{
+ guint uid;
+ GError * err;
+ ConsoleKitSession * session = CONSOLE_KIT_SESSION (o);
+
+ uid = 0;
+ err = NULL;
+ console_kit_session_call_get_unix_user_finish (session, &uid, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else if (uid)
+ {
+ const char * path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(session));
+ track_session (gself, path, uid);
+ }
+
+ g_object_unref (o);
+}
+
+static void
+on_session_x11_display_ready (GObject * o,
+ GAsyncResult * res,
+ gpointer gself)
+{
+ priv_t * p;
+ GError * err;
+ gchar * gui;
+ ConsoleKitSession * session;
+
+ p = INDICATOR_SESSION_USERS_DBUS(gself)->priv;
+
+ err = NULL;
+ gui = NULL;
+ session = CONSOLE_KIT_SESSION (o);
+ console_kit_session_call_get_x11_display_finish (session, &gui, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ gboolean is_gui_session;
+
+ is_gui_session = gui && *gui;
+
+ if (!is_gui_session)
+ g_clear_object (&session);
+ else
+ console_kit_session_call_get_unix_user (session,
+ p->cancellable,
+ on_session_proxy_uid_ready,
+ gself);
+
+ g_free (gui);
+ }
+}
+
+static void
+on_session_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ ConsoleKitSession * session;
+
+ err = NULL;
+ session = console_kit_session_proxy_new_finish (res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else if (session != NULL)
+ {
+ priv_t * p = INDICATOR_SESSION_USERS_DBUS(gself)->priv;
+
+ console_kit_session_call_get_x11_display (session,
+ p->cancellable,
+ on_session_x11_display_ready,
+ gself);
+ }
+}
+
+static void
+create_session_proxy_for_ssid (IndicatorSessionUsersDbus * self,
+ const char * ssid)
+{
+ const char * name = "org.freedesktop.ConsoleKit";
+ GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES;
+
+ console_kit_session_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ flags, name, ssid,
+ self->priv->cancellable,
+ on_session_proxy_ready, self);
+}
+
+static void
+on_session_list_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gchar ** sessions;
+
+ err = NULL;
+ sessions = NULL;
+ console_kit_seat_call_get_sessions_finish (CONSOLE_KIT_SEAT(o),
+ &sessions, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else
+ {
+ int i;
+
+ for (i=0; sessions && sessions[i]; i++)
+ create_session_proxy_for_ssid (gself, sessions[i]);
+
+ g_strfreev (sessions);
+ }
+}
+
+static inline guint
+get_uid_for_session (IndicatorSessionUsersDbus * self, const char * ssid)
+{
+ guint uid = 0;
+ gpointer value;
+
+ if (ssid != NULL)
+ if ((value = g_hash_table_lookup (self->priv->session_to_uid, ssid)))
+ uid = GPOINTER_TO_UINT (value);
+
+ return uid;
+}
+
+/* it's a live session if username is 'ubuntu' and uid is 999 */
+static gboolean
+is_live_ssid (IndicatorSessionUsersDbus * self, const char * ssid)
+{
+ priv_t * p;
+ guint uid;
+
+ p = INDICATOR_SESSION_USERS_DBUS (self)->priv;
+ uid = get_uid_for_session (self, ssid);
+
+ if (uid == 999)
+ {
+ const char * path;
+ AccountsUser * user = NULL;
+
+ if ((path = g_hash_table_lookup (p->uid_to_user_path, GUINT_TO_POINTER (uid))))
+ user = g_hash_table_lookup (p->path_to_user, path);
+
+ return (user != NULL) && !g_strcmp0 (accounts_user_get_user_name(user), "ubuntu");
+ }
+
+ return FALSE;
+}
+
+
+static void
+set_active_session (IndicatorSessionUsersDbus * self, const char * ssid)
+{
+ priv_t * p = self->priv;
+ const guint old_uid = get_uid_for_session (self, p->active_session_id);
+ const guint new_uid = get_uid_for_session (self, ssid);
+ const gboolean old_live = is_live_ssid (self, p->active_session_id);
+ const gboolean new_live = is_live_ssid (self, ssid);
+
+ g_debug ("%s %s changing active_session_id from '%s' to '%s'",
+ G_STRLOC, G_STRFUNC, p->active_session_id, ssid);
+ g_free (p->active_session_id);
+ p->active_session_id = g_strdup (ssid);
+
+ if (old_uid != new_uid)
+ {
+ emit_user_changed_for_uid (self, old_uid);
+ emit_user_changed_for_uid (self, new_uid);
+ }
+
+ if (old_live != new_live)
+ {
+ indicator_session_users_notify_is_live_session (INDICATOR_SESSION_USERS(self));
+ }
+}
+
+static void
+on_seat_active_session_ready (GObject * o, GAsyncResult * res, gpointer gself)
+{
+ GError * err;
+ gchar * ssid;
+ ConsoleKitSeat * seat;
+
+ err = NULL;
+ ssid = NULL;
+ seat = CONSOLE_KIT_SEAT (o);
+ console_kit_seat_call_get_active_session_finish (seat, &ssid, res, &err);
+ if (err != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
+ g_error_free (err);
+ }
+ else if (ssid != NULL)
+ {
+ set_active_session (INDICATOR_SESSION_USERS_DBUS(gself), ssid);
+ g_free (ssid);
+ }
+}
+
+static void
+set_seat (IndicatorSessionUsersDbus * self, ConsoleKitSeat * seat)
+{
+ priv_t * p = self->priv;
+
+ if (p->seat_proxy != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (p->seat_proxy, self);
+ g_clear_object (&p->seat_proxy);
+ }
+
+ if (seat != NULL)
+ {
+ p->seat_proxy = g_object_ref (seat);
+
+ /* ask the seat for a list of all the sessions */
+ console_kit_seat_call_get_sessions (seat,
+ p->cancellable,
+ on_session_list_ready,
+ self);
+
+ /* ask the seat for the name of the active session */
+ console_kit_seat_call_get_active_session (p->seat_proxy,
+ p->cancellable,
+ on_seat_active_session_ready,
+ self);
+
+ /* listen for session changes in this seat */
+ g_signal_connect_swapped (seat, "session-added",
+ G_CALLBACK(create_session_proxy_for_ssid),self);
+ g_signal_connect_swapped (seat, "session-removed",
+ G_CALLBACK(untrack_session), self);
+ g_signal_connect_swapped (seat, "active-session-changed",
+ G_CALLBACK(set_active_session), self);
+ }
+}
+
+/***
+****
+***/
+
+static void
+set_dm_seat (IndicatorSessionUsersDbus * self, DisplayManagerSeat * dm_seat)
+{
+ priv_t * p = self->priv;
+
+ g_clear_object (&p->dm_seat);
+
+ if (dm_seat != NULL)
+ p->dm_seat = g_object_ref (dm_seat);
+}
+
+static void
+activate_username (IndicatorSessionUsersDbus * self, const char * username)
+{
+ priv_t * p = self->priv;
+ const char * session = "";
+
+ g_return_if_fail (p->dm_seat != NULL);
+
+ display_manager_seat_call_switch_to_user (p->dm_seat, username, session,
+ p->cancellable, NULL, NULL);
+}
+
+/***
+****
+***/
+
+static void
+my_dispose (GObject * o)
+{
+ IndicatorSessionUsersDbus * self = INDICATOR_SESSION_USERS_DBUS (o);
+ priv_t * p = self->priv;
+
+ if (p->cancellable)
+ {
+ g_cancellable_cancel (p->cancellable);
+ g_clear_object (&p->cancellable);
+ }
+
+ set_seat (self, NULL);
+ set_dm_seat (self, NULL);
+ set_account_manager (self, NULL);
+
+ g_clear_pointer (&p->path_to_user, g_hash_table_destroy);
+ g_clear_pointer (&p->session_to_uid, g_hash_table_destroy);
+ g_clear_pointer (&p->uid_to_sessions, g_hash_table_destroy);
+ g_clear_pointer (&p->uid_to_user_path, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (indicator_session_users_dbus_parent_class)->dispose (o);
+}
+
+static void
+my_finalize (GObject * o)
+{
+ IndicatorSessionUsersDbus * u = INDICATOR_SESSION_USERS_DBUS (o);
+
+ g_free (u->priv->active_session_id);
+
+ G_OBJECT_CLASS (indicator_session_users_dbus_parent_class)->finalize (o);
+}
+
+static void
+my_activate_user (IndicatorSessionUsers * users, const char * key)
+{
+ priv_t * p;
+ const char * username = 0;
+
+ p = INDICATOR_SESSION_USERS_DBUS (users)->priv;
+ if (p != 0)
+ {
+ AccountsUser * au = g_hash_table_lookup (p->path_to_user, key);
+
+ if (au != NULL)
+ username = accounts_user_get_user_name (au);
+ }
+
+ if (username != 0)
+ activate_username (INDICATOR_SESSION_USERS_DBUS(users), username);
+ else
+ g_warning ("%s %s can't find user for '%s'", G_STRLOC, G_STRFUNC, key);
+}
+
+static gboolean
+my_is_live_session (IndicatorSessionUsers * users)
+{
+ IndicatorSessionUsersDbus * self = INDICATOR_SESSION_USERS_DBUS(users);
+
+ return is_live_ssid (self, self->priv->active_session_id);
+}
+
+static GStrv
+my_get_keys (IndicatorSessionUsers * users)
+{
+ int i;
+ priv_t * p;
+ gchar ** keys;
+ GHashTableIter iter;
+ gpointer path;
+ gpointer user;
+
+ g_return_val_if_fail (INDICATOR_IS_SESSION_USERS_DBUS(users), NULL);
+ p = INDICATOR_SESSION_USERS_DBUS (users)->priv;
+
+ i = 0;
+ keys = g_new (gchar*, g_hash_table_size(p->path_to_user)+1);
+ g_hash_table_iter_init (&iter, p->path_to_user);
+ while (g_hash_table_iter_next (&iter, &path, &user))
+ if (!accounts_user_get_system_account (user))
+ keys[i++] = g_strdup (path);
+ keys[i] = NULL;
+
+ return keys;
+}
+
+static IndicatorSessionUser *
+my_get_user (IndicatorSessionUsers * users, const gchar * key)
+{
+ priv_t * p;
+ AccountsUser * au;
+ IndicatorSessionUser * ret = NULL;
+
+ p = INDICATOR_SESSION_USERS_DBUS (users)->priv;
+
+ au = g_hash_table_lookup (p->path_to_user, key);
+ if (au && !accounts_user_get_system_account(au))
+ {
+ const guint uid = (guint) accounts_user_get_uid (au);
+ GHashTable * s;
+
+ ret = g_new0 (IndicatorSessionUser, 1);
+
+ s = g_hash_table_lookup (p->uid_to_sessions, GUINT_TO_POINTER(uid));
+ if (s == NULL)
+ {
+ ret->is_logged_in = FALSE;
+ ret->is_current_user = FALSE;
+ }
+ else
+ {
+ ret->is_logged_in = g_hash_table_size (s) > 0;
+ ret->is_current_user = g_hash_table_contains (s, p->active_session_id);
+ }
+
+ ret->uid = uid;
+ ret->user_name = g_strdup (accounts_user_get_user_name (au));
+ ret->real_name = g_strdup (accounts_user_get_real_name (au));
+ ret->icon_file = g_strdup (accounts_user_get_icon_file (au));
+ ret->login_frequency = accounts_user_get_login_frequency (au);
+ }
+
+ return ret;
+}
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_users_dbus_class_init (IndicatorSessionUsersDbusClass * klass)
+{
+ GObjectClass * object_class;
+ IndicatorSessionUsersClass * users_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = my_dispose;
+ object_class->finalize = my_finalize;
+
+ users_class = INDICATOR_SESSION_USERS_CLASS (klass);
+ users_class->is_live_session = my_is_live_session;
+ users_class->get_keys = my_get_keys;
+ users_class->get_user = my_get_user;
+ users_class->activate_user = my_activate_user;
+
+ g_type_class_add_private (klass, sizeof (IndicatorSessionUsersDbusPriv));
+}
+
+static void
+/* cppcheck-suppress unusedFunction */
+indicator_session_users_dbus_init (IndicatorSessionUsersDbus * self)
+{
+ priv_t * p;
+
+ p = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ INDICATOR_TYPE_SESSION_USERS_DBUS,
+ IndicatorSessionUsersDbusPriv);
+ self->priv = p;
+ p->cancellable = g_cancellable_new ();
+
+ p->path_to_user = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+
+ p->uid_to_user_path = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_free);
+
+ p->session_to_uid = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ p->uid_to_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL,
+ (GDestroyNotify)g_hash_table_destroy);
+
+#if 0
+ console_kit_manager_proxy_new_for_bus (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ p->cancellable,
+ on_console_kit_manager_proxy_ready,
+ self);
+#endif
+}
+
+/***
+**** Public
+***/
+
+IndicatorSessionUsers *
+indicator_session_users_dbus_new (void)
+{
+ gpointer o = g_object_new (INDICATOR_TYPE_SESSION_USERS_DBUS, NULL);
+
+ return INDICATOR_SESSION_USERS (o);
+}
+
+void
+indicator_session_users_dbus_set_proxies (IndicatorSessionUsersDbus * self,
+ Accounts * accounts,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * seat)
+{
+ g_return_if_fail (INDICATOR_IS_SESSION_USERS_DBUS (self));
+
+ set_account_manager (self, accounts);
+ set_seat (self, seat);
+ set_dm_seat (self, dm_seat);
+}
diff --git a/src/backend-dbus/users.h b/src/backend-dbus/users.h
new file mode 100644
index 0000000..ff1e0ad
--- /dev/null
+++ b/src/backend-dbus/users.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USERS_DBUS_H__
+#define __USERS_DBUS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../users.h" /* parent class */
+#include "dbus-accounts.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-display-manager.h"
+
+G_BEGIN_DECLS
+
+#define INDICATOR_TYPE_SESSION_USERS_DBUS (indicator_session_users_dbus_get_type())
+#define INDICATOR_SESSION_USERS_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_SESSION_USERS_DBUS, IndicatorSessionUsersDbus))
+#define INDICATOR_SESSION_USERS_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_SESSION_USERS_DBUS, IndicatorSessionUsersDbusClass))
+#define INDICATOR_IS_SESSION_USERS_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_SESSION_USERS_DBUS))
+
+typedef struct _IndicatorSessionUsersDbus IndicatorSessionUsersDbus;
+typedef struct _IndicatorSessionUsersDbusPriv IndicatorSessionUsersDbusPriv;
+typedef struct _IndicatorSessionUsersDbusClass IndicatorSessionUsersDbusClass;
+
+/**
+ * An implementation of IndicatorSessionUsers that gets its user information
+ * from org.freedesktop.ConsoleKit and org.freedesktop.Accounts over DBus.
+ */
+struct _IndicatorSessionUsersDbus
+{
+ /*< private >*/
+ IndicatorSessionUsers parent;
+ IndicatorSessionUsersDbusPriv * priv;
+};
+
+struct _IndicatorSessionUsersDbusClass
+{
+ IndicatorSessionUsersClass parent_class;
+};
+
+GType indicator_session_users_dbus_get_type (void);
+
+IndicatorSessionUsers * indicator_session_users_dbus_new (void);
+
+void indicator_session_users_dbus_set_proxies (IndicatorSessionUsersDbus *,
+ Accounts *,
+ DisplayManagerSeat *,
+ ConsoleKitSeat *);
+
+
+
+G_END_DECLS
+
+#endif
diff --git a/src/backend-dbus/utils.c b/src/backend-dbus/utils.c
new file mode 100644
index 0000000..86a5e5a
--- /dev/null
+++ b/src/backend-dbus/utils.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils.h"
+
+/***
+**** indicator_session_util_get_session_proxies()
+***/
+
+struct session_proxy_data
+{
+ ConsoleKitManager * ck_manager;
+ Accounts * account_manager;
+ DisplayManagerSeat * dm_seat;
+
+ ConsoleKitSeat * current_seat;
+ ConsoleKitSession * current_session;
+ AccountsUser * active_user;
+
+ GCancellable * cancellable;
+ GError * error;
+ int pending;
+
+ indicator_session_util_session_proxies_func callback;
+ gpointer user_data;
+};
+
+static void
+session_proxy_data_free (struct session_proxy_data * data)
+{
+ g_clear_object (&data->ck_manager);
+ g_clear_object (&data->account_manager);
+ g_clear_object (&data->dm_seat);
+
+ g_clear_object (&data->current_seat);
+ g_clear_object (&data->current_session);
+ g_clear_object (&data->active_user);
+
+ g_clear_object (&data->cancellable);
+ g_clear_error (&data->error);
+
+ g_free (data);
+}
+
+static void
+finish_callback (struct session_proxy_data * data)
+{
+ g_assert (data != NULL);
+ g_debug ("%s %s: pending is %d", G_STRLOC, G_STRFUNC, (data->pending-1));
+
+ if (!--data->pending)
+ {
+ data->callback (data->ck_manager,
+ data->account_manager,
+ data->dm_seat,
+ data->current_seat,
+ data->current_session,
+ data->active_user,
+ data->error,
+ data->user_data);
+
+ session_proxy_data_free (data);
+ }
+}
+
+static void
+on_user_proxy_ready (GObject * o G_GNUC_UNUSED,
+ GAsyncResult * res,
+ gpointer gdata)
+{
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ data->active_user = accounts_user_proxy_new_for_bus_finish (res, &data->error);
+
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else
+ {
+ g_debug ("%s %s user proxy is %p", G_STRLOC, G_STRFUNC, (void*)data->active_user);
+ }
+
+ finish_callback (data);
+}
+
+static void
+on_user_path_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ char * path = NULL;
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ accounts_call_find_user_by_id_finish (data->account_manager, &path, res, &data->error);
+
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else if (path != NULL)
+ {
+ g_debug ("%s %s user path is %s", G_STRLOC, G_STRFUNC, path);
+ ++data->pending;
+ accounts_user_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.Accounts",
+ path,
+ data->cancellable,
+ on_user_proxy_ready,
+ data);
+ }
+
+ finish_callback (data);
+ g_free (path);
+}
+
+static void
+on_uid_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ guint uid = 0;
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ console_kit_session_call_get_unix_user_finish (data->current_session, &uid, res, &data->error);
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else if (uid)
+ {
+ g_debug ("%s %s uid is %u", G_STRLOC, G_STRFUNC, uid);
+ ++data->pending;
+ accounts_call_find_user_by_id (data->account_manager,
+ uid,
+ data->cancellable,
+ on_user_path_ready,
+ data);
+ }
+
+ finish_callback (data);
+}
+
+static void
+on_seat_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ data->current_seat = console_kit_seat_proxy_new_for_bus_finish (res, &data->error);
+
+ if (data->error != NULL)
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+
+ finish_callback (data);
+}
+
+static void
+on_sid_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ char * sid = NULL;
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ console_kit_session_call_get_seat_id_finish (data->current_session, &sid, res, &data->error);
+
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else if (sid != NULL)
+ {
+ g_debug ("%s %s sid is %s", G_STRLOC, G_STRFUNC, sid);
+ ++data->pending;
+ console_kit_seat_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.ConsoleKit",
+ sid,
+ data->cancellable,
+ on_seat_proxy_ready,
+ data);
+ }
+
+ finish_callback (data);
+ g_free (sid);
+}
+
+static void
+on_session_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ data->current_session = console_kit_session_proxy_new_finish (res, &data->error);
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else
+ {
+ ++data->pending;
+ console_kit_session_call_get_seat_id (data->current_session,
+ data->cancellable,
+ on_sid_ready,
+ data);
+
+ ++data->pending;
+ console_kit_session_call_get_unix_user (data->current_session,
+ data->cancellable,
+ on_uid_ready,
+ data);
+ }
+
+ finish_callback (data);
+}
+
+static void
+on_current_session_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ char * ssid = NULL;
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ ssid = NULL;
+ console_kit_manager_call_get_current_session_finish (data->ck_manager,
+ &ssid, res,
+ &data->error);
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else if (ssid)
+ {
+ g_debug ("%s %s ssid is %s", G_STRLOC, G_STRFUNC, ssid);
+ data->pending++;
+ console_kit_session_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.ConsoleKit",
+ ssid,
+ data->cancellable,
+ on_session_proxy_ready,
+ data);
+
+ }
+
+ finish_callback (data);
+ g_free (ssid);
+}
+
+static void
+on_display_manager_seat_proxy_ready (GObject * o G_GNUC_UNUSED,
+ GAsyncResult * res,
+ gpointer gdata)
+{
+ DisplayManagerSeat * seat;
+ struct session_proxy_data * data = gdata;
+
+ seat = display_manager_seat_proxy_new_for_bus_finish (res, &data->error);
+
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else if (seat != NULL)
+ {
+ data->dm_seat = g_object_ref (seat);
+ }
+
+ finish_callback (data);
+ g_clear_object (&seat);
+}
+
+static void
+on_console_kit_manager_proxy_ready (GObject * o G_GNUC_UNUSED,
+ GAsyncResult * res,
+ gpointer gdata)
+{
+ ConsoleKitManager * mgr;
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ if (data->error == NULL)
+ {
+ mgr = console_kit_manager_proxy_new_for_bus_finish (res, &data->error);
+ g_debug ("%s %s mgr is %p, err is %p", G_STRLOC, G_STRFUNC, (void*)mgr, (void*)data->error);
+
+ if (data->error != NULL)
+ {
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+ else
+ {
+ data->ck_manager = mgr;
+
+ data->pending++;
+ console_kit_manager_call_get_current_session (mgr,
+ data->cancellable,
+ on_current_session_ready,
+ data);
+
+ }
+ }
+
+ finish_callback (data);
+}
+
+static void
+on_accounts_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
+{
+ struct session_proxy_data * data = gdata;
+ g_debug ("%s %s", G_STRLOC, G_STRFUNC);
+
+ if (data->error == NULL)
+ {
+ data->account_manager = accounts_proxy_new_for_bus_finish (res, &data->error);
+
+ if (data->error != NULL)
+ g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, data->error->message);
+ }
+
+ finish_callback (data);
+}
+
+/**
+ * Getting all the proxies we want is kind of a pain --
+ * especially without blocking (ie, using _sync() funcs) --
+ * so it's farmed out to this wrapper utility.
+ *
+ * 1. in this func, start getting the ConsoleKit and Accounts proxies
+ * 2. when the accounts proxy is ready, stash it in data.account_manager
+ * 3. when the ck manager proxy is ready, stash it in data.ck_manager and
+ * ask it for the current session's ssid
+ * 4. when the ssid is ready, start getting a proxy for it
+ * 5. when the session's proxy is ready, stash it in data.current_session
+ * and ask it for both the current seat's sid and the active user's uid
+ * 6. When the current seat's sid is ready, start getting a proxy for it
+ * 7. When the current seat's proxy is ready, stash it in data.current_seat
+ * 8. when the active user's uid is ready, ask data.account_manager for the path
+ * 9. when the user path is ready, start getting an Accounts.User proxy for it
+ * 10. when the Accounts.User proxy is read, stash it in data.active_user
+ *
+ * When everything is done, or if there's an error, invoke the data.callback
+ */
+void
+indicator_session_util_get_session_proxies (
+ indicator_session_util_session_proxies_func func,
+ GCancellable * cancellable,
+ gpointer user_data)
+{
+ struct session_proxy_data * data;
+
+ data = g_new0 (struct session_proxy_data, 1);
+ data->callback = func;
+ data->user_data = user_data;
+ data->cancellable = g_object_ref (cancellable);
+
+ data->pending++;
+ accounts_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ data->cancellable,
+ on_accounts_proxy_ready, data);
+
+ data->pending++;
+ console_kit_manager_proxy_new_for_bus (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ data->cancellable,
+ on_console_kit_manager_proxy_ready, data);
+
+ data->pending++;
+ display_manager_seat_proxy_new_for_bus (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ "org.freedesktop.DisplayManager",
+ g_getenv ("XDG_SEAT_PATH"),
+ data->cancellable,
+ on_display_manager_seat_proxy_ready, data);
+
+}
diff --git a/src/backend-dbus/utils.h b/src/backend-dbus/utils.h
new file mode 100644
index 0000000..b4f26c3
--- /dev/null
+++ b/src/backend-dbus/utils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DBUS_UTILS_H__
+#define __DBUS_UTILS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "dbus-accounts.h"
+#include "dbus-display-manager.h"
+#include "dbus-user.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-session.h"
+#include "dbus-consolekit-manager.h"
+
+typedef void (*indicator_session_util_session_proxies_func)(
+ ConsoleKitManager * ck_manager,
+ Accounts * account_manager,
+ DisplayManagerSeat * dm_seat,
+ ConsoleKitSeat * current_ck_seat,
+ ConsoleKitSession * current_ck_session,
+ AccountsUser * active_user,
+ const GError * error,
+ gpointer user_data);
+
+/**
+ * Both users-dbus and guest-dbus need some of these proxies.
+ * Getting them all involves a lot of steps, so instead of repeating
+ * ourselves, the common dbus steps are extracted to this func.
+ */
+void indicator_session_util_get_session_proxies (
+ indicator_session_util_session_proxies_func func,
+ GCancellable * cancellable,
+ gpointer user_data);
+
+#endif