aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am130
-rw-r--r--src/dialog.c47
-rw-r--r--src/display-manager.xml14
-rw-r--r--src/gtk-logout-helper.c2
-rw-r--r--src/lock-helper.c83
-rw-r--r--src/org.freedesktop.Accounts.User.xml744
-rw-r--r--src/org.freedesktop.Accounts.xml (renamed from src/accounts-service.xml)0
-rw-r--r--src/org.freedesktop.ConsoleKit.Seat.xml2
-rw-r--r--src/session-service.c10
-rw-r--r--src/settings-helper.c3
-rw-r--r--src/settings-helper.h3
-rw-r--r--src/upower.xml2
-rw-r--r--src/user-menu-mgr.c206
-rw-r--r--src/users-service-dbus.c1417
-rw-r--r--src/users-service-dbus.h94
15 files changed, 1833 insertions, 924 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index cfe083c..55262a1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,53 +23,77 @@ libsession_la_SOURCES = \
dbus-shared-names.h \
dbusmenu-shared.h \
user-widget.c \
- user-widget.h \
- accounts-service-client.h
+ user-widget.h
libsession_la_CFLAGS = \
$(APPLET_CFLAGS) \
$(COVERAGE_CFLAGS) \
- -Wall -Werror \
+ -Wall -Wunused \
-DG_LOG_DOMAIN=\"Indicator-Session\"
libsession_la_LIBADD = $(APPLET_LIBS)
libsession_la_LDFLAGS = \
$(COVERAGE_LDFLAGS) \
-module -avoid-version
-consolekit-manager-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Manager.xml
- dbus-binding-tool \
- --prefix=_consolekit_manager_client \
- --mode=glib-client \
- --output=consolekit-manager-client.h \
- $(srcdir)/org.freedesktop.ConsoleKit.Manager.xml
-
-consolekit-seat-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Seat.xml
- dbus-binding-tool \
- --prefix=_consolekit_seat_client \
- --mode=glib-client \
- --output=consolekit-seat-client.h \
- $(srcdir)/org.freedesktop.ConsoleKit.Seat.xml
-
-consolekit-session-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Session.xml
- dbus-binding-tool \
- --prefix=_consolekit_session_client \
- --mode=glib-client \
- --output=consolekit-session-client.h \
- $(srcdir)/org.freedesktop.ConsoleKit.Session.xml
-
-display-manager-client.h: $(srcdir)/display-manager.xml
- dbus-binding-tool \
- --prefix=_gdm_local_display_factory_client \
- --mode=glib-client \
- --output=display-manager-client.h \
- $(srcdir)/display-manager.xml
-
-accounts-service-client.h: $(srcdir)/accounts-service.xml
- dbus-binding-tool \
- --prefix=_accounts_service_client \
- --mode=glib-client \
- --output=accounts-service-client.h \
- $(srcdir)/accounts-service.xml
+dbus_display_manager_sources = \
+ dbus-display-manager.c \
+ dbus-display-manager.h
+$(dbus_display_manager_sources): display-manager.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-display-manager \
+ $^
+
+dbus_consolekit_manager_sources = \
+ dbus-consolekit-manager.c \
+ dbus-consolekit-manager.h
+
+$(dbus_consolekit_manager_sources): org.freedesktop.ConsoleKit.Manager.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-consolekit-manager \
+ $^
+
+dbus_consolekit_seat_sources = \
+ dbus-consolekit-seat.c \
+ dbus-consolekit-seat.h
+
+$(dbus_consolekit_seat_sources): org.freedesktop.ConsoleKit.Seat.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-consolekit-seat \
+ $^
+
+dbus_consolekit_session_sources = \
+ dbus-consolekit-session.c \
+ dbus-consolekit-session.h
+
+$(dbus_consolekit_session_sources): org.freedesktop.ConsoleKit.Session.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-consolekit-session \
+ $^
+
+dbus_accounts_sources = \
+ dbus-accounts.c \
+ dbus-accounts.h
+
+$(dbus_accounts_sources): org.freedesktop.Accounts.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-accounts \
+ $^
+
+dbus_user_sources = \
+ dbus-user.c \
+ dbus-user.h
+
+$(dbus_user_sources): org.freedesktop.Accounts.User.xml
+ gdbus-codegen \
+ --interface-prefix org.freedesktop \
+ --generate-c-code dbus-user \
+ $^
+
dbus_upower_sources = \
dbus-upower.c \
dbus-upower.h
@@ -96,7 +120,13 @@ gen-%.xml.h: %.xml
#################
indicator_session_service_SOURCES = \
+ $(dbus_accounts_sources) \
+ $(dbus_consolekit_manager_sources) \
+ $(dbus_consolekit_seat_sources) \
+ $(dbus_consolekit_session_sources) \
+ $(dbus_display_manager_sources) \
$(dbus_upower_sources) \
+ $(dbus_user_sources) \
lock-helper.c \
lock-helper.h \
session-service.c \
@@ -116,7 +146,7 @@ indicator_session_service_CFLAGS = \
$(SESSIONSERVICE_CFLAGS) \
$(GCONF_CFLAGS) \
-DLIBEXECDIR=\"$(libexecdir)\" \
- -Wall -Werror \
+ -Wall \
-DG_LOG_DOMAIN=\"Indicator-Session\" \
$(COVERAGE_CFLAGS)
indicator_session_service_LDADD = \
@@ -131,6 +161,7 @@ indicator_session_service_LDFLAGS = \
if BUILD_GTKLOGOUTHELPER
gtk_logout_helper_SOURCES = \
+ $(dbus_consolekit_manager_sources) \
gtk-logout-helper.c \
settings-helper.c \
settings-helper.h \
@@ -142,7 +173,7 @@ gtk_logout_helper_CFLAGS = \
$(GTKLOGOUTHELPER_CFLAGS) \
$(GCONF_CFLAGS) \
$(COVERAGE_CFLAGS) \
- -Wall -Werror \
+ -Wall \
-DINDICATOR_ICONS_DIR="\"$(INDICATORICONSDIR)\""
gtk_logout_helper_LDADD = \
@@ -160,23 +191,24 @@ endif
###############
BUILT_SOURCES = \
+ $(dbus_accounts_sources) \
+ $(dbus_consolekit_manager_sources) \
+ $(dbus_consolekit_seat_sources) \
+ $(dbus_consolekit_session_sources) \
+ $(dbus_display_manager_sources) \
$(dbus_upower_sources) \
- consolekit-manager-client.h \
- consolekit-seat-client.h \
- consolekit-session-client.h \
- display-manager-client.h \
+ $(dbus_user_sources) \
gen-session-dbus.xml.c \
- gen-session-dbus.xml.h \
- accounts-service-client.h
+ gen-session-dbus.xml.h
EXTRA_DIST += \
+ display-manager.xml \
+ org.freedesktop.Accounts.User.xml \
+ org.freedesktop.Accounts.xml \
org.freedesktop.ConsoleKit.Manager.xml \
org.freedesktop.ConsoleKit.Seat.xml \
org.freedesktop.ConsoleKit.Session.xml \
- display-manager.xml \
session-dbus.xml \
- upower.xml \
- accounts-service.xml \
- accounts-service-user.xml
+ upower.xml
CLEANFILES += $(BUILT_SOURCES)
diff --git a/src/dialog.c b/src/dialog.c
index 4b139ca..5686a95 100644
--- a/src/dialog.c
+++ b/src/dialog.c
@@ -26,7 +26,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
-#include "consolekit-manager-client.h"
+#include "dbus-consolekit-manager.h"
#include "dialog.h"
/* Strings */
@@ -137,30 +137,31 @@ check_restart_required (void)
static gboolean
ck_check_allowed (LogoutDialogType type)
{
- DBusGConnection * system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
- g_return_val_if_fail(system_bus != NULL, TRUE);
-
- DBusGProxy * ck_proxy = dbus_g_proxy_new_for_name (system_bus,
- "org.freedesktop.ConsoleKit",
- "/org/freedesktop/ConsoleKit/Manager",
- "org.freedesktop.ConsoleKit.Manager");
- g_return_val_if_fail(ck_proxy != NULL, TRUE);
-
- gboolean retval = TRUE;
- switch (type) {
- case LOGOUT_DIALOG_TYPE_RESTART:
- org_freedesktop_ConsoleKit_Manager_can_restart(ck_proxy, &retval, NULL);
- break;
- case LOGOUT_DIALOG_TYPE_SHUTDOWN:
- org_freedesktop_ConsoleKit_Manager_can_stop(ck_proxy, &retval, NULL);
- break;
- default:
- break;
- }
+ gboolean allowed = TRUE;
+
+ ConsoleKitManager * ck_proxy = console_kit_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ NULL,
+ NULL);
+ if (ck_proxy != NULL)
+ {
+ switch (type) {
+ case LOGOUT_DIALOG_TYPE_RESTART:
+ console_kit_manager_call_can_restart_sync (ck_proxy, &allowed, NULL, NULL);
+ break;
+ case LOGOUT_DIALOG_TYPE_SHUTDOWN:
+ console_kit_manager_call_can_stop_sync (ck_proxy, &allowed, NULL, NULL);
+ break;
+ default:
+ break;
+ }
- g_object_unref(ck_proxy);
+ g_object_unref(ck_proxy);
+ }
- return retval;
+ return allowed;
}
LogoutDialog *
diff --git a/src/display-manager.xml b/src/display-manager.xml
index 92f5e05..07b5f29 100644
--- a/src/display-manager.xml
+++ b/src/display-manager.xml
@@ -1,20 +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" direction="in" type="s"/>
+ <arg name="session_name" direction="in" type="s"/>
</method>
<!-- Switch to the guest user -->
<method name="SwitchToGuest">
- <arg name="session" direction="in" type="s"/>
+ <arg name="session_name" direction="in" type="s"/>
</method>
+ <method name='Lock'/>
+
</interface>
+
</node>
diff --git a/src/gtk-logout-helper.c b/src/gtk-logout-helper.c
index f5c11ba..8b8ff8f 100644
--- a/src/gtk-logout-helper.c
+++ b/src/gtk-logout-helper.c
@@ -24,8 +24,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <config.h>
#include <locale.h>
#include <glib.h>
-#include <gtk/gtk.h>
#include <dbus/dbus-glib.h>
+#include <gtk/gtk.h>
#include "dialog.h"
#include "settings-helper.h"
diff --git a/src/lock-helper.c b/src/lock-helper.c
index 8eae674..11bcbd1 100644
--- a/src/lock-helper.c
+++ b/src/lock-helper.c
@@ -21,13 +21,13 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
#include <gio/gio.h>
-#include <dbus/dbus-glib.h>
#include "lock-helper.h"
#define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver"
#define SCREENSAVER_LOCK_ENABLED_KEY "lock-enabled"
-static DBusGProxy * gss_proxy = NULL;
+static GDBusProxy * gss_proxy = NULL;
+
static GMainLoop * gss_mainloop = NULL;
static gboolean is_guest = FALSE;
@@ -52,16 +52,29 @@ will_lock_screen (void)
return g_settings_get_boolean (settings, SCREENSAVER_LOCK_ENABLED_KEY);
}
-/* When the screensave go active, if we've got a mainloop
- running we should quit it. */
+/* When the screensave goes active,
+ if we've got a mainloop running we should quit it. */
static void
-gss_active_changed (DBusGProxy * proxy, gboolean active, gpointer data)
+on_gss_signal (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
{
- if (active && gss_mainloop != NULL) {
- g_main_loop_quit(gss_mainloop);
+ g_debug ("%s sender_name: %s", G_STRLOC, sender_name);
+ g_debug ("%s signal_name: %s", G_STRLOC, signal_name);
+
+ if (!g_strcmp0 (signal_name, "ActiveChanged"))
+ {
+ gboolean active = FALSE;
+ g_variant_get_child (parameters, 0, "b", &active);
+ g_debug ("%s active: %i", G_STRLOC, active);
+
+ if (active && gss_mainloop != NULL)
+ {
+ g_main_loop_quit(gss_mainloop);
+ }
}
-
- return;
}
static gboolean
@@ -72,7 +85,7 @@ get_greeter_mode (void)
return (g_strcmp0(var, "1") == 0);
}
-/* Build the gss proxy and set up it's signals */
+/* Build the gss proxy and set up its signals */
void
build_gss_proxy (void)
{
@@ -80,17 +93,23 @@ build_gss_proxy (void)
if (get_greeter_mode ())
return; /* Don't start/lock the screensaver from the login screen */
- DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
- g_return_if_fail(session_bus != NULL);
-
- gss_proxy = dbus_g_proxy_new_for_name(session_bus,
- "org.gnome.ScreenSaver",
- "/",
- "org.gnome.ScreenSaver");
- g_return_if_fail(gss_proxy != NULL);
-
- dbus_g_proxy_add_signal(gss_proxy, "ActiveChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(gss_proxy, "ActiveChanged", G_CALLBACK(gss_active_changed), NULL, NULL);
+
+ GError * error = NULL;
+ gss_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.ScreenSaver",
+ "/",
+ "org.gnome.ScreenSaver",
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_message ("Unable to get ScreenSaver proxy: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_return_if_fail (gss_proxy != NULL);
+ g_signal_connect (gss_proxy, "g-signal", G_CALLBACK(on_gss_signal), NULL);
}
return;
@@ -113,8 +132,8 @@ activate_timeout (gpointer data)
return FALSE;
}
-/* A fun little function to actually lock the screen. If,
- that's what you want, let's do it! */
+/* A fun little function to actually lock the screen.
+ If that's what you want, let's do it! */
void
lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
{
@@ -123,11 +142,19 @@ lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
build_gss_proxy();
g_return_if_fail(gss_proxy != NULL);
- dbus_g_proxy_call_no_reply(gss_proxy,
- "Lock",
- G_TYPE_INVALID,
- G_TYPE_INVALID);
-
+ GError * error = NULL;
+ GVariant * ret = g_dbus_proxy_call_sync (gss_proxy,
+ "Lock",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ g_variant_unref (ret);
+ if (error != NULL) {
+ g_warning ("Unable to lock: %s", error->message);
+ g_error_free (error);
+ }
if (gss_mainloop == NULL) {
gss_mainloop = g_main_loop_new(NULL, FALSE);
}
diff --git a/src/org.freedesktop.Accounts.User.xml b/src/org.freedesktop.Accounts.User.xml
new file mode 100644
index 0000000..53f54d4
--- /dev/null
+++ b/src/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/accounts-service.xml b/src/org.freedesktop.Accounts.xml
index 9c19761..9c19761 100644
--- a/src/accounts-service.xml
+++ b/src/org.freedesktop.Accounts.xml
diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml
index d95990b..58c2ce7 100644
--- a/src/org.freedesktop.ConsoleKit.Seat.xml
+++ b/src/org.freedesktop.ConsoleKit.Seat.xml
@@ -101,7 +101,7 @@ seat at a time.</doc:para>
</method>
<signal name="ActiveSessionChanged">
- <arg name="ssid" type="o">
+ <arg name="ssid" type="s">
<doc:doc>
<doc:summary>Session ID</doc:summary>
</doc:doc>
diff --git a/src/session-service.c b/src/session-service.c
index 1dd1e14..6a07f29 100644
--- a/src/session-service.c
+++ b/src/session-service.c
@@ -32,9 +32,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
-
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
#include <libdbusmenu-glib/client.h>
@@ -51,13 +48,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "device-menu-mgr.h"
#include "session-dbus.h"
-typedef struct _ActivateData ActivateData;
-struct _ActivateData
-{
- UsersServiceDbus *service;
- UserData *user;
-};
-
//static UsersServiceDbus *dbus_interface = NULL;
static SessionDbus *session_dbus = NULL;
static GMainLoop * mainloop = NULL;
diff --git a/src/settings-helper.c b/src/settings-helper.c
index 007f83f..6a09498 100644
--- a/src/settings-helper.c
+++ b/src/settings-helper.c
@@ -22,9 +22,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <gio/gio.h>
#include <glib/gi18n.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
-
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
diff --git a/src/settings-helper.h b/src/settings-helper.h
index ea0c99f..f50c4d8 100644
--- a/src/settings-helper.h
+++ b/src/settings-helper.h
@@ -25,9 +25,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
-
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
diff --git a/src/upower.xml b/src/upower.xml
index a4066ff..18d5fbd 100644
--- a/src/upower.xml
+++ b/src/upower.xml
@@ -86,7 +86,7 @@ method return sender=:1.386 -> dest=:1.451 reply_serial=2
<!-- ************************************************************ -->
<signal name="DeviceChanged">
- <arg name="device" type="o">
+ <arg name="device" type="s">
<doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc>
</arg>
diff --git a/src/user-menu-mgr.c b/src/user-menu-mgr.c
index 00ad8a2..f44f888 100644
--- a/src/user-menu-mgr.c
+++ b/src/user-menu-mgr.c
@@ -28,7 +28,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
struct ActivateUserSessionData
{
UserMenuMgr * menu_mgr;
- UserData * user;
+ AccountsUser * user;
};
struct _UserMenuMgr
@@ -36,6 +36,7 @@ struct _UserMenuMgr
GObject parent_instance;
UsersServiceDbus* users_dbus_interface;
DbusmenuMenuitem* root_item;
+ DbusmenuMenuitem * guest_mi;
SessionDbus* session_dbus_interface;
GSettings * lockdown_settings;
gboolean greeter_mode;
@@ -59,6 +60,13 @@ static void user_menu_mgr_rebuild_items (UserMenuMgr *self);
static void user_change (UsersServiceDbus *service,
const gchar *user_id,
gpointer user_data);
+
+static void on_guest_logged_in_changed (UsersServiceDbus * users_dbus,
+ UserMenuMgr * self);
+
+static void on_user_logged_in_changed (UsersServiceDbus * users_dbus,
+ AccountsUser * user,
+ UserMenuMgr * self);
static gboolean is_this_guest_session (void);
static void activate_guest_session (DbusmenuMenuitem * mi,
guint timestamp,
@@ -67,6 +75,9 @@ static void activate_guest_session (DbusmenuMenuitem * mi,
G_DEFINE_TYPE (UserMenuMgr, user_menu_mgr, G_TYPE_OBJECT);
+/***
+****
+***/
static void
user_menu_mgr_init (UserMenuMgr *self)
@@ -74,14 +85,14 @@ user_menu_mgr_init (UserMenuMgr *self)
self->lockdown_settings = g_settings_new (LOCKDOWN_SCHEMA);
self->users_dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
self->root_item = dbusmenu_menuitem_new ();
- g_signal_connect (G_OBJECT (self->users_dbus_interface),
- "user-added",
- G_CALLBACK (user_change),
- self);
- g_signal_connect (G_OBJECT (self->users_dbus_interface),
- "user-deleted",
- G_CALLBACK (user_change),
- self);
+ g_signal_connect (self->users_dbus_interface, "user-added",
+ G_CALLBACK (user_change), self);
+ g_signal_connect (self->users_dbus_interface, "user-deleted",
+ G_CALLBACK (user_change), self);
+ g_signal_connect (self->users_dbus_interface, "user-logged-in-changed",
+ G_CALLBACK(on_user_logged_in_changed), self);
+ g_signal_connect (self->users_dbus_interface, "guest-logged-in-changed",
+ G_CALLBACK(on_guest_logged_in_changed), self);
}
static void
@@ -108,8 +119,67 @@ user_menu_mgr_class_init (UserMenuMgrClass *klass)
object_class->finalize = user_menu_mgr_finalize;
}
+/***
+****
+***/
+
+static GQuark
+get_menuitem_quark (void)
+{
+ static GQuark q = 0;
+
+ if (G_UNLIKELY(!q))
+ {
+ q = g_quark_from_static_string ("menuitem");
+ }
+
+ return q;
+}
+
+static DbusmenuMenuitem*
+user_get_menuitem (AccountsUser * user)
+{
+ return g_object_get_qdata (G_OBJECT(user), get_menuitem_quark());
+}
+
+static void
+user_set_menuitem (AccountsUser * user, DbusmenuMenuitem * mi)
+{
+ g_message ("%s %s() associating user %s with mi %p", G_STRLOC, G_STRFUNC, accounts_user_get_user_name(user), mi);
+ g_object_set_qdata_full (G_OBJECT(user), get_menuitem_quark(), g_object_ref(G_OBJECT(mi)), g_object_unref);
+}
+
+static GQuark
+get_name_collision_quark (void)
+{
+ static GQuark q = 0;
+
+ if (G_UNLIKELY(!q))
+ {
+ q = g_quark_from_static_string ("name-collision");
+ }
+
+ return q;
+}
+
+static gboolean
+get_user_name_collision (AccountsUser * user)
+{
+ return g_object_get_qdata (G_OBJECT(user), get_name_collision_quark()) != NULL;
+}
+
+static void
+set_user_name_collision (AccountsUser * user, gboolean b)
+{
+ g_object_set_qdata (G_OBJECT(user), get_name_collision_quark(), GINT_TO_POINTER(b));
+}
+
+/***
+****
+***/
+
static DbusmenuMenuitem*
-create_user_menuitem (UserMenuMgr * menu_mgr, UserData * user)
+create_user_menuitem (UserMenuMgr * menu_mgr, AccountsUser * user)
{
DbusmenuMenuitem * mi = dbusmenu_menuitem_new ();
dbusmenu_menuitem_property_set (mi,
@@ -117,27 +187,30 @@ create_user_menuitem (UserMenuMgr * menu_mgr, UserData * user)
USER_ITEM_TYPE);
/* set the name property */
- char * str = user->real_name_conflict
- ? g_strdup_printf ("%s (%s)", user->real_name, user->user_name)
- : g_strdup (user->real_name);
+ const gchar * const real_name = accounts_user_get_real_name (user);
+ const gchar * const user_name = accounts_user_get_user_name (user);
+ char * str = get_user_name_collision (user)
+ ? g_strdup_printf ("%s (%s)", real_name, user_name)
+ : g_strdup (real_name);
dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, str);
g_free (str);
/* set the logged-in property */
+ const gboolean is_logged_in = users_service_dbus_is_user_logged_in (menu_mgr->users_dbus_interface, user);
dbusmenu_menuitem_property_set_bool (mi,
USER_ITEM_PROP_LOGGED_IN,
- user->sessions != NULL);
+ is_logged_in);
/* set the icon property */
- str = user->icon_file;
- if (!str || !*str)
- str = USER_ITEM_ICON_DEFAULT;
- dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_ICON, str);
+ const gchar * icon_str = accounts_user_get_icon_file (user);
+ if (!icon_str || !*icon_str)
+ icon_str = USER_ITEM_ICON_DEFAULT;
+ dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_ICON, icon_str);
/* set the is-current-user property */
dbusmenu_menuitem_property_set_bool (mi,
USER_ITEM_PROP_IS_CURRENT_USER,
- !g_strcmp0 (user->user_name, g_get_user_name()));
+ !g_strcmp0 (user_name, g_get_user_name()));
/* set the activate callback */
struct ActivateUserSessionData * data = g_new (struct ActivateUserSessionData, 1);
@@ -148,10 +221,42 @@ create_user_menuitem (UserMenuMgr * menu_mgr, UserData * user)
data, (GClosureNotify)g_free,
0);
+ /* give this AccountsUser a hook back to this menuitem */
+ user_set_menuitem (user, mi);
+
/* done */
return mi;
}
+static void
+on_guest_logged_in_changed (UsersServiceDbus * users_service_dbus,
+ UserMenuMgr * self)
+{
+ if (self->guest_mi != NULL)
+ {
+ const gboolean b = users_service_dbus_is_guest_logged_in (users_service_dbus);
+ dbusmenu_menuitem_property_set_bool (self->guest_mi, USER_ITEM_PROP_LOGGED_IN, b);
+ }
+}
+
+/* When a user's login state changes,
+ update the corresponding menuitem's LOGGED_IN property */
+static void
+on_user_logged_in_changed (UsersServiceDbus * users_service_dbus,
+ AccountsUser * user,
+ UserMenuMgr * self)
+{
+ DbusmenuMenuitem * mi = user_get_menuitem (user);
+g_message ("%s %s() user %s corresponds to mi %p", G_STRLOC, G_STRFUNC, accounts_user_get_user_name(user), mi);
+
+ if (mi != NULL)
+ {
+ const gboolean b = users_service_dbus_is_user_logged_in (users_service_dbus, user);
+g_message ("setting %p USER_ITEM_PROP_LOGGED_IN to %d", mi, (int)b);
+ dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, b);
+ }
+}
+
/* Builds up the menu for us */
static void
user_menu_mgr_rebuild_items (UserMenuMgr *self)
@@ -169,8 +274,8 @@ user_menu_mgr_rebuild_items (UserMenuMgr *self)
g_list_foreach (children, (GFunc)g_object_unref, NULL);
g_list_free (children);
- /* Set to NULL just incase we don't end up building one */
- users_service_dbus_set_guest_item(self->users_dbus_interface, NULL);
+ /* Set to NULL in case we don't end up building one */
+ self->guest_mi = NULL;
/* Build all of the user switching items */
if (can_activate)
@@ -201,24 +306,19 @@ user_menu_mgr_rebuild_items (UserMenuMgr *self)
if ( !is_this_guest_session () && guest_enabled)
{
- DbusmenuMenuitem *guest_mi = NULL;
- guest_mi = dbusmenu_menuitem_new ();
- dbusmenu_menuitem_property_set (guest_mi,
+ self->guest_mi = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (self->guest_mi,
DBUSMENU_MENUITEM_PROP_TYPE,
USER_ITEM_TYPE);
- dbusmenu_menuitem_property_set (guest_mi,
+ dbusmenu_menuitem_property_set (self->guest_mi,
USER_ITEM_PROP_NAME,
_("Guest Session"));
- dbusmenu_menuitem_property_set_bool (guest_mi,
- USER_ITEM_PROP_LOGGED_IN,
- FALSE);
- dbusmenu_menuitem_child_append (self->root_item, guest_mi);
- g_signal_connect (G_OBJECT (guest_mi),
+ on_guest_logged_in_changed (self->users_dbus_interface, self);
+ dbusmenu_menuitem_child_append (self->root_item, self->guest_mi);
+ g_signal_connect (G_OBJECT (self->guest_mi),
DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
G_CALLBACK (activate_guest_session),
self);
- users_service_dbus_set_guest_item (self->users_dbus_interface,
- guest_mi);
}
else{
session_dbus_set_users_real_name (self->session_dbus_interface,
@@ -231,14 +331,16 @@ user_menu_mgr_rebuild_items (UserMenuMgr *self)
for (u = users; u != NULL; u = g_list_next (u))
{
- UserData * user = u->data;
+ AccountsUser * user = u->data;
DbusmenuMenuitem * mi = create_user_menuitem (self, user);
dbusmenu_menuitem_child_append (self->root_item, mi);
- if (!g_strcmp0 (user->user_name, g_get_user_name()))
+ const char * const user_name = accounts_user_get_user_name (user);
+ if (!g_strcmp0 (user_name, g_get_user_name()))
{
- session_dbus_set_users_real_name (self->session_dbus_interface, user->real_name);
+ const char * const real_name = accounts_user_get_real_name (user);
+ session_dbus_set_users_real_name (self->session_dbus_interface, real_name);
}
}
@@ -305,20 +407,21 @@ activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data
/* Comparison function to look into the UserData struct
to compare by using the username value */
static gint
-compare_users_by_username (gconstpointer a, gconstpointer b)
+compare_users_by_username (gconstpointer ga, gconstpointer gb)
{
- UserData *user1 = (UserData *)a;
- UserData *user2 = (UserData *)b;
+ AccountsUser * a = ACCOUNTS_USER(ga);
+ AccountsUser * b = ACCOUNTS_USER(gb);
- gint retval = g_strcmp0 (user1->real_name, user2->real_name);
+ const int ret = g_strcmp0 (accounts_user_get_real_name (a),
+ accounts_user_get_real_name (b));
- /* If they're the same, they're both in conflict. */
- if (retval == 0) {
- user1->real_name_conflict = TRUE;
- user2->real_name_conflict = TRUE;
- }
+ if (!ret) /* names are the same, so both have a name collision */
+ {
+ set_user_name_collision (a, TRUE);
+ set_user_name_collision (b, TRUE);
+ }
- return retval;
+ return ret;
}
static void
@@ -334,15 +437,16 @@ activate_user_accounts (DbusmenuMenuitem *mi,
}
}
-/* Signal called when a user is added. It updates the count and
- rebuilds the menu */
+/* Signal called when a user is added.
+ It updates the count and rebuilds the menu */
static void
-user_change (UsersServiceDbus *service,
- const gchar *user_id,
+user_change (UsersServiceDbus *service G_GNUC_UNUSED,
+ const gchar *user_id G_GNUC_UNUSED,
gpointer user_data)
{
- g_return_if_fail (USER_IS_MENU_MGR (user_data));
- UserMenuMgr* user_mgr = USER_MENU_MGR(user_data);
+ UserMenuMgr* user_mgr = USER_MENU_MGR (user_data);
+ g_return_if_fail (user_mgr != NULL);
+
user_menu_mgr_rebuild_items (user_mgr);
}
diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c
index e6d094c..382c2dc 100644
--- a/src/users-service-dbus.c
+++ b/src/users-service-dbus.c
@@ -4,6 +4,7 @@
*
* Authors:
* Cody Russell <crussell@canonical.com>
+ * 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
@@ -19,946 +20,938 @@
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <string.h>
+#include <glib.h>
+
#include <errno.h>
-#include <pwd.h>
+#include <string.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <pwd.h> /* getpwuid() */
#include "dbus-shared-names.h"
-#include "display-manager-client.h"
+#include "dbus-accounts.h"
+#include "dbus-consolekit-manager.h"
+#include "dbus-consolekit-seat.h"
+#include "dbus-consolekit-session.h"
+#include "dbus-display-manager.h"
+#include "dbus-user.h"
#include "users-service-dbus.h"
-#include "accounts-service-client.h"
-#include "consolekit-manager-client.h"
-#include "consolekit-session-client.h"
-#include "consolekit-seat-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);
-static void users_service_dbus_dispose (GObject *object);
-static void users_service_dbus_finalize (GObject *object);
-static void create_display_manager_proxy (UsersServiceDbus *self);
-static void create_accounts_service_proxy (UsersServiceDbus *self);
-static void create_seat_proxy (UsersServiceDbus *self);
-static void create_ck_proxy (UsersServiceDbus *self);
-static void create_cksession_proxy (UsersServiceDbus *self);
-static gchar *get_seat (UsersServiceDbus *service);
-static void user_added (DBusGProxy *proxy,
- const gchar *user_id,
- gpointer user_data);
-static void user_deleted (DBusGProxy *proxy,
- const gchar *user_id,
- gpointer user_data);
-static void user_changed (DBusGProxy *proxy,
- gpointer user_data);
-static void seat_proxy_session_added (DBusGProxy *seat_proxy,
- const gchar *session_id,
- UsersServiceDbus *service);
-static void seat_proxy_session_removed (DBusGProxy *seat_proxy,
- const gchar *session_id,
- UsersServiceDbus *service);
-static void sync_users (UsersServiceDbus *self);
-static gboolean do_add_session (UsersServiceDbus *service,
- UserData *user,
- const gchar *ssid);
-static gchar * get_seat_internal (DBusGProxy *proxy);
-
-/* Private */
-typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate;
+static void init_users (UsersServiceDbus * self);
-struct _UsersServiceDbusPrivate
-{
- GHashTable *users;
- gint count;
- gchar *seat;
- gchar *ssid;
+static gchar* get_seat (UsersServiceDbus * service);
- DBusGConnection *system_bus;
+static void on_user_added (Accounts * o,
+ const gchar * user_object_path,
+ UsersServiceDbus * service);
- DBusGProxy *accounts_service_proxy;
- DBusGProxy *display_manager_proxy;
- DBusGProxy *display_manager_props_proxy;
- DBusGProxy *ck_proxy;
- DBusGProxy *seat_proxy;
- DBusGProxy *session_proxy;
+static void on_user_deleted (Accounts * o,
+ const gchar * user_object_path,
+ UsersServiceDbus * service);
- GHashTable *exclusions;
- GHashTable *sessions;
+static void on_session_added (ConsoleKitSeat * seat,
+ const gchar * ssid,
+ UsersServiceDbus * service);
- DbusmenuMenuitem * guest_item;
- gchar * guest_session_id;
- gboolean guest_session_enabled;
-};
-
-#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate))
-
-/* Signals */
-enum {
- USER_ADDED,
- USER_DELETED,
- LAST_SIGNAL
-};
+static void on_session_removed (ConsoleKitSeat * seat,
+ const gchar * ssid,
+ UsersServiceDbus * service);
-static guint signals[LAST_SIGNAL] = { 0 };
+static void on_session_list (ConsoleKitSeat * seat,
+ GAsyncResult * result,
+ UsersServiceDbus * service);
-/* GObject Boilerplate */
-G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT);
+/***
+**** Priv Struct
+***/
-static void
-users_service_dbus_class_init (UsersServiceDbusClass *klass)
+struct _UsersServiceDbusPrivate
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ gchar * seat;
+ gchar * guest_ssid;
- g_type_class_add_private (object_class, sizeof (UsersServiceDbusPrivate));
+ /* ssid -> AccountsUser lookup */
+ GHashTable * sessions;
- object_class->dispose = users_service_dbus_dispose;
- object_class->finalize = users_service_dbus_finalize;
+ /* user object path -> AccountsUser lookup */
+ GHashTable * users;
- signals[USER_ADDED] = g_signal_new ("user-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (UsersServiceDbusClass, user_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
+ GCancellable * cancellable;
+ ConsoleKitSeat * seat_proxy;
+ ConsoleKitManager * ck_manager_proxy;
+ Accounts * accounts_proxy;
+ DisplayManagerSeat * display_proxy;
+};
- signals[USER_DELETED] = g_signal_new ("user-deleted",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (UsersServiceDbusClass, user_deleted),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
-}
+/***
+**** GObject
+***/
-static void
-users_service_dbus_init (UsersServiceDbus *self)
+enum
{
- GError *error = NULL;
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
-
- priv->users = NULL;
- priv->count = 0;
- priv->guest_item = NULL;
- priv->guest_session_id = NULL;
-
- priv->guest_session_enabled = FALSE;
-
- /* Get the system bus */
- priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
- if (error != NULL)
- {
- g_error ("Unable to get system bus");
- g_error_free(error);
-
- return;
- }
-
- priv->sessions = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- g_free);
+ USER_ADDED,
+ USER_DELETED,
+ USER_LOGGED_IN_CHANGED,
+ GUEST_LOGGED_IN_CHANGED,
+ N_SIGNALS
+};
- priv->users = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- NULL);
+static guint signals[N_SIGNALS] = { 0 };
- create_ck_proxy (self);
- create_seat_proxy (self);
- create_display_manager_proxy (self);
- create_accounts_service_proxy (self);
-}
+G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT);
static void
users_service_dbus_dispose (GObject *object)
{
- G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (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);
-}
+ UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv;
+ g_clear_object (&priv->accounts_proxy);
+ g_clear_object (&priv->display_proxy);
+ g_clear_object (&priv->seat_proxy);
+ g_clear_object (&priv->ck_manager_proxy);
-static void
-create_display_manager_proxy (UsersServiceDbus *self)
-{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- GError *error = NULL;
- const gchar *seat = NULL;
-
- seat = g_getenv ("XDG_SEAT_PATH");
- g_debug ("CREATING DM PROXIES WITH %s", seat);
- priv->display_manager_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.DisplayManager",
- seat,
- "org.freedesktop.DisplayManager.Seat");
-
- priv->display_manager_props_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.DisplayManager",
- seat,
- "org.freedesktop.DBus.Properties");
-
-
- if (!priv->display_manager_proxy)
+ if (priv->cancellable != NULL)
{
- g_warning ("Failed to get DisplayManager seat proxy.");
- return;
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
}
- if (!priv->display_manager_props_proxy)
- {
- g_warning ("Failed to get DisplayManager Properties seat proxy.");
- return;
- }
-
- GValue has_guest_session = {0};
- g_value_init (&has_guest_session, G_TYPE_BOOLEAN);
- if (!dbus_g_proxy_call (priv->display_manager_props_proxy,
- "Get",
- &error,
- G_TYPE_STRING,
- "org.freedesktop.DisplayManager.Seat",
- G_TYPE_STRING,
- "HasGuestAccount",
- G_TYPE_INVALID,
- G_TYPE_VALUE,
- &has_guest_session,
- G_TYPE_INVALID))
+
+ if (priv->users != NULL)
{
- g_warning ("Failed to get the HasGuestSession property from the DisplayManager Properties seat proxy. error: %s", error->message);
- g_error_free (error);
- return;
+ g_hash_table_destroy (priv->users);
+ priv->users = NULL;
}
- g_debug ("Does seat have a guest account = %i", g_value_get_boolean (&has_guest_session));
- priv->guest_session_enabled = g_value_get_boolean (&has_guest_session);
-}
-static void
-create_accounts_service_proxy (UsersServiceDbus *self)
-{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- GPtrArray *users = g_ptr_array_new ();
- GError *error = NULL;
-
- priv->accounts_service_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.Accounts",
- "/org/freedesktop/Accounts",
- "org.freedesktop.Accounts");
-
- dbus_g_proxy_add_signal (priv->accounts_service_proxy,
- "UserAdded",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
-
- dbus_g_proxy_add_signal (priv->accounts_service_proxy,
- "UserChanged",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
-
- dbus_g_proxy_add_signal (priv->accounts_service_proxy,
- "UserDeleted",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
-
- dbus_g_proxy_connect_signal (priv->accounts_service_proxy,
- "UserAdded",
- G_CALLBACK (user_added),
- self,
- NULL);
-
- dbus_g_proxy_connect_signal (priv->accounts_service_proxy,
- "UserDeleted",
- G_CALLBACK (user_deleted),
- self,
- NULL);
-
- if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy,
- &users,
- &error))
+ if (priv->sessions != NULL)
{
- g_warning ("failed to retrieve user count: %s", error->message);
- g_error_free (error);
-
- return;
+ g_hash_table_destroy (priv->sessions);
+ priv->sessions = NULL;
}
- priv->count = users->len;
- g_ptr_array_free (users, TRUE);
- sync_users (self);
+ G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object);
}
static void
-create_ck_proxy (UsersServiceDbus *self)
+users_service_dbus_finalize (GObject *object)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+ UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv;
- priv->ck_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.ConsoleKit",
- "/org/freedesktop/ConsoleKit/Manager",
- "org.freedesktop.ConsoleKit.Manager");
+ g_free (priv->guest_ssid);
+ g_free (priv->seat);
- if (!priv->ck_proxy)
- {
- g_warning ("Failed to get ConsoleKit proxy.");
- return;
- }
+ G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object);
}
-/* Get the initial sessions when starting up */
-static void
-get_cksessions_cb (DBusGProxy *proxy, GPtrArray * sessions, GError * error, gpointer userdata)
+static void
+users_service_dbus_class_init (UsersServiceDbusClass *klass)
{
- if (error != NULL) {
- g_warning("Unable to get initial sessions: %s", error->message);
- return;
- }
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- /* If there's no error we should at least get an
- array of zero entries */
- g_return_if_fail(sessions != NULL);
- g_debug("Got %d initial sessions", sessions->len);
+ g_type_class_add_private (object_class, sizeof (UsersServiceDbusPrivate));
- int i;
- for (i = 0; i < sessions->len; i++) {
- seat_proxy_session_added(proxy, g_ptr_array_index(sessions, i), USERS_SERVICE_DBUS(userdata));
- }
+ object_class->dispose = users_service_dbus_dispose;
+ object_class->finalize = users_service_dbus_finalize;
- return;
+ signals[USER_ADDED] = g_signal_new (
+ "user-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, user_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[USER_DELETED] = g_signal_new (
+ "user-deleted",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, user_deleted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[USER_LOGGED_IN_CHANGED] = g_signal_new (
+ "user-logged-in-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, user_logged_in_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[GUEST_LOGGED_IN_CHANGED] = g_signal_new (
+ "guest-logged-in-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, guest_logged_in_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
-create_seat_proxy (UsersServiceDbus *self)
+users_service_dbus_init (UsersServiceDbus *self)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- GError *error = NULL;
+ GError * error = NULL;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ USERS_SERVICE_DBUS_TYPE,
+ UsersServiceDbusPrivate);
+
+ UsersServiceDbusPrivate * p = self->priv;
- priv->seat = get_seat (self);
- if (priv->seat == NULL)
+ p->cancellable = g_cancellable_new ();
+
+ /* ssid -> AccountsUser */
+ p->sessions = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ /* user object path -> AccountsUser */
+ p->users = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ /**
+ *** create the consolekit manager proxy...
+ **/
+
+ p->ck_manager_proxy = console_kit_manager_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ NULL,
+ &error);
+ if (error != NULL)
{
- return;
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_clear_error (&error);
}
- priv->seat_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus,
- "org.freedesktop.ConsoleKit",
- priv->seat,
- "org.freedesktop.ConsoleKit.Seat",
- &error);
+ p->seat = get_seat (self);
- if (!priv->seat_proxy)
+ /**
+ *** create the consolekit seat proxy...
+ **/
+
+ if (p->seat != NULL)
{
+ ConsoleKitSeat * proxy = console_kit_seat_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.ConsoleKit",
+ p->seat,
+ NULL,
+ &error);
+
if (error != NULL)
{
g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message);
- g_error_free (error);
+ g_clear_error (&error);
}
+ else
+ {
+ g_signal_connect (proxy, "session-added",
+ G_CALLBACK (on_session_added), self);
+ g_signal_connect (proxy, "session-removed",
+ G_CALLBACK (on_session_removed), self);
+ console_kit_seat_call_get_sessions (proxy, p->cancellable,
+ (GAsyncReadyCallback)on_session_list, self);
+ p->seat_proxy = proxy;
+ }
+ }
- return;
+ /**
+ *** create the accounts manager proxy...
+ **/
+
+ Accounts * proxy = accounts_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ NULL,
+ &error);
+ if (error != NULL)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_clear_error (&error);
}
+ else
+ {
+ g_signal_connect (proxy, "user-added", G_CALLBACK(on_user_added), self);
+ g_signal_connect (proxy, "user-deleted", G_CALLBACK(on_user_deleted), self);
+ p->accounts_proxy = proxy;
+ init_users (self);
+ }
+}
- dbus_g_proxy_add_signal (priv->seat_proxy,
- "SessionAdded",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
- dbus_g_proxy_add_signal (priv->seat_proxy,
- "SessionRemoved",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
+/***
+****
+***/
- dbus_g_proxy_connect_signal (priv->seat_proxy,
- "SessionAdded",
- G_CALLBACK (seat_proxy_session_added),
- self,
- NULL);
- dbus_g_proxy_connect_signal (priv->seat_proxy,
- "SessionRemoved",
- G_CALLBACK (seat_proxy_session_removed),
- self,
- NULL);
+static void
+emit_user_added (UsersServiceDbus * self, AccountsUser * user)
+{
+ g_signal_emit (self, signals[USER_ADDED], 0, user);
+}
- org_freedesktop_ConsoleKit_Seat_get_sessions_async (priv->seat_proxy, get_cksessions_cb, self);
+static void
+emit_user_deleted (UsersServiceDbus * self, AccountsUser * user)
+{
+ g_signal_emit (self, signals[USER_DELETED], 0, user);
+}
- return;
+static void
+emit_user_login_changed (UsersServiceDbus * self, AccountsUser * user)
+{
+ g_signal_emit (self, signals[USER_LOGGED_IN_CHANGED], 0, user);
}
static void
-create_cksession_proxy (UsersServiceDbus *service)
+emit_guest_login_changed (UsersServiceDbus * self)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
+ g_signal_emit (self, signals[GUEST_LOGGED_IN_CHANGED], 0);
+}
- priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- CK_ADDR,
- priv->ssid,
- CK_SESSION_IFACE);
+/***
+****
+***/
- if (!priv->session_proxy)
+static ConsoleKitSession*
+create_consolekit_session_proxy (const char * ssid)
+{
+ GError * error = NULL;
+
+ ConsoleKitSession * p = console_kit_session_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ CK_ADDR,
+ ssid,
+ NULL,
+ &error);
+
+ if (error != NULL)
{
- g_warning ("Failed to get ConsoleKit session proxy");
- return;
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
}
+
+ return p;
}
static gchar *
-get_seat (UsersServiceDbus *service)
+get_seat_from_session_proxy (ConsoleKitSession * session_proxy)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
- GError *error = NULL;
- gchar *ssid = NULL;
- gchar *seat;
-
- if (!dbus_g_proxy_call (priv->ck_proxy,
- "GetCurrentSession",
- &error,
- G_TYPE_INVALID,
- DBUS_TYPE_G_OBJECT_PATH,
- &ssid,
- G_TYPE_INVALID))
- {
- if (error)
- {
- g_debug ("Failed to call GetCurrentSession: %s", error->message);
- g_error_free (error);
- }
-
- if (ssid)
- g_free (ssid);
+ gchar * seat = NULL;
- return NULL;
+ GError * error = NULL;
+ console_kit_session_call_get_seat_id_sync (session_proxy,
+ &seat,
+ NULL,
+ &error);
+ if (error != NULL)
+ {
+ g_debug ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
}
- priv->ssid = ssid;
- create_cksession_proxy (service);
-
- seat = get_seat_internal (priv->session_proxy);
-
return seat;
}
static gchar *
-get_seat_internal (DBusGProxy *proxy)
+get_seat (UsersServiceDbus *service)
{
- GError *error = NULL;
- gchar *seat = NULL;
+ gchar * seat = NULL;
+ gchar * ssid = NULL;
+ GError * error = NULL;
+ UsersServiceDbusPrivate * priv = service->priv;
+
+ console_kit_manager_call_get_current_session_sync (priv->ck_manager_proxy,
+ &ssid,
+ NULL,
+ &error);
- if (!org_freedesktop_ConsoleKit_Session_get_seat_id (proxy, &seat, &error))
+ if (error != NULL)
{
- if (error)
- {
- g_debug ("Failed to call GetSeatId: %s", error->message);
+ g_debug ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ ConsoleKitSession * session = create_consolekit_session_proxy (ssid);
- return NULL;
+ if (session != NULL)
+ {
+ seat = get_seat_from_session_proxy (session);
+ g_object_unref (session);
}
}
return seat;
}
-static gboolean
-get_unix_user (UsersServiceDbus *service,
- const gchar *session_id,
- uid_t *uidp)
-{
- 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 (!org_freedesktop_ConsoleKit_Session_get_unix_user(session_proxy, &uid, &error))
+/* lazy-create the display manager proxy */
+static DisplayManagerSeat *
+get_display_proxy (UsersServiceDbus * self)
+{
+ UsersServiceDbusPrivate * priv = self->priv;
+
+ if (priv->display_proxy == NULL)
{
- if (error)
+ const gchar * const seat = g_getenv ("XDG_SEAT_PATH");
+ g_debug ("%s lazy-creating the DisplayManager proxy for seat %s", G_STRLOC, seat);
+
+ GError * error = NULL;
+ DisplayManagerSeat * p = display_manager_seat_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.DisplayManager",
+ seat,
+ NULL,
+ &error);
+
+ if (error == NULL)
+ {
+ priv->display_proxy = p;
+ }
+ else
{
- g_warning ("Failed to call GetUnixUser: %s", error->message);
+ g_warning ("%s: %s", G_STRLOC, error->message);
g_error_free (error);
}
+ }
+
+ return priv->display_proxy;
+}
- g_object_unref(session_proxy);
- return FALSE;
+/***
+**** AccountsUser add-ons for tracking sessions
+***/
+
+static GHashTable*
+user_get_sessions_hashset (AccountsUser * user)
+{
+ static GQuark q = 0;
+
+ if (G_UNLIKELY(!q))
+ {
+ q = g_quark_from_static_string ("sessions");
}
- if (uidp != NULL)
+ GObject * o = G_OBJECT (user);
+ GHashTable * h = g_object_get_qdata (o, q);
+ if (h == NULL)
{
- *uidp = (uid_t)uid;
+ h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_object_set_qdata_full (o, q, h, (GDestroyNotify)g_hash_table_destroy);
}
- g_object_unref(session_proxy);
- return TRUE;
+ return h;
}
-static gboolean
-do_add_session (UsersServiceDbus *service,
- UserData *user,
- const gchar *ssid)
-{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
- GError *error = NULL;
- gchar *seat = NULL;
- gchar *xdisplay = NULL;
- DBusGProxy * session_proxy;
- GList *l;
-
- session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus,
- CK_ADDR,
- ssid,
- CK_SESSION_IFACE,
- &error);
-
- if (error != NULL) {
- g_warning("Unable to get CK Session proxy: %s", error->message);
- g_error_free(error);
- return FALSE;
- }
-
- 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))
+static void
+user_add_session (AccountsUser * user, const char * ssid)
+{
+ g_hash_table_add (user_get_sessions_hashset(user), g_strdup(ssid));
+}
+
+static void
+user_remove_session (AccountsUser * user, const char * ssid)
+{
+ g_hash_table_remove (user_get_sessions_hashset(user), ssid);
+}
+
+static guint
+user_count_sessions (AccountsUser * user)
+{
+ return g_hash_table_size (user_get_sessions_hashset(user));
+}
+
+/***
+**** Users
+***/
+
+/* adds this user session to the user's and service's session tables */
+static void
+add_user_session (UsersServiceDbus * service,
+ AccountsUser * user,
+ const gchar * ssid)
+{
+ ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid);
+ if (session_proxy != NULL)
{
- if (error)
+ UsersServiceDbusPrivate * priv = service->priv;
+ gchar * seat = get_seat_from_session_proxy (session_proxy);
+
+ /* is this session in our seat? */
+ if (seat && priv->seat && !g_strcmp0 (seat, priv->seat))
{
- g_debug ("Failed to call GetX11Display: %s", error->message);
- g_error_free (error);
+ /* does this session have a display? */
+ gchar * display = NULL;
+ console_kit_session_call_get_x11_display_sync (session_proxy,
+ &display,
+ NULL, NULL);
+ const gboolean has_display = display && *display;
+ g_free (display);
+
+ if (has_display)
+ {
+ const gchar * username = accounts_user_get_user_name (user);
+ g_debug ("%s adding %s's session '%s' to our tables",
+ G_STRLOC, username, ssid);
+
+ g_hash_table_insert (priv->sessions,
+ g_strdup (ssid),
+ g_object_ref (user));
+
+ user_add_session (user, ssid);
+ }
}
- g_object_unref(session_proxy);
- return FALSE;
+ g_free (seat);
+ g_object_unref (session_proxy);
}
+}
- g_object_unref(session_proxy);
+/* calls add_user_session() for each of this user's sessions */
+static void
+add_user (UsersServiceDbus *self, AccountsUser * user)
+{
+ const guint64 uid = accounts_user_get_uid (user);
+ const char * username = accounts_user_get_user_name (user);
+ g_debug ("%s adding %s (%i)", G_STRLOC, username, (int)uid);
+
+ GError * error = NULL;
+ gchar ** sessions = NULL;
+ console_kit_manager_call_get_sessions_for_unix_user_sync (
+ self->priv->ck_manager_proxy,
+ uid,
+ &sessions,
+ NULL,
+ &error);
- if (!xdisplay || xdisplay[0] == '\0')
- return FALSE;
+ if (error != NULL)
+ {
+ g_debug ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
+ }
+ else if (sessions != NULL)
+ {
+ int i;
- g_hash_table_insert (priv->sessions,
- g_strdup (ssid),
- g_strdup (user->user_name));
+ for (i=0; sessions[i]; i++)
+ {
+ const char * const ssid = sessions[i];
+ g_debug ("%s adding %s's session %s", G_STRLOC, username, ssid);
+ add_user_session (self, user, ssid);
+ }
- l = g_list_find_custom (user->sessions, ssid, (GCompareFunc)g_strcmp0);
- if (l == NULL)
- {
- g_debug ("Adding session %s", ssid);
+ g_strfreev (sessions);
+ }
+}
- user->sessions = g_list_prepend (user->sessions, g_strdup (ssid));
+static void
+add_user_from_object_path (UsersServiceDbus * self,
+ const char * user_object_path)
+{
+ GError * error = NULL;
+ AccountsUser * user = accounts_user_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.Accounts",
+ user_object_path,
+ NULL,
+ &error);
- if (user->menuitem != NULL) {
- dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, TRUE);
- }
+ if (error != NULL)
+ {
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_clear_error (&error);
}
else
{
- g_debug ("User %s already has session %s", user->user_name, ssid);
+ g_debug ("%s adding user %s from object path %s", G_STRLOC,
+ accounts_user_get_user_name(user),
+ user_object_path);
+ g_hash_table_insert (self->priv->users, g_strdup(user_object_path), user);
+ add_user (self, user);
}
-
- return TRUE;
}
+
+/* calls add_user_from_object_path() on a list of user object paths */
static void
-add_sessions_for_user (UsersServiceDbus *self,
- UserData *user)
+init_users (UsersServiceDbus *self)
{
- g_return_if_fail (IS_USERS_SERVICE_DBUS(self));
+ g_return_if_fail(IS_USERS_SERVICE_DBUS(self));
- g_debug ("!!!!!!!!!! - add_sessions_for_user %i %s",
- (int)user->uid, user->user_name);
+ GError * error = NULL;
+ char ** object_paths = NULL;
+ UsersServiceDbusPrivate * priv = self->priv;
+ g_debug ("%s bootstrapping the user list", G_STRLOC);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- GError *error;
- GPtrArray *sessions;
- int i;
+ accounts_call_list_cached_users_sync (priv->accounts_proxy,
+ &object_paths,
+ NULL,
+ &error);
- error = NULL;
- if (!org_freedesktop_ConsoleKit_Manager_get_sessions_for_unix_user(priv->ck_proxy, user->uid, &sessions, &error))
+ if (error != NULL)
{
- g_debug ("Failed to call GetSessionsForUnixUser: %s", error->message);
- g_error_free (error);
-
- return;
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_clear_error (&error);
}
-
- for (i = 0; i < sessions->len; i++)
+ else if (object_paths != NULL)
{
- char *ssid;
+ gint i;
- ssid = g_ptr_array_index (sessions, i);
- do_add_session (self, user, ssid);
+ for (i=0; object_paths[i] != NULL; ++i)
+ {
+ add_user_from_object_path (self, object_paths[i]);
+ }
+
+ g_strfreev (object_paths);
}
- g_ptr_array_foreach (sessions, (GFunc)g_free, NULL);
- g_ptr_array_free (sessions, TRUE);
+ g_debug ("%s finished bootstrapping the user list", G_STRLOC);
}
+static void
+on_user_added (Accounts * o G_GNUC_UNUSED,
+ const gchar * user_path,
+ UsersServiceDbus * service)
+{
+ add_user_from_object_path (service, user_path);
+
+ AccountsUser * user = g_hash_table_lookup (service->priv->users, user_path);
+ emit_user_added (service, user);
+}
static void
-seat_proxy_session_added (DBusGProxy *seat_proxy,
- const gchar *session_id,
- UsersServiceDbus *service)
+on_user_deleted (Accounts * o G_GNUC_UNUSED,
+ const gchar * user_path,
+ UsersServiceDbus * service)
{
- g_return_if_fail(IS_USERS_SERVICE_DBUS(service));
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
- uid_t uid;
- struct passwd *pwent;
- UserData *user;
+ AccountsUser * user = g_hash_table_lookup (service->priv->users, user_path);
- if (!get_unix_user (service, session_id, &uid))
+ if (user != NULL)
{
- g_warning ("Failed to lookup user for session");
- return;
+ GObject * o = g_object_ref (G_OBJECT(user));
+ g_hash_table_remove (service->priv->users, user_path);
+ emit_user_deleted (service, user);
+ g_object_unref (o);
}
+}
- errno = 0;
- pwent = getpwuid (uid);
- if (!pwent)
- {
- g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror (errno));
- return;
- }
+static AccountsUser *
+find_user_from_username (UsersServiceDbus * self,
+ const gchar * username)
+{
+ AccountsUser * match = NULL;
- /* 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;
- }
+ g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), match);
- user = users_service_dbus_get_user_by_username (service, pwent->pw_name);
- if (!user)
- return;
+ gpointer user;
+ GHashTableIter iter;
+ g_hash_table_iter_init (&iter, self->priv->users);
+ while (!match && g_hash_table_iter_next (&iter, NULL, &user))
+ {
+ if (!g_strcmp0 (username, accounts_user_get_user_name (user)))
+ {
+ match = user;
+ }
+ }
- do_add_session (service, user, session_id);
+ return match;
}
+/***
+**** Sessions
+***/
+
static void
-seat_proxy_session_removed (DBusGProxy *seat_proxy,
- const gchar *session_id,
- UsersServiceDbus *service)
-{
- g_return_if_fail(IS_USERS_SERVICE_DBUS(service));
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
- UserData *user;
- gchar *username;
- GList *l;
-
- username = g_hash_table_lookup (priv->sessions, session_id);
- 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;
- }
+on_session_removed (ConsoleKitSeat * seat_proxy,
+ const gchar * ssid,
+ UsersServiceDbus * service)
+{
+ g_return_if_fail (IS_USERS_SERVICE_DBUS (service));
- user = users_service_dbus_get_user_by_username (service, username);
- if (!user)
- return;
+ UsersServiceDbusPrivate * priv = service->priv;
+ g_debug ("%s %s() session removed %s", G_STRLOC, G_STRFUNC, ssid);
- l = g_list_find_custom (user->sessions,
- session_id,
- (GCompareFunc)g_strcmp0);
- if (l)
+ if (!g_strcmp0 (ssid, priv->guest_ssid))
{
- g_debug ("Removing session %s", session_id);
-
- 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);
- }
+ g_debug ("%s removing guest session %s", G_STRLOC, ssid);
+ g_clear_pointer (&priv->guest_ssid, g_free);
+ emit_guest_login_changed (service);
}
else
{
- g_debug ("Session not found: %s", session_id);
+ AccountsUser * user = g_hash_table_lookup (priv->sessions, ssid);
+ if (user == NULL)
+ {
+ g_debug ("%s we're not tracking ssid %s", G_STRLOC, ssid);
+ }
+ else
+ {
+ GObject * o = g_object_ref (G_OBJECT(user));
+ g_hash_table_remove (service->priv->users, ssid);
+ user_remove_session (user, ssid);
+ emit_user_login_changed (service, user);
+ g_object_unref (o);
+ }
}
}
-static void
-sync_users (UsersServiceDbus *self)
+static gchar*
+get_unix_username_from_ssid (UsersServiceDbus * self,
+ const gchar * ssid)
{
- g_return_if_fail(IS_USERS_SERVICE_DBUS(self));
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
-
- GPtrArray *users = NULL;
- GError *error = NULL;
- gint i;
-
- users = g_ptr_array_new ();
-
- if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy,
- &users,
- &error))
- {
- g_warning ("failed to retrieve user list: %s", error->message);
- g_error_free (error);
+ gchar * username = NULL;
- return;
- }
-
- for (i = 0; i < users->len; i++)
+ ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid);
+ if (session_proxy != NULL)
{
- gchar *id;
- DBusGProxy *proxy;
- UserData *user;
- GError *error = NULL;
-
- id = g_ptr_array_index (users, i);
-
- proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.Accounts",
- id,
- "org.freedesktop.DBus.Properties");
-
- GHashTable *properties;
- if (!dbus_g_proxy_call (proxy, "GetAll", &error,
- G_TYPE_STRING, "org.freedesktop.Accounts.User", G_TYPE_INVALID,
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &properties, G_TYPE_INVALID))
- {
- g_warning ("unable to retrieve user info: %s", error->message);
- g_error_free (error);
-
- continue;
- }
-
- user = g_hash_table_lookup (priv->users, id);
- // Double check we havent processed this user already
- if (user != NULL)
+ guint uid = 0;
+ GError * error = NULL;
+ console_kit_session_call_get_unix_user_sync (session_proxy,
+ &uid,
+ NULL, &error);
+ if (error != NULL)
{
- g_free(user->user_name);
- g_free(user->real_name);
- g_free(user->icon_file);
- user->real_name_conflict = FALSE;
- //continue;
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_clear_error (&error);
}
else
- {
- user = g_new0 (UserData, 1);
+ {
+ errno = 0;
+ const struct passwd * pwent = getpwuid (uid);
+ if (pwent == NULL)
+ {
+ g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror(errno));
+ }
+ else
+ {
+ username = g_strdup (pwent->pw_name);
+ }
}
- // Can't subscribe to the Changed signal on each individual user path
- // for some reason.
- dbus_g_proxy_add_signal (proxy,
- "Changed",
- G_TYPE_INVALID);
-
- dbus_g_proxy_connect_signal (proxy, "Changed",
- G_CALLBACK(user_changed),
- self,
- NULL);
- user->uid = g_value_get_uint64 (g_hash_table_lookup (properties, "Uid"));
- user->user_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "UserName")));
- user->real_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "RealName")));
- user->icon_file = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "IconFile")));
- user->real_name_conflict = FALSE;
- user->menuitem = NULL;
-
- g_hash_table_unref (properties);
-
- g_hash_table_insert (priv->users,
- g_strdup (id),
- user);
-
- add_sessions_for_user (self, user);
+
+ g_object_unref (session_proxy);
}
- g_ptr_array_free (users, TRUE);
+ return username;
}
-static void
-user_changed (DBusGProxy *proxy,
- gpointer user_data)
+static gboolean
+is_guest_username (const char * username)
{
- g_debug ("JUST RESYNCED THE USERS FROM A USER CHANGE");
- UsersServiceDbus *service = (UsersServiceDbus *)user_data;
- sync_users (service);
+ if (!g_strcmp0 (username, "guest"))
+ return TRUE;
+
+ if ((strlen(username)==12) && !memcmp(username,"guest-",6))
+ return TRUE;
+
+ return FALSE;
}
+/* If the new session belongs to 'guest', update our guest_ssid.
+ Otherwise, call add_user_session() to update our session tables */
static void
-user_added (DBusGProxy *proxy,
- const gchar *user_id,
- gpointer user_data)
+on_session_added (ConsoleKitSeat * seat_proxy G_GNUC_UNUSED,
+ const gchar * ssid,
+ UsersServiceDbus * service)
{
- UsersServiceDbus *service = (UsersServiceDbus *)user_data;
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
- priv->count++;
- sync_users (service);
- g_signal_emit (service,
- signals[USER_ADDED],
- 0,
- user_id);
-}
+ g_return_if_fail (IS_USERS_SERVICE_DBUS(service));
-static void
-user_deleted (DBusGProxy *proxy,
- const gchar *user_id,
- gpointer user_data)
-{
- UsersServiceDbus *service = (UsersServiceDbus *)user_data;
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
+ gchar * username = get_unix_username_from_ssid (service, ssid);
+ g_debug ("%s %s() username %s has new session %s", G_STRLOC, G_STRFUNC, username, ssid);
- priv->count--;
- g_hash_table_remove (priv->users, user_id);
+ if (is_guest_username (username))
+ {
+ /* handle guest as a special case -- it's not in the GDM
+ user tables and there isn't be an AccountsUser for it */
+ g_debug("Found guest session: %s", ssid);
+ g_free (service->priv->guest_ssid);
+ service->priv->guest_ssid = g_strdup (ssid);
+ emit_guest_login_changed (service);
+ }
+ else
+ {
+ AccountsUser * user = find_user_from_username (service, username);
+
+ if (user != NULL)
+ {
+ add_user_session (service, user, ssid);
+ emit_user_login_changed (service, user);
+ }
+ }
- g_signal_emit (service,
- signals[USER_DELETED],
- 0,
- user_id);
-
+ g_free (username);
}
-UserData *
-users_service_dbus_get_user_by_username (UsersServiceDbus *self,
- const gchar *username)
+/* Receives a list of sessions and calls on_session_added() for each of them */
+static void
+on_session_list (ConsoleKitSeat * seat_proxy,
+ GAsyncResult * result,
+ UsersServiceDbus * self)
{
- GHashTableIter iter;
- gpointer value;
+ GError * error = NULL;
+ gchar ** sessions = NULL;
+ g_debug ("%s bootstrapping the session list", G_STRLOC);
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL);
+ console_kit_seat_call_get_sessions_finish (seat_proxy,
+ &sessions,
+ result,
+ &error);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
-
- g_hash_table_iter_init (&iter, priv->users);
- while (g_hash_table_iter_next (&iter, NULL, &value))
+ if (error != NULL)
{
- UserData *user = value;
- if (strcmp (user->user_name, username) == 0)
- return user;
+ g_debug ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
+ }
+ else if (sessions != NULL)
+ {
+ int i;
+
+ for (i=0; sessions[i]; i++)
+ {
+ g_debug ("%s adding initial session '%s'", G_STRLOC, sessions[i]);
+ on_session_added (seat_proxy, sessions[i], self);
+ }
+
+ g_strfreev (sessions);
}
- return NULL;
+ g_debug ("%s done bootstrapping the session list", G_STRLOC);
}
+/***
+**** Public API
+***/
+
+/**
+ * users_service_dbus_get_user_list:
+ *
+ * Returns: (transfer container): a list of AccountsUser objects
+ */
GList *
-users_service_dbus_get_user_list (UsersServiceDbus *self)
+users_service_dbus_get_user_list (UsersServiceDbus * self)
{
g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+ return g_hash_table_get_values (self->priv->users);
+}
- return g_hash_table_get_values (priv->users);
+/**
+ * users_service_dbus_show_greeter:
+ *
+ * Ask the Display Mnaager to switch to the greeter screen.
+ */
+void
+users_service_dbus_show_greeter (UsersServiceDbus * self)
+{
+ g_return_if_fail (IS_USERS_SERVICE_DBUS(self));
+
+ display_manager_seat_call_switch_to_greeter_sync (get_display_proxy(self),
+ NULL,
+ NULL);
}
-gboolean
-users_service_dbus_show_greeter (UsersServiceDbus *self)
+/**
+ * users_service_dbus_activate_guest_session:
+ *
+ * Activates the guest account.
+ */
+void
+users_service_dbus_activate_guest_session (UsersServiceDbus * self)
{
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- return org_freedesktop_DisplayManager_Seat_switch_to_greeter(priv->display_manager_proxy, NULL);
+ g_return_if_fail(IS_USERS_SERVICE_DBUS(self));
+
+ display_manager_seat_call_switch_to_guest_sync (get_display_proxy(self),
+ "",
+ NULL,
+ NULL);
}
-/* Activates the guest account if it can. */
-gboolean
-users_service_dbus_activate_guest_session (UsersServiceDbus *self)
+/**
+ * users_service_dbus_activate_user_session:
+ *
+ * Activates a specific user.
+ */
+void
+users_service_dbus_activate_user_session (UsersServiceDbus * self,
+ AccountsUser * user)
{
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- return org_freedesktop_DisplayManager_Seat_switch_to_guest(priv->display_manager_proxy, "", NULL);
+ g_return_if_fail (IS_USERS_SERVICE_DBUS(self));
+
+ const char * const username = accounts_user_get_user_name (user);
+ display_manager_seat_call_switch_to_user_sync (get_display_proxy(self),
+ username,
+ "",
+ NULL,
+ NULL);
}
-/* Activates a specific user */
+/**
+ * users_service_dbus_guest_session_enabled:
+ *
+ * Tells whether or not guest sessions are allowed.
+ */
gboolean
-users_service_dbus_activate_user_session (UsersServiceDbus *self,
- UserData *user)
+users_service_dbus_guest_session_enabled (UsersServiceDbus * self)
{
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- return org_freedesktop_DisplayManager_Seat_switch_to_user(priv->display_manager_proxy, user->user_name, "", NULL);
+ g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
+
+ return display_manager_seat_get_has_guest_account (get_display_proxy(self));
}
gboolean
-users_service_dbus_can_activate_session (UsersServiceDbus *self)
+users_service_dbus_can_activate_session (UsersServiceDbus * self)
{
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
gboolean can_activate = FALSE;
- GError *error = NULL;
- if (!priv->seat_proxy)
- {
- create_seat_proxy (self);
- }
+ g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), can_activate);
- if (!priv->seat || priv->seat[0] == '\0')
- {
- return FALSE;
- }
-
- if (!dbus_g_proxy_call (priv->seat_proxy,
- "CanActivateSessions",
- &error,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &can_activate,
- G_TYPE_INVALID))
+ GError * error = NULL;
+ console_kit_seat_call_can_activate_sessions_sync (self->priv->seat_proxy,
+ &can_activate,
+ NULL,
+ &error);
+ if (error != NULL)
{
- if (error != NULL){
- g_warning ("Failed to determine if seat can activate sessions: %s",
- error->message);
- g_error_free (error);
- }
- return FALSE;
+ g_warning ("%s: %s", G_STRLOC, error->message);
+ g_error_free (error);
}
return can_activate;
}
-/* Sets the menu item that represents the guest account */
-void
-users_service_dbus_set_guest_item (UsersServiceDbus * self, DbusmenuMenuitem * mi)
+gboolean
+users_service_dbus_is_guest_logged_in (UsersServiceDbus * self)
{
- g_return_if_fail(IS_USERS_SERVICE_DBUS(self));
- 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);
- }
+ g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE);
- return;
+ return self->priv->guest_ssid != NULL;
}
-gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self)
+gboolean
+users_service_dbus_is_user_logged_in (UsersServiceDbus * self,
+ AccountsUser * user)
{
- g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE);
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
-
- return priv->guest_session_enabled;
-}
+ g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE);
+ g_return_val_if_fail (IS_ACCOUNTS_USER(user), FALSE);
+ return user_count_sessions (user) > 0;
+}
diff --git a/src/users-service-dbus.h b/src/users-service-dbus.h
index 66f3b9d..bc153df 100644
--- a/src/users-service-dbus.h
+++ b/src/users-service-dbus.h
@@ -3,6 +3,7 @@
*
* Authors:
* Cody Russell <crussell@canonical.com>
+ * 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
@@ -22,62 +23,75 @@
#include <glib.h>
#include <glib-object.h>
-#include <libdbusmenu-glib/menuitem.h>
+
+#include "dbus-user.h" /* for AccountsUser */
G_BEGIN_DECLS
-#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ())
-#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus))
-#define USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass))
-#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE))
-#define IS_USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), USERS_SERVICE_DBUS_TYPE))
-#define USERS_SERVICE_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass))
+#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ())
+#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus))
+#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE))
-typedef struct _UsersServiceDbus UsersServiceDbus;
-typedef struct _UsersServiceDbusClass UsersServiceDbusClass;
-typedef struct _UserData UserData;
+typedef struct _UsersServiceDbus UsersServiceDbus;
+typedef struct _UsersServiceDbusClass UsersServiceDbusClass;
+typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate;
-struct _UserData
+/**
+ * A class which interacts with multiple DBus services to track
+ * info which is useful to the interactor's user menu:
+ *
+ * 1. A list of users to add to the user menu.
+ *
+ * Each user is an AccountsUser object, which is a GDBusProxy
+ * to an org.freedesktop.Accounts.User object.
+ *
+ * We initially build this list by calling org.freedesktop.Accounts'
+ * GetCachedUsers method. We also monitor o.f.Accounts' UserAdded
+ * and UserDeleted and update the list accordingly.
+ *
+ * 2. Track which users currently have X sessions.
+ * This is used for the menuitems' USER_ITEM_PROP_LOGGED_IN property.
+ *
+ * We initially build this list by calling org.freedesktop.ConsoleKit.Seat's
+ * GetDevices method. We also monitor the seat for SessionAdded and
+ * SessionRemoved and update the list accordingly.
+ *
+ * 3. Provide an API for user switching and guest sessions.
+ * These are typically pass-through functions to GDBusProxies.
+ *
+ */
+struct _UsersServiceDbus
{
- gint64 uid;
- gchar *user_name;
- gchar *real_name;
- gchar *icon_file;
-
- 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;
-};
-
-struct _UsersServiceDbus {
+ /*< private >*/
GObject parent;
+ UsersServiceDbusPrivate * priv;
};
-struct _UsersServiceDbusClass {
+struct _UsersServiceDbusClass
+{
GObjectClass parent_class;
/* Signals */
- void (* user_added) (UsersServiceDbus *self, const gchar *user_id, gpointer user_data);
- void (* user_deleted) (UsersServiceDbus *self, const gchar *user_id, gpointer user_data);
+ void (* user_added) (UsersServiceDbus*, AccountsUser*, gpointer);
+ void (* user_deleted) (UsersServiceDbus*, AccountsUser*, gpointer);
+ void (* user_logged_in_changed) (UsersServiceDbus*, AccountsUser*, gpointer);
+ void (* guest_logged_in_changed) (UsersServiceDbus*, gpointer);
};
-GType users_service_dbus_get_type (void) G_GNUC_CONST;
+GType users_service_dbus_get_type (void) G_GNUC_CONST;
+
+GList * users_service_dbus_get_user_list (UsersServiceDbus * self);
-UserData *users_service_dbus_get_user_by_username (UsersServiceDbus *self,
- const gchar *username);
-GList *users_service_dbus_get_user_list (UsersServiceDbus *self);
-gboolean users_service_dbus_show_greeter (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);
+gboolean users_service_dbus_is_guest_logged_in (UsersServiceDbus * self);
+gboolean users_service_dbus_is_user_logged_in (UsersServiceDbus * self,
+ AccountsUser * user);
-gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self);
+void users_service_dbus_show_greeter (UsersServiceDbus * self);
+gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self);
+gboolean users_service_dbus_can_activate_session (UsersServiceDbus * self);
+void users_service_dbus_activate_guest_session (UsersServiceDbus * self);
+void users_service_dbus_activate_user_session (UsersServiceDbus * self,
+ AccountsUser * user);
G_END_DECLS