diff options
-rw-r--r-- | .bzrignore | 2 | ||||
-rw-r--r-- | src/Makefile.am | 18 | ||||
-rw-r--r-- | src/consolekit-session.xml | 435 | ||||
-rw-r--r-- | src/gdm-local-display-factory.xml | 20 | ||||
-rw-r--r-- | src/indicator-session.c | 15 | ||||
-rw-r--r-- | src/session-service.c | 12 | ||||
-rw-r--r-- | src/users-service-dbus.c | 211 | ||||
-rw-r--r-- | src/users-service-dbus.h | 7 |
8 files changed, 634 insertions, 86 deletions
@@ -58,3 +58,5 @@ src/consolekit-manager-client.h src/session-dbus-client.h src/session-dbus-server.h src/upower-client.h +src/gdm-local-display-factory-client.h +src/consolekit-session-client.h diff --git a/src/Makefile.am b/src/Makefile.am index db41db6..24e00e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,20 @@ consolekit-manager-client.h: $(srcdir)/consolekit-manager.xml --output=consolekit-manager-client.h \ $(srcdir)/consolekit-manager.xml +consolekit-session-client.h: $(srcdir)/consolekit-session.xml + dbus-binding-tool \ + --prefix=_consolekit_session_client \ + --mode=glib-client \ + --output=consolekit-session-client.h \ + $(srcdir)/consolekit-session.xml + +gdm-local-display-factory-client.h: $(srcdir)/gdm-local-display-factory.xml + dbus-binding-tool \ + --prefix=_gdm_local_display_factory_client \ + --mode=glib-client \ + --output=gdm-local-display-factory-client.h \ + $(srcdir)/gdm-local-display-factory.xml + users-service-client.h: $(srcdir)/users-service.xml dbus-binding-tool \ --prefix=_users_service_client \ @@ -113,6 +127,8 @@ gtk_logout_helper_LDADD = \ BUILT_SOURCES = \ consolekit-manager-client.h \ + consolekit-session-client.h \ + gdm-local-display-factory-client.h \ session-dbus-client.h \ session-dbus-server.h \ upower-client.h \ @@ -122,6 +138,8 @@ BUILT_SOURCES = \ EXTRA_DIST = \ consolekit-manager.xml \ + consolekit-session.xml \ + gdm-local-display-factory.xml \ session-dbus.xml \ upower.xml \ users-service.xml \ diff --git a/src/consolekit-session.xml b/src/consolekit-session.xml new file mode 100644 index 0000000..b6e1cdb --- /dev/null +++ b/src/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/gdm-local-display-factory.xml b/src/gdm-local-display-factory.xml new file mode 100644 index 0000000..66fb77c --- /dev/null +++ b/src/gdm-local-display-factory.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="/org/gnome/DisplayManager/LocalDisplayFactory"> + <interface name="org.gnome.DisplayManager.LocalDisplayFactory"> + <method name="CreateProductDisplay"> + <arg name="parent_display_id" direction="in" type="o"/> + <arg name="relay_address" direction="in" type="s"/> + <arg name="id" direction="out" type="o"/> + </method> + <method name="CreateTransientDisplay"> + <arg name="id" direction="out" type="o"/> + </method> + <method name="StartGuestSession"> + <arg name="id" direction="out" type="o"/> + </method> + <method name="SwitchToUser"> + <arg name="username" direction="in" type="s"/> + <arg name="id" direction="out" type="o"/> + </method> + </interface> +</node> diff --git a/src/indicator-session.c b/src/indicator-session.c index e92c36b..b54a5d9 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -217,6 +217,19 @@ get_icon (IndicatorObject * io) return INDICATOR_SESSION(io)->status_image; } +static void +user_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data) +{ + if (g_strcmp0(property, USER_ITEM_PROP_LOGGED_IN) == 0) { + if (g_value_get_boolean(value)) { + gtk_widget_show(GTK_WIDGET(user_data)); + } else { + gtk_widget_hide(GTK_WIDGET(user_data)); + } + } + return; +} + /* Builds an item with a hip little logged in icon. */ static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) @@ -263,6 +276,8 @@ new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuCl dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent); + g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(user_property_change), icon); + return TRUE; } diff --git a/src/session-service.c b/src/session-service.c index ee1a9af..514a86f 100644 --- a/src/session-service.c +++ b/src/session-service.c @@ -386,6 +386,13 @@ activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_da lock_if_possible(); + if (dbusmenu_menuitem_property_get_bool(mi, USER_ITEM_PROP_LOGGED_IN)) { + if (users_service_dbus_activate_guest_session(USERS_SERVICE_DBUS(user_data))) { + return; + } + g_warning("Unable to activate guest session, falling back to command line activation."); + } + if (!g_spawn_command_line_async(GUEST_SESSION_LAUNCHER, &error)) { g_warning("Unable to start guest session: %s", error->message); g_error_free(error); @@ -519,6 +526,9 @@ rebuild_items (DbusmenuMenuitem *root, lock_screen_update_item(lock_menuitem); } + /* Set to NULL just incase we don't end up building one */ + users_service_dbus_set_guest_item(service, NULL); + /* Build all of the user switching items */ if (can_activate == TRUE) { @@ -536,6 +546,7 @@ rebuild_items (DbusmenuMenuitem *root, dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, FALSE); dbusmenu_menuitem_child_append (root, guest_mi); g_signal_connect (G_OBJECT (guest_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), NULL); + users_service_dbus_set_guest_item(service, guest_mi); } if (check_new_session ()) @@ -597,6 +608,7 @@ rebuild_items (DbusmenuMenuitem *root, } dbusmenu_menuitem_child_append (root, mi); g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_user_session), user); + user->menuitem = mi; } } diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c index 4aefdff..86007c3 100644 --- a/src/users-service-dbus.c +++ b/src/users-service-dbus.c @@ -31,10 +31,16 @@ #include <dbus/dbus-glib-lowlevel.h> #include "dbus-shared-names.h" +#include "gdm-local-display-factory-client.h" #include "users-service-dbus.h" #include "users-service-client.h" #include "users-service-marshal.h" #include "consolekit-manager-client.h" +#include "consolekit-session-client.h" + +#define CK_ADDR "org.freedesktop.ConsoleKit" +#define CK_SESSION_IFACE "org.freedesktop.ConsoleKit.Session" + static void users_service_dbus_class_init (UsersServiceDbusClass *klass); static void users_service_dbus_init (UsersServiceDbus *self); @@ -65,7 +71,7 @@ static void seat_proxy_session_removed (DBusGProxy *seat_ static gboolean do_add_session (UsersServiceDbus *service, UserData *user, const gchar *ssid); -static gchar * get_seat_internal (UsersServiceDbus *self); +static gchar * get_seat_internal (DBusGProxy *proxy); /* Private */ typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate; @@ -80,12 +86,16 @@ struct _UsersServiceDbusPrivate DBusGConnection *system_bus; DBusGProxy *gdm_proxy; + DBusGProxy *gdm_local_proxy; DBusGProxy *ck_proxy; DBusGProxy *seat_proxy; DBusGProxy *session_proxy; GHashTable *exclusions; GHashTable *sessions; + + DbusmenuMenuitem * guest_item; + gchar * guest_session_id; }; #define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate)) @@ -155,6 +165,8 @@ users_service_dbus_init (UsersServiceDbus *self) priv->users = NULL; priv->count = 0; + priv->guest_item = NULL; + priv->guest_session_id = NULL; /* Get the system bus */ priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); @@ -198,6 +210,13 @@ users_service_dbus_dispose (GObject *object) static void users_service_dbus_finalize (GObject *object) { + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (object); + + if (priv->guest_session_id != NULL) { + g_free(priv->guest_session_id); + priv->guest_session_id = NULL; + } + G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); } @@ -266,6 +285,11 @@ create_gdm_proxy (UsersServiceDbus *self) G_CALLBACK (user_updated), self, NULL); + + priv->gdm_local_proxy = dbus_g_proxy_new_for_name (priv->system_bus, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/LocalDisplayFactory", + "org.gnome.DisplayManager.LocalDisplayFactory"); } static void @@ -341,9 +365,9 @@ create_cksession_proxy (UsersServiceDbus *service) UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.ConsoleKit", + CK_ADDR, priv->ssid, - "org.freedesktop.ConsoleKit.Session"); + CK_SESSION_IFACE); if (!priv->session_proxy) { @@ -383,24 +407,18 @@ get_seat (UsersServiceDbus *service) priv->ssid = ssid; create_cksession_proxy (service); - seat = get_seat_internal (service); + seat = get_seat_internal (priv->session_proxy); return seat; } static gchar * -get_seat_internal (UsersServiceDbus *self) +get_seat_internal (DBusGProxy *proxy) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); GError *error = NULL; gchar *seat = NULL; - if (!dbus_g_proxy_call (priv->session_proxy, - "GetSeatId", - &error, - G_TYPE_INVALID, - DBUS_TYPE_G_OBJECT_PATH, &seat, - G_TYPE_INVALID)) + if (!org_freedesktop_ConsoleKit_Session_get_seat_id (proxy, &seat, &error)) { if (error) { @@ -421,13 +439,22 @@ get_unix_user (UsersServiceDbus *service, UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); GError *error = NULL; guint uid; + DBusGProxy *session_proxy; + + g_debug("Building session proxy for: %s", session_id); + session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, + CK_ADDR, + session_id, + CK_SESSION_IFACE, + &error); + + if (error != NULL) { + g_warning("Unable to get CK Session proxy: %s", error->message); + g_error_free(error); + return FALSE; + } - if (dbus_g_proxy_call (priv->session_proxy, - "GetUnixUser", - &error, - G_TYPE_INVALID, - G_TYPE_UINT, &uid, - G_TYPE_INVALID)) + if (!org_freedesktop_ConsoleKit_Session_get_unix_user(session_proxy, &uid, &error)) { if (error) { @@ -435,6 +462,7 @@ get_unix_user (UsersServiceDbus *service, g_error_free (error); } + g_object_unref(session_proxy); return FALSE; } @@ -443,6 +471,7 @@ get_unix_user (UsersServiceDbus *service, *uidp = (uid_t)uid; } + g_object_unref(session_proxy); return TRUE; } @@ -455,19 +484,29 @@ do_add_session (UsersServiceDbus *service, GError *error = NULL; gchar *seat = NULL; gchar *xdisplay = NULL; + DBusGProxy * session_proxy; GList *l; - seat = get_seat_internal (service); + session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, + CK_ADDR, + ssid, + CK_SESSION_IFACE, + &error); - if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) + if (error != NULL) { + g_warning("Unable to get CK Session proxy: %s", error->message); + g_error_free(error); return FALSE; + } - if (!dbus_g_proxy_call (priv->session_proxy, - "GetX11Display", - &error, - G_TYPE_INVALID, - G_TYPE_STRING, &xdisplay, - G_TYPE_INVALID)) + seat = get_seat_internal (session_proxy); + + if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) { + g_object_unref(session_proxy); + return FALSE; + } + + if (!org_freedesktop_ConsoleKit_Session_get_x11_display (session_proxy, &xdisplay, &error)) { if (error) { @@ -475,9 +514,12 @@ do_add_session (UsersServiceDbus *service, g_error_free (error); } + g_object_unref(session_proxy); return FALSE; } + g_object_unref(session_proxy); + if (!xdisplay || xdisplay[0] == '\0') return FALSE; @@ -491,6 +533,10 @@ do_add_session (UsersServiceDbus *service, g_debug ("Adding session %s", ssid); user->sessions = g_list_prepend (user->sessions, g_strdup (ssid)); + + if (user->menuitem != NULL) { + dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, TRUE); + } } else { @@ -556,6 +602,17 @@ seat_proxy_session_added (DBusGProxy *seat_proxy, return; } + /* We need to special case guest here because it doesn't + show up in the GDM user tables. */ + if (g_strcmp0("guest", pwent->pw_name) == 0) { + if (priv->guest_item != NULL) { + dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); + } + priv->guest_session_id = g_strdup(session_id); + g_debug("Found guest session: %s", priv->guest_session_id); + return; + } + user = g_hash_table_lookup (priv->users, pwent->pw_name); if (!user) { @@ -576,8 +633,17 @@ seat_proxy_session_removed (DBusGProxy *seat_proxy, GList *l; username = g_hash_table_lookup (priv->sessions, session_id); - if (!username) + if (!username) { + if (g_strcmp0(session_id, priv->guest_session_id) == 0) { + g_debug("Removing guest session: %s", priv->guest_session_id); + if (priv->guest_item != NULL) { + dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, FALSE); + } + g_free(priv->guest_session_id); + priv->guest_session_id = NULL; + } return; + } user = g_hash_table_lookup (priv->users, username); if (!user) @@ -592,6 +658,9 @@ seat_proxy_session_removed (DBusGProxy *seat_proxy, g_free (l->data); user->sessions = g_list_delete_link (user->sessions, l); + if (user->menuitem != NULL && user->sessions == NULL) { + dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, FALSE); + } } else { @@ -657,6 +726,7 @@ sync_users (UsersServiceDbus *self) user->login_count = g_value_get_int (g_value_array_get_nth (values, 4)); user->icon_url = g_strdup (g_value_get_string (g_value_array_get_nth (values, 5))); user->real_name_conflict = FALSE; + user->menuitem = NULL; g_hash_table_insert (priv->users, g_strdup (user->user_name), @@ -706,21 +776,16 @@ session_is_login_window (UsersServiceDbus *self, char *type = NULL; if (!(proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.ConsoleKit", + CK_ADDR, ssid, - "org.freedesktop.ConsoleKit.Session"))) + CK_SESSION_IFACE))) { g_warning ("Failed to get ConsoleKit proxy"); return FALSE; } - if (!dbus_g_proxy_call (proxy, - "GetSessionType", - &error, - G_TYPE_INVALID, - G_TYPE_STRING, &type, - G_TYPE_INVALID)) + if (!org_freedesktop_ConsoleKit_Session_get_session_type (proxy, &type, &error)) { g_warning ("Can't call GetSessionType: %s", error->message); g_error_free (error); @@ -1005,61 +1070,21 @@ users_service_dbus_get_user_list (UsersServiceDbus *self) return g_hash_table_get_values (priv->users); } +/* Activates the guest account if it can. */ +gboolean +users_service_dbus_activate_guest_session (UsersServiceDbus *self) +{ + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, "guest", NULL, NULL); +} + +/* Activates a specific user */ gboolean users_service_dbus_activate_user_session (UsersServiceDbus *self, UserData *user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - DBusMessage *message = NULL; - DBusMessage *reply = NULL; - DBusError error; - - dbus_error_init (&error); - - if (!(message = dbus_message_new_method_call ("org.gnome.DisplayManager", - "/org/gnome/DisplayManager/LocalDisplayFactory", - "org.gnome.DisplayManager.LocalDisplayFactory", - "SwitchToUser"))) - { - g_warning ("failed to create new message"); - return FALSE; - } - - if (!dbus_message_append_args (message, - DBUS_TYPE_STRING, &user->user_name, - DBUS_TYPE_INVALID)) - { - g_warning ("failed to append args"); - return FALSE; - } - - if (!(reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (priv->system_bus), - message, - -1, - &error))) - { - if (dbus_error_is_set (&error)) - { - g_warning ("Failed to send message: %s", error.message); - dbus_error_free (&error); - - return FALSE; - } - } - - if (message) - { - dbus_message_unref (message); - } - - if (reply) - { - dbus_message_unref (reply); - } - - dbus_error_free (&error); - - return TRUE; + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, user->user_name, NULL, NULL); } gboolean @@ -1094,3 +1119,17 @@ users_service_dbus_can_activate_session (UsersServiceDbus *self) return can_activate; } + +/* Sets the menu item that represents the guest account */ +void +users_service_dbus_set_guest_item (UsersServiceDbus * self, DbusmenuMenuitem * mi) +{ + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + priv->guest_item = mi; + + if (priv->guest_session_id != NULL) { + dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); + } + + return; +} diff --git a/src/users-service-dbus.h b/src/users-service-dbus.h index bba88a7..4798d64 100644 --- a/src/users-service-dbus.h +++ b/src/users-service-dbus.h @@ -22,6 +22,7 @@ #include <glib.h> #include <glib-object.h> +#include <libdbusmenu-glib/menuitem.h> G_BEGIN_DECLS @@ -47,7 +48,10 @@ struct _UserData GList *sessions; + /* Whether the real name here conflicts with another in the system */ gboolean real_name_conflict; + /* The menuitem representing this user if there is one. */ + DbusmenuMenuitem * menuitem; UsersServiceDbus *service; }; @@ -80,6 +84,9 @@ GList *users_service_dbus_get_user_list (UsersServiceDbus *self); gboolean users_service_dbus_can_activate_session (UsersServiceDbus *self); gboolean users_service_dbus_activate_user_session (UsersServiceDbus *self, UserData *user); +gboolean users_service_dbus_activate_guest_session (UsersServiceDbus *self); +void users_service_dbus_set_guest_item (UsersServiceDbus * self, + DbusmenuMenuitem * mi); G_END_DECLS |