Merge lp:~bratsche/indicator-session/users-service into lp:indicator-session/0.1
- users-service
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~bratsche/indicator-session/users-service |
Merge into: | lp:indicator-session/0.1 |
Diff against target: |
1768 lines 9 files modified
AUTHORS (+2/-0) src/Makefile.am (+27/-2) src/dbus-shared-names.h (+8/-6) src/status-service.c (+8/-8) src/users-service-dbus.c (+1147/-0) src/users-service-dbus.h (+81/-0) src/users-service.c (+191/-62) src/users-service.list (+1/-0) src/users-service.xml (+56/-0) |
To merge this branch: | bzr merge lp:~bratsche/indicator-session/users-service |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Approve | ||
Indicator Applet Developers | Pending | ||
Review via email: mp+12316@code.launchpad.net |
Commit message
Description of the change
- 42. By Cody Russell
-
modify count in user_added(
)/user_ removed( )
Cody Russell (bratsche) wrote : | # |
> * I was looking at "CanActivateSes
> you think we should check this earlier and make the menu items
> sensitive or insensitive based on this?
Should the menuitems even be there if you can never click them? I went ahead and made an API on UsersServiceDbus that can check if the seat can activate sessions, and we can either make the menuitems insensitive or not add them or whatever. For now I didn't change the menu, just added the API.
I'm fixing up the remaining issues now.
Cody Russell (bratsche) wrote : | # |
I'm going to sleep, but figured I'd document the status of this now.
> * In users-service.c I don't see where count is updated. I think
> it should be incremented/
Fixed.
> * There should be icons on the users if they are set (probably
> should go in another branch/bug)
TODO. Can we do this in a separate branch?
> * There doesn't seem to be any sorting of the user list. They
> should be sorted alphabetical by first name.
Fixed.
> * There are six signals defined in the Class structure but only 4
> created on class init.
TODO.
> * I don't think that you need a call to
> dbus_g_
> this object is being shared over DBus (server) but I think it's
> only a client.
Fixed.
> * Confirm with Robert, but I'm pretty sure the excludes list is
> already being applied on the GDM side. We shouldn't need to
> apply it on this side as well. That way there's only one copy
> of the list.
Confirmed with Robert, and fixed.
> * I think that dbus_g_
> as well. Which I think is the only reason you're using the
> session bus, so I think that can be dropped.
Fixed.
> * Oh, now realizing more of the issue. Makefile.am shouldn't even
> be generating user-service-
Fixed.
> * I don't think that dbus_proxy_system and dbus_proxy_session are
> needed as we're not asking DBus itself for any information.
> We're just using it to communicate. We'd only need those
> proxies to query information about the bus itself.
Fixed.
> * Can session_compare be replaced with g_strcmp0? It seems about
> the same.
Fixed.
> * I was looking at "CanActivateSes
> you think we should check this earlier and make the menu items
> sensitive or insensitive based on this?
See previous comment.
> * It looks like you're always getting the information on all the
> users. I think that we really don't care if it's over our max,
> so can we just not bother getting all that data if we're in
> overflow?
Fixed.
> * The guest user needs to be handled as well. If there is a guest
> already logged in selecting the guest on the menu shouldn't
> start a new session, but should go to the guest that is already
> running.
TODO.
Ted Gould (ted) wrote : | # |
On Thu, 2009-09-24 at 06:31 +0000, Cody Russell wrote:
> > * There should be icons on the users if they are set (probably
> > should go in another branch/bug)
>
> TODO. Can we do this in a separate branch?
Yeah, sounds good.
> > * The guest user needs to be handled as well. If there is a guest
> > already logged in selecting the guest on the menu shouldn't
> > start a new session, but should go to the guest that is already
> > running.
>
> TODO.
Let's put this in a new branch as well. We screwed this up in Jaunty,
so it's not a regression :)
- 43. By Cody Russell
-
don't need to dbus_g_
object_ type_install_ info() - 44. By Cody Russell
-
remove unnecessary stuff
- 45. By Cody Russell
-
remove session proxy fu
- 46. By Cody Russell
-
remove the server code
- 47. By Cody Russell
-
remove system proxy
- 48. By Cody Russell
-
use g_strcmp0
- 49. By Cody Russell
-
expose users_service_
dbus_can_ activate_ session( ) - 50. By Cody Russell
-
don't load all the users unless needed
- 51. By Cody Russell
-
cleanup
- 52. By Cody Russell
-
sort users
Ted Gould (ted) wrote : | # |
On Thu, 2009-09-24 at 04:37 +0000, Cody Russell wrote:
> > * I was looking at "CanActivateSes
> > you think we should check this earlier and make the menu items
> > sensitive or insensitive based on this?
>
> Should the menuitems even be there if you can never click them? I
> went ahead and made an API on UsersServiceDbus that can check if
> the seat can activate sessions, and we can either make the menuitems
> insensitive or not add them or whatever. For now I didn't change the
> menu, just added the API.
My thought is let's just hide them. The reason being that then sys
admins can use this as a lockdown mode. We have a bug on this from OEM
as well. But we need to hide all the switching items.
CC'ing MPT as well to get his comments.
Matthew Paul Thomas (mpt) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ted Gould wrote on 24/09/09 14:59:
> On Thu, 2009-09-24 at 04:37 +0000, Cody Russell wrote:
>...
>> Should the menuitems even be there if you can never click them? I
>> went ahead and made an API on UsersServiceDbus that can check if
>> the seat can activate sessions, and we can either make the menuitems
>> insensitive or not add them or whatever. For now I didn't change the
>> menu, just added the API.
>
> My thought is let's just hide them. The reason being that then sys
> admins can use this as a lockdown mode. We have a bug on this from OEM
> as well. But we need to hide all the switching items.
>
> CC'ing MPT as well to get his comments.
What menu items are you talking about?
- --
Matthew Paul Thomas
http://
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkq
tKoAoIUnp8iDhrj
=9HY0
-----END PGP SIGNATURE-----
Ted Gould (ted) wrote : | # |
On Thu, 2009-09-24 at 14:09 +0000, Matthew Paul Thomas wrote:
> Ted Gould wrote on 24/09/09 14:59:
> > On Thu, 2009-09-24 at 04:37 +0000, Cody Russell wrote:
> >...
> >> Should the menuitems even be there if you can never click them? I
> >> went ahead and made an API on UsersServiceDbus that can check if
> >> the seat can activate sessions, and we can either make the menuitems
> >> insensitive or not add them or whatever. For now I didn't change the
> >> menu, just added the API.
> >
> > My thought is let's just hide them. The reason being that then sys
> > admins can use this as a lockdown mode. We have a bug on this from OEM
> > as well. But we need to hide all the switching items.
> >
> > CC'ing MPT as well to get his comments.
>
> What menu items are you talking about?
Basically every menu item involved with user switching. The command
that we have to console kit is whether we can do VT switching. So we'd
be disabling Guess Session, Switching to any user, or starting a new
session without logging out.
Cody Russell (bratsche) wrote : | # |
> > * There are six signals defined in the Class structure but only 4
> > created on class init.
>
> TODO.
I think these other two must have been left over from something, because they're not in the .xml file. So I'm removing them and committing.
- 53. By Cody Russell
-
Remove user_changed and users_icons_changed from the class
- 54. By Cody Russell
-
only add menuitems if the current seat can activate new sessions
Cody Russell (bratsche) wrote : | # |
> My thought is let's just hide them. The reason being that then sys
> admins can use this as a lockdown mode. We have a bug on this from OEM
> as well. But we need to hide all the switching items.
>
> CC'ing MPT as well to get his comments.
Okay, I've gone ahead and committed/pushed a revision that will only add the menuitems if the user has the ability to activate new sessions. If it turns out MPT doesn't like this, it'll be easy enough to change.
- 55. By Cody Russell
-
Don't check range twice here
Preview Diff
1 | === modified file 'AUTHORS' |
2 | --- AUTHORS 2008-12-05 03:13:41 +0000 |
3 | +++ AUTHORS 2009-09-24 16:28:09 +0000 |
4 | @@ -0,0 +1,2 @@ |
5 | +Ted Gould <ted@canonical.com> |
6 | +Cody Russell <crussell@canonical.com> |
7 | |
8 | === modified file 'src/Makefile.am' |
9 | --- src/Makefile.am 2009-09-02 14:17:44 +0000 |
10 | +++ src/Makefile.am 2009-09-24 16:28:09 +0000 |
11 | @@ -11,7 +11,8 @@ |
12 | libsession_la_SOURCES = \ |
13 | indicator-session.c \ |
14 | dbus-shared-names.h \ |
15 | - status-service-client.h |
16 | + status-service-client.h \ |
17 | + users-service-client.h |
18 | libsession_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror |
19 | libsession_la_LIBADD = $(APPLET_LIBS) |
20 | libsession_la_LDFLAGS = -module -avoid-version |
21 | @@ -25,6 +26,10 @@ |
22 | status-service-dbus.h \ |
23 | status-service-dbus.c \ |
24 | status-service-server.h \ |
25 | + users-service-dbus.h \ |
26 | + users-service-dbus.c \ |
27 | + users-service-marshal.c \ |
28 | + users-service-marshal.h \ |
29 | status-provider.h \ |
30 | status-provider.c \ |
31 | status-provider-pidgin.h \ |
32 | @@ -38,6 +43,13 @@ |
33 | indicator_status_service_CFLAGS = $(STATUSSERVICE_CFLAGS) -Wall -Werror |
34 | indicator_status_service_LDADD = $(STATUSSERVICE_LIBS) |
35 | |
36 | +users-service-client.h: $(srcdir)/users-service.xml |
37 | + dbus-binding-tool \ |
38 | + --prefix=_users_service_client \ |
39 | + --mode=glib-client \ |
40 | + --output=users-service-client.h \ |
41 | + $(srcdir)/users-service.xml |
42 | + |
43 | status-service-client.h: $(srcdir)/status-service.xml |
44 | dbus-binding-tool \ |
45 | --prefix=_status_service_client \ |
46 | @@ -52,6 +64,16 @@ |
47 | --output=status-service-server.h \ |
48 | $(srcdir)/status-service.xml |
49 | |
50 | +users-service-marshal.h: $(srcdir)/users-service.list |
51 | + glib-genmarshal --header \ |
52 | + --prefix=_users_service_marshal $(srcdir)/users-service.list \ |
53 | + > users-service-marshal.h |
54 | + |
55 | +users-service-marshal.c: $(srcdir)/users-service.list |
56 | + glib-genmarshal --body \ |
57 | + --prefix=_users_service_marshal $(srcdir)/users-service.list \ |
58 | + > users-service-marshal.c |
59 | + |
60 | status-provider-pidgin-marshal.h: $(srcdir)/status-provider-pidgin.list |
61 | glib-genmarshal --header \ |
62 | --prefix=_status_provider_pidgin_marshal $(srcdir)/status-provider-pidgin.list \ |
63 | @@ -76,7 +98,7 @@ |
64 | # Users Stuff |
65 | ############### |
66 | |
67 | -indicator_users_service_SOURCES = users-service.c |
68 | +indicator_users_service_SOURCES = users-service.c users-service-dbus.c users-service-marshal.c |
69 | indicator_users_service_CFLAGS = $(USERSSERVICE_CFLAGS) -Wall -Werror |
70 | indicator_users_service_LDADD = $(USERSSERVICE_LIBS) |
71 | |
72 | @@ -93,8 +115,11 @@ |
73 | ############### |
74 | |
75 | BUILT_SOURCES = \ |
76 | + users-service-client.h \ |
77 | status-service-client.h \ |
78 | status-service-server.h \ |
79 | + users-service-marshal.h \ |
80 | + users-service-marshal.c \ |
81 | status-provider-pidgin-marshal.h \ |
82 | status-provider-pidgin-marshal.c \ |
83 | status-provider-telepathy-marshal.h \ |
84 | |
85 | === modified file 'src/dbus-shared-names.h' |
86 | --- src/dbus-shared-names.h 2009-08-08 20:37:04 +0000 |
87 | +++ src/dbus-shared-names.h 2009-09-24 16:28:09 +0000 |
88 | @@ -7,16 +7,16 @@ |
89 | Authors: |
90 | Ted Gould <ted@canonical.com> |
91 | |
92 | -This program is free software: you can redistribute it and/or modify it |
93 | -under the terms of the GNU General Public License version 3, as published |
94 | +This program is free software: you can redistribute it and/or modify it |
95 | +under the terms of the GNU General Public License version 3, as published |
96 | by the Free Software Foundation. |
97 | |
98 | -This program is distributed in the hope that it will be useful, but |
99 | -WITHOUT ANY WARRANTY; without even the implied warranties of |
100 | -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
101 | +This program is distributed in the hope that it will be useful, but |
102 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
103 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
104 | PURPOSE. See the GNU General Public License for more details. |
105 | |
106 | -You should have received a copy of the GNU General Public License along |
107 | +You should have received a copy of the GNU General Public License along |
108 | with this program. If not, see <http://www.gnu.org/licenses/>. |
109 | */ |
110 | |
111 | @@ -31,6 +31,8 @@ |
112 | |
113 | #define INDICATOR_USERS_DBUS_NAME "org.ayatana.indicator.users" |
114 | #define INDICATOR_USERS_DBUS_OBJECT "/org/ayatana/indicator/users/menu" |
115 | +#define INDICATOR_USERS_SERVICE_DBUS_OBJECT "/org/gnome/DisplayManager/UserManager" |
116 | +#define INDICATOR_USERS_SERVICE_DBUS_INTERFACE "org.gnome.DisplayManager.UserManager" |
117 | |
118 | #define INDICATOR_SESSION_DBUS_NAME "org.ayatana.indicator.session" |
119 | #define INDICATOR_SESSION_DBUS_OBJECT "/org/ayatana/indicator/session/menu" |
120 | |
121 | === modified file 'src/status-service.c' |
122 | --- src/status-service.c 2009-09-16 21:00:17 +0000 |
123 | +++ src/status-service.c 2009-09-24 16:28:09 +0000 |
124 | @@ -7,16 +7,16 @@ |
125 | Authors: |
126 | Ted Gould <ted@canonical.com> |
127 | |
128 | -This program is free software: you can redistribute it and/or modify it |
129 | -under the terms of the GNU General Public License version 3, as published |
130 | +This program is free software: you can redistribute it and/or modify it |
131 | +under the terms of the GNU General Public License version 3, as published |
132 | by the Free Software Foundation. |
133 | |
134 | -This program is distributed in the hope that it will be useful, but |
135 | -WITHOUT ANY WARRANTY; without even the implied warranties of |
136 | -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
137 | +This program is distributed in the hope that it will be useful, but |
138 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
139 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
140 | PURPOSE. See the GNU General Public License for more details. |
141 | |
142 | -You should have received a copy of the GNU General Public License along |
143 | +You should have received a copy of the GNU General Public License along |
144 | with this program. If not, see <http://www.gnu.org/licenses/>. |
145 | */ |
146 | |
147 | @@ -238,12 +238,12 @@ |
148 | if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_STATUS_DBUS_NAME, 0, &nameret, &error)) { |
149 | g_error("Unable to call to request name"); |
150 | return 1; |
151 | - } |
152 | + } |
153 | |
154 | if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { |
155 | g_error("Unable to get name"); |
156 | return 1; |
157 | - } |
158 | + } |
159 | |
160 | g_idle_add(build_providers, NULL); |
161 | |
162 | |
163 | === added file 'src/users-service-dbus.c' |
164 | --- src/users-service-dbus.c 1970-01-01 00:00:00 +0000 |
165 | +++ src/users-service-dbus.c 2009-09-24 16:28:09 +0000 |
166 | @@ -0,0 +1,1147 @@ |
167 | +/* |
168 | + * Copyright 2009 Canonical Ltd. |
169 | + * |
170 | + * Authors: |
171 | + * Cody Russell <crussell@canonical.com> |
172 | + * |
173 | + * This program is free software: you can redistribute it and/or modify it |
174 | + * under the terms of the GNU General Public License version 3, as published |
175 | + * by the Free Software Foundation. |
176 | + * |
177 | + * This program is distributed in the hope that it will be useful, but |
178 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
179 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
180 | + * PURPOSE. See the GNU General Public License for more details. |
181 | + * |
182 | + * You should have received a copy of the GNU General Public License along |
183 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
184 | + */ |
185 | + |
186 | +#ifdef HAVE_CONFIG_H |
187 | +#include "config.h" |
188 | +#endif |
189 | + |
190 | +#include <string.h> |
191 | +#include <errno.h> |
192 | +#include <pwd.h> |
193 | + |
194 | +#include <dbus/dbus-glib.h> |
195 | +#include <dbus/dbus-glib.h> |
196 | +#include <dbus/dbus-glib-lowlevel.h> |
197 | + |
198 | +#include "dbus-shared-names.h" |
199 | +#include "users-service-dbus.h" |
200 | +#include "users-service-client.h" |
201 | +#include "users-service-marshal.h" |
202 | + |
203 | +static void users_service_dbus_class_init (UsersServiceDbusClass *klass); |
204 | +static void users_service_dbus_init (UsersServiceDbus *self); |
205 | +static void users_service_dbus_dispose (GObject *object); |
206 | +static void users_service_dbus_finalize (GObject *object); |
207 | +static void create_gdm_proxy (UsersServiceDbus *self); |
208 | +static void create_seat_proxy (UsersServiceDbus *self); |
209 | +static void create_ck_proxy (UsersServiceDbus *self); |
210 | +static void create_cksession_proxy (UsersServiceDbus *self); |
211 | +static gchar *get_seat (UsersServiceDbus *service); |
212 | +static void users_loaded (DBusGProxy *proxy, |
213 | + gpointer user_data); |
214 | +static void user_added (DBusGProxy *proxy, |
215 | + guint uid, |
216 | + gpointer user_data); |
217 | +static void user_removed (DBusGProxy *proxy, |
218 | + guint uid, |
219 | + gpointer user_data); |
220 | +static void user_updated (DBusGProxy *proxy, |
221 | + guint uid, |
222 | + gpointer user_data); |
223 | +static void seat_proxy_session_added (DBusGProxy *seat_proxy, |
224 | + const gchar *session_id, |
225 | + UsersServiceDbus *service); |
226 | +static void seat_proxy_session_removed (DBusGProxy *seat_proxy, |
227 | + const gchar *session_id, |
228 | + UsersServiceDbus *service); |
229 | +static gboolean do_add_session (UsersServiceDbus *service, |
230 | + UserData *user, |
231 | + const gchar *ssid); |
232 | +static gchar * get_seat_internal (UsersServiceDbus *self); |
233 | + |
234 | +/* Private */ |
235 | +typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate; |
236 | + |
237 | +struct _UsersServiceDbusPrivate |
238 | +{ |
239 | + GHashTable *users; |
240 | + gint count; |
241 | + gchar *seat; |
242 | + gchar *ssid; |
243 | + |
244 | + DBusGConnection *system_bus; |
245 | + |
246 | + DBusGProxy *gdm_proxy; |
247 | + DBusGProxy *ck_proxy; |
248 | + DBusGProxy *seat_proxy; |
249 | + DBusGProxy *session_proxy; |
250 | + |
251 | + GHashTable *exclusions; |
252 | + GHashTable *sessions; |
253 | +}; |
254 | + |
255 | +#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate)) |
256 | + |
257 | +/* Signals */ |
258 | +enum { |
259 | + USERS_LOADED, |
260 | + USER_ADDED, |
261 | + USER_REMOVED, |
262 | + USER_UPDATED, |
263 | + LAST_SIGNAL |
264 | +}; |
265 | + |
266 | +static guint signals[LAST_SIGNAL] = { 0 }; |
267 | + |
268 | +/* GObject Boilerplate */ |
269 | +G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT); |
270 | + |
271 | +static void |
272 | +users_service_dbus_class_init (UsersServiceDbusClass *klass) |
273 | +{ |
274 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
275 | + |
276 | + g_type_class_add_private (object_class, sizeof (UsersServiceDbusPrivate)); |
277 | + |
278 | + object_class->dispose = users_service_dbus_dispose; |
279 | + object_class->finalize = users_service_dbus_finalize; |
280 | + |
281 | + signals[USERS_LOADED] = g_signal_new ("users-loaded", |
282 | + G_TYPE_FROM_CLASS (klass), |
283 | + G_SIGNAL_RUN_LAST, |
284 | + G_STRUCT_OFFSET (UsersServiceDbusClass, users_loaded), |
285 | + NULL, NULL, |
286 | + g_cclosure_marshal_VOID__VOID, |
287 | + G_TYPE_NONE, 0); |
288 | + |
289 | + signals[USER_ADDED] = g_signal_new ("user-added", |
290 | + G_TYPE_FROM_CLASS (klass), |
291 | + G_SIGNAL_RUN_LAST, |
292 | + G_STRUCT_OFFSET (UsersServiceDbusClass, user_added), |
293 | + NULL, NULL, |
294 | + _users_service_marshal_VOID__INT64, |
295 | + G_TYPE_NONE, 1, G_TYPE_INT64); |
296 | + |
297 | + signals[USER_REMOVED] = g_signal_new ("user-removed", |
298 | + G_TYPE_FROM_CLASS (klass), |
299 | + G_SIGNAL_RUN_LAST, |
300 | + G_STRUCT_OFFSET (UsersServiceDbusClass, user_removed), |
301 | + NULL, NULL, |
302 | + _users_service_marshal_VOID__INT64, |
303 | + G_TYPE_NONE, 1, G_TYPE_INT64); |
304 | + |
305 | + signals[USER_UPDATED] = g_signal_new ("user-updated", |
306 | + G_TYPE_FROM_CLASS (klass), |
307 | + G_SIGNAL_RUN_LAST, |
308 | + G_STRUCT_OFFSET (UsersServiceDbusClass, user_updated), |
309 | + NULL, NULL, |
310 | + _users_service_marshal_VOID__INT64, |
311 | + G_TYPE_NONE, 1, G_TYPE_INT64); |
312 | +} |
313 | + |
314 | +static void |
315 | +users_service_dbus_init (UsersServiceDbus *self) |
316 | +{ |
317 | + GError *error = NULL; |
318 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
319 | + |
320 | + priv->users = NULL; |
321 | + priv->count = 0; |
322 | + |
323 | + /* Get the system bus */ |
324 | + priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); |
325 | + if (error != NULL) |
326 | + { |
327 | + g_error ("Unable to get system bus: %s", error->message); |
328 | + g_error_free(error); |
329 | + |
330 | + return; |
331 | + } |
332 | + |
333 | + priv->sessions = g_hash_table_new_full (g_str_hash, |
334 | + g_str_equal, |
335 | + g_free, |
336 | + g_free); |
337 | + |
338 | + priv->users = g_hash_table_new_full (g_str_hash, |
339 | + g_str_equal, |
340 | + g_free, |
341 | + NULL); |
342 | + |
343 | + dbus_g_object_register_marshaller (_users_service_marshal_VOID__INT64, |
344 | + G_TYPE_NONE, |
345 | + G_TYPE_INT64, |
346 | + G_TYPE_INVALID); |
347 | + |
348 | + create_gdm_proxy (self); |
349 | + create_ck_proxy (self); |
350 | + create_seat_proxy (self); |
351 | + |
352 | + users_loaded (priv->gdm_proxy, self); |
353 | +} |
354 | + |
355 | +static void |
356 | +users_service_dbus_dispose (GObject *object) |
357 | +{ |
358 | + G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object); |
359 | +} |
360 | + |
361 | +static void |
362 | +users_service_dbus_finalize (GObject *object) |
363 | +{ |
364 | + G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); |
365 | +} |
366 | + |
367 | +static void |
368 | +create_gdm_proxy (UsersServiceDbus *self) |
369 | +{ |
370 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
371 | + GError *error = NULL; |
372 | + |
373 | + priv->gdm_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus, |
374 | + "org.gnome.DisplayManager", |
375 | + "/org/gnome/DisplayManager/UserManager", |
376 | + "org.gnome.DisplayManager.UserManager", |
377 | + &error); |
378 | + |
379 | + if (!priv->gdm_proxy) |
380 | + { |
381 | + if (error != NULL) |
382 | + { |
383 | + g_error ("Unable to get DisplayManager proxy on system bus: %s", error->message); |
384 | + g_error_free (error); |
385 | + } |
386 | + |
387 | + return; |
388 | + } |
389 | + |
390 | + dbus_g_proxy_add_signal (priv->gdm_proxy, |
391 | + "UsersLoaded", |
392 | + G_TYPE_INVALID); |
393 | + |
394 | + dbus_g_proxy_add_signal (priv->gdm_proxy, |
395 | + "UserAdded", |
396 | + G_TYPE_INT64, |
397 | + G_TYPE_INVALID); |
398 | + |
399 | + dbus_g_proxy_add_signal (priv->gdm_proxy, |
400 | + "UserRemoved", |
401 | + G_TYPE_INT64, |
402 | + G_TYPE_INVALID); |
403 | + |
404 | + dbus_g_proxy_add_signal (priv->gdm_proxy, |
405 | + "UserUpdated", |
406 | + G_TYPE_INT64, |
407 | + G_TYPE_INVALID); |
408 | + |
409 | + dbus_g_proxy_connect_signal (priv->gdm_proxy, |
410 | + "UsersLoaded", |
411 | + G_CALLBACK (users_loaded), |
412 | + self, |
413 | + NULL); |
414 | + |
415 | + dbus_g_proxy_connect_signal (priv->gdm_proxy, |
416 | + "UserAdded", |
417 | + G_CALLBACK (user_added), |
418 | + self, |
419 | + NULL); |
420 | + |
421 | + dbus_g_proxy_connect_signal (priv->gdm_proxy, |
422 | + "UserRemoved", |
423 | + G_CALLBACK (user_removed), |
424 | + self, |
425 | + NULL); |
426 | + |
427 | + dbus_g_proxy_connect_signal (priv->gdm_proxy, |
428 | + "UserUpdated", |
429 | + G_CALLBACK (user_updated), |
430 | + self, |
431 | + NULL); |
432 | +} |
433 | + |
434 | +static void |
435 | +create_ck_proxy (UsersServiceDbus *self) |
436 | +{ |
437 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
438 | + |
439 | + priv->ck_proxy = dbus_g_proxy_new_for_name (priv->system_bus, |
440 | + "org.freedesktop.ConsoleKit", |
441 | + "/org/freedesktop/ConsoleKit/Manager", |
442 | + "org.freedesktop.ConsoleKit.Manager"); |
443 | + |
444 | + if (!priv->ck_proxy) |
445 | + { |
446 | + g_warning ("Failed to get ConsoleKit proxy."); |
447 | + return; |
448 | + } |
449 | +} |
450 | + |
451 | +static void |
452 | +create_seat_proxy (UsersServiceDbus *self) |
453 | +{ |
454 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
455 | + GError *error = NULL; |
456 | + |
457 | + priv->seat = get_seat (self); |
458 | + if (priv->seat == NULL) |
459 | + { |
460 | + return; |
461 | + } |
462 | + |
463 | + priv->seat_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus, |
464 | + "org.freedesktop.ConsoleKit", |
465 | + priv->seat, |
466 | + "org.freedesktop.ConsoleKit.Seat", |
467 | + &error); |
468 | + |
469 | + if (!priv->seat_proxy) |
470 | + { |
471 | + if (error != NULL) |
472 | + { |
473 | + g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message); |
474 | + g_error_free (error); |
475 | + } |
476 | + |
477 | + return; |
478 | + } |
479 | + |
480 | + dbus_g_proxy_add_signal (priv->seat_proxy, |
481 | + "SessionAdded", |
482 | + DBUS_TYPE_G_OBJECT_PATH, |
483 | + G_TYPE_INVALID); |
484 | + dbus_g_proxy_add_signal (priv->seat_proxy, |
485 | + "SessionRemoved", |
486 | + DBUS_TYPE_G_OBJECT_PATH, |
487 | + G_TYPE_INVALID); |
488 | + |
489 | + dbus_g_proxy_connect_signal (priv->seat_proxy, |
490 | + "SessionAdded", |
491 | + G_CALLBACK (seat_proxy_session_added), |
492 | + self, |
493 | + NULL); |
494 | + dbus_g_proxy_connect_signal (priv->seat_proxy, |
495 | + "SessionRemoved", |
496 | + G_CALLBACK (seat_proxy_session_removed), |
497 | + self, |
498 | + NULL); |
499 | +} |
500 | + |
501 | +static void |
502 | +create_cksession_proxy (UsersServiceDbus *service) |
503 | +{ |
504 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
505 | + |
506 | + priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus, |
507 | + "org.freedesktop.ConsoleKit", |
508 | + priv->ssid, |
509 | + "org.freedesktop.ConsoleKit.Session"); |
510 | + |
511 | + if (!priv->session_proxy) |
512 | + { |
513 | + g_warning ("Failed to get ConsoleKit session proxy"); |
514 | + return; |
515 | + } |
516 | +} |
517 | + |
518 | +static gchar * |
519 | +get_seat (UsersServiceDbus *service) |
520 | +{ |
521 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
522 | + GError *error = NULL; |
523 | + gchar *ssid = NULL; |
524 | + gchar *seat; |
525 | + |
526 | + if (!dbus_g_proxy_call (priv->ck_proxy, |
527 | + "GetCurrentSession", |
528 | + &error, |
529 | + G_TYPE_INVALID, |
530 | + DBUS_TYPE_G_OBJECT_PATH, |
531 | + &ssid, |
532 | + G_TYPE_INVALID)) |
533 | + { |
534 | + if (error) |
535 | + { |
536 | + g_debug ("Failed to call GetCurrentSession: %s", error->message); |
537 | + g_error_free (error); |
538 | + } |
539 | + |
540 | + if (ssid) |
541 | + g_free (ssid); |
542 | + |
543 | + return NULL; |
544 | + } |
545 | + |
546 | + priv->ssid = ssid; |
547 | + create_cksession_proxy (service); |
548 | + |
549 | + seat = get_seat_internal (service); |
550 | + |
551 | + return seat; |
552 | +} |
553 | + |
554 | +static gchar * |
555 | +get_seat_internal (UsersServiceDbus *self) |
556 | +{ |
557 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
558 | + GError *error = NULL; |
559 | + gchar *seat = NULL; |
560 | + |
561 | + if (!dbus_g_proxy_call (priv->session_proxy, |
562 | + "GetSeatId", |
563 | + &error, |
564 | + G_TYPE_INVALID, |
565 | + DBUS_TYPE_G_OBJECT_PATH, &seat, |
566 | + G_TYPE_INVALID)) |
567 | + { |
568 | + if (error) |
569 | + { |
570 | + g_debug ("Failed to call GetSeatId: %s", error->message); |
571 | + |
572 | + return NULL; |
573 | + } |
574 | + } |
575 | + |
576 | + return seat; |
577 | +} |
578 | + |
579 | +static gboolean |
580 | +get_unix_user (UsersServiceDbus *service, |
581 | + const gchar *session_id, |
582 | + uid_t *uidp) |
583 | +{ |
584 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
585 | + GError *error = NULL; |
586 | + guint uid; |
587 | + |
588 | + if (dbus_g_proxy_call (priv->session_proxy, |
589 | + "GetUnixUser", |
590 | + &error, |
591 | + G_TYPE_INVALID, |
592 | + G_TYPE_UINT, &uid, |
593 | + G_TYPE_INVALID)) |
594 | + { |
595 | + if (error) |
596 | + { |
597 | + g_warning ("Failed to call GetUnixUser: %s", error->message); |
598 | + g_error_free (error); |
599 | + } |
600 | + |
601 | + return FALSE; |
602 | + } |
603 | + |
604 | + if (uidp != NULL) |
605 | + { |
606 | + *uidp = (uid_t)uid; |
607 | + } |
608 | + |
609 | + return TRUE; |
610 | +} |
611 | + |
612 | +static gchar * |
613 | +get_session_for_user (UsersServiceDbus *service, |
614 | + UserData *user) |
615 | +{ |
616 | + GList *l; |
617 | + |
618 | + if (!users_service_dbus_can_activate_session (service)) |
619 | + { |
620 | + return NULL; |
621 | + } |
622 | + |
623 | + if (!user->sessions || g_list_length (user->sessions) == 0) |
624 | + { |
625 | + return NULL; |
626 | + } |
627 | + |
628 | + for (l = user->sessions; l != NULL; l = l->next) |
629 | + { |
630 | + const char *ssid; |
631 | + |
632 | + ssid = l->data; |
633 | + |
634 | + if (ssid) |
635 | + { |
636 | + return g_strdup (ssid); |
637 | + } |
638 | + } |
639 | + |
640 | + return NULL; |
641 | +} |
642 | + |
643 | +static gboolean |
644 | +do_add_session (UsersServiceDbus *service, |
645 | + UserData *user, |
646 | + const gchar *ssid) |
647 | +{ |
648 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
649 | + GError *error = NULL; |
650 | + gchar *seat = NULL; |
651 | + gchar *xdisplay = NULL; |
652 | + GList *l; |
653 | + |
654 | + seat = get_seat_internal (service); |
655 | + |
656 | + if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) |
657 | + return FALSE; |
658 | + |
659 | + if (!dbus_g_proxy_call (priv->session_proxy, |
660 | + "GetX11Display", |
661 | + &error, |
662 | + G_TYPE_INVALID, |
663 | + G_TYPE_STRING, &xdisplay, |
664 | + G_TYPE_INVALID)) |
665 | + { |
666 | + if (error) |
667 | + { |
668 | + g_debug ("Failed to call GetX11Display: %s", error->message); |
669 | + g_error_free (error); |
670 | + } |
671 | + |
672 | + return FALSE; |
673 | + } |
674 | + |
675 | + if (!xdisplay || xdisplay[0] == '\0') |
676 | + return FALSE; |
677 | + |
678 | + g_hash_table_insert (priv->sessions, |
679 | + g_strdup (ssid), |
680 | + g_strdup (user->user_name)); |
681 | + |
682 | + l = g_list_find_custom (user->sessions, ssid, (GCompareFunc)g_strcmp0); |
683 | + if (l == NULL) |
684 | + { |
685 | + g_debug ("Adding session %s", ssid); |
686 | + |
687 | + user->sessions = g_list_prepend (user->sessions, g_strdup (ssid)); |
688 | + } |
689 | + else |
690 | + { |
691 | + g_debug ("User %s already has session %s", user->user_name, ssid); |
692 | + } |
693 | + |
694 | + return TRUE; |
695 | +} |
696 | + |
697 | +static void |
698 | +add_sessions_for_user (UsersServiceDbus *self, |
699 | + UserData *user) |
700 | +{ |
701 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
702 | + GError *error; |
703 | + GPtrArray *sessions; |
704 | + int i; |
705 | + |
706 | + error = NULL; |
707 | + if (!dbus_g_proxy_call (priv->ck_proxy, |
708 | + "GetSessionsForUnixUser", |
709 | + &error, |
710 | + G_TYPE_UINT, user->uid, |
711 | + G_TYPE_INVALID, |
712 | + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), |
713 | + &sessions, |
714 | + G_TYPE_INVALID)) |
715 | + { |
716 | + g_debug ("Failed to call GetSessionsForUnixUser: %s", error->message); |
717 | + g_error_free (error); |
718 | + |
719 | + return; |
720 | + } |
721 | + |
722 | + for (i = 0; i < sessions->len; i++) |
723 | + { |
724 | + char *ssid; |
725 | + |
726 | + ssid = g_ptr_array_index (sessions, i); |
727 | + do_add_session (self, user, ssid); |
728 | + } |
729 | + |
730 | + g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); |
731 | + g_ptr_array_free (sessions, TRUE); |
732 | +} |
733 | + |
734 | + |
735 | +static void |
736 | +seat_proxy_session_added (DBusGProxy *seat_proxy, |
737 | + const gchar *session_id, |
738 | + UsersServiceDbus *service) |
739 | +{ |
740 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
741 | + uid_t uid; |
742 | + gboolean res; |
743 | + struct passwd *pwent; |
744 | + UserData *user; |
745 | + |
746 | + if (!get_unix_user (service, session_id, &uid)) |
747 | + { |
748 | + g_warning ("Failed to lookup user for session"); |
749 | + return; |
750 | + } |
751 | + |
752 | + errno = 0; |
753 | + pwent = getpwuid (uid); |
754 | + if (!pwent) |
755 | + { |
756 | + g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror (errno)); |
757 | + return; |
758 | + } |
759 | + |
760 | + user = g_hash_table_lookup (priv->users, pwent->pw_name); |
761 | + if (!user) |
762 | + { |
763 | + return; |
764 | + } |
765 | + |
766 | + res = do_add_session (service, user, session_id); |
767 | +} |
768 | + |
769 | +static void |
770 | +seat_proxy_session_removed (DBusGProxy *seat_proxy, |
771 | + const gchar *session_id, |
772 | + UsersServiceDbus *service) |
773 | +{ |
774 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
775 | + UserData *user; |
776 | + gchar *username; |
777 | + GList *l; |
778 | + |
779 | + username = g_hash_table_lookup (priv->sessions, session_id); |
780 | + if (!username) |
781 | + return; |
782 | + |
783 | + user = g_hash_table_lookup (priv->users, username); |
784 | + if (!user) |
785 | + return; |
786 | + |
787 | + l = g_list_find_custom (user->sessions, |
788 | + session_id, |
789 | + (GCompareFunc)g_strcmp0); |
790 | + if (l) |
791 | + { |
792 | + g_debug ("Removing session %s", session_id); |
793 | + |
794 | + g_free (l->data); |
795 | + user->sessions = g_list_delete_link (user->sessions, l); |
796 | + } |
797 | + else |
798 | + { |
799 | + g_debug ("Session not found: %s", session_id); |
800 | + } |
801 | +} |
802 | + |
803 | +static void |
804 | +sync_users (UsersServiceDbus *self) |
805 | +{ |
806 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
807 | + |
808 | + if (g_hash_table_size (priv->users) > 0) |
809 | + { |
810 | + return; |
811 | + } |
812 | + |
813 | + if (priv->count > MINIMUM_USERS && priv->count < MAXIMUM_USERS) |
814 | + { |
815 | + GArray *uids = NULL; |
816 | + GPtrArray *users_info = NULL; |
817 | + GError *error = NULL; |
818 | + gint i; |
819 | + |
820 | + uids = g_array_new (FALSE, FALSE, sizeof (gint64)); |
821 | + |
822 | + if (!org_gnome_DisplayManager_UserManager_get_user_list (priv->gdm_proxy, |
823 | + &uids, |
824 | + &error)) |
825 | + { |
826 | + g_warning ("failed to retrieve user list: %s", error->message); |
827 | + g_error_free (error); |
828 | + |
829 | + return; |
830 | + } |
831 | + |
832 | + users_info = g_ptr_array_new (); |
833 | + |
834 | + if (!org_gnome_DisplayManager_UserManager_get_users_info (priv->gdm_proxy, |
835 | + uids, |
836 | + &users_info, |
837 | + &error)) |
838 | + { |
839 | + g_warning ("failed to retrieve user info: %s", error->message); |
840 | + g_error_free (error); |
841 | + |
842 | + return; |
843 | + } |
844 | + |
845 | + for (i = 0; i < users_info->len; i++) |
846 | + { |
847 | + GValueArray *values; |
848 | + UserData *user; |
849 | + |
850 | + values = g_ptr_array_index (users_info, i); |
851 | + |
852 | + user = g_new0 (UserData, 1); |
853 | + |
854 | + user->uid = g_value_get_int64 (g_value_array_get_nth (values, 0)); |
855 | + user->user_name = g_strdup (g_value_get_string (g_value_array_get_nth (values, 1))); |
856 | + user->real_name = g_strdup (g_value_get_string (g_value_array_get_nth (values, 2))); |
857 | + user->shell = g_strdup (g_value_get_string (g_value_array_get_nth (values, 3))); |
858 | + user->login_count = g_value_get_int (g_value_array_get_nth (values, 4)); |
859 | + user->icon_url = g_strdup (g_value_get_string (g_value_array_get_nth (values, 5))); |
860 | + |
861 | + g_hash_table_insert (priv->users, |
862 | + g_strdup (user->user_name), |
863 | + user); |
864 | + |
865 | + add_sessions_for_user (self, user); |
866 | + } |
867 | + } |
868 | +} |
869 | + |
870 | +static void |
871 | +users_loaded (DBusGProxy *proxy, |
872 | + gpointer user_data) |
873 | +{ |
874 | + UsersServiceDbus *service; |
875 | + UsersServiceDbusPrivate *priv; |
876 | + GError *error = NULL; |
877 | + gint count; |
878 | + |
879 | + service = (UsersServiceDbus *)user_data; |
880 | + priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
881 | + |
882 | + if (!org_gnome_DisplayManager_UserManager_count_users (proxy, |
883 | + &count, |
884 | + &error)) |
885 | + { |
886 | + g_warning ("failed to retrieve user count: %s", error->message); |
887 | + g_error_free (error); |
888 | + |
889 | + return; |
890 | + } |
891 | + |
892 | + priv->count = count; |
893 | + |
894 | + sync_users (service); |
895 | +} |
896 | + |
897 | +static gboolean |
898 | +session_is_login_window (UsersServiceDbus *self, |
899 | + const char *ssid) |
900 | +{ |
901 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
902 | + DBusGProxy *proxy = NULL; |
903 | + GError *error = NULL; |
904 | + char *type = NULL; |
905 | + |
906 | + if (!(proxy = dbus_g_proxy_new_for_name (priv->system_bus, |
907 | + "org.freedesktop.ConsoleKit", |
908 | + ssid, |
909 | + "org.freedesktop.ConsoleKit.Session"))) |
910 | + { |
911 | + g_warning ("Failed to get ConsoleKit proxy"); |
912 | + |
913 | + return FALSE; |
914 | + } |
915 | + |
916 | + if (!dbus_g_proxy_call (proxy, |
917 | + "GetSessionType", |
918 | + &error, |
919 | + G_TYPE_INVALID, |
920 | + G_TYPE_STRING, &type, |
921 | + G_TYPE_INVALID)) |
922 | + { |
923 | + g_warning ("Can't call GetSessionType: %s", error->message); |
924 | + g_error_free (error); |
925 | + |
926 | + if (proxy) |
927 | + g_object_unref (proxy); |
928 | + |
929 | + return FALSE; |
930 | + } |
931 | + |
932 | + if (proxy) |
933 | + g_object_unref (proxy); |
934 | + |
935 | + return (type && type[0] != '\0' && strcmp (type, "LoginWindow") == 0); |
936 | +} |
937 | + |
938 | +static char * |
939 | +get_login_session (UsersServiceDbus *self) |
940 | +{ |
941 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
942 | + gboolean can_activate; |
943 | + GError *error = NULL; |
944 | + GPtrArray *sessions = NULL; |
945 | + char *ssid = NULL; |
946 | + int i; |
947 | + |
948 | + if (!priv->seat || priv->seat[0] == '\0') |
949 | + { |
950 | + return NULL; |
951 | + } |
952 | + |
953 | + if (!dbus_g_proxy_call (priv->seat_proxy, |
954 | + "CanActivateSessions", |
955 | + &error, |
956 | + G_TYPE_INVALID, |
957 | + G_TYPE_BOOLEAN, &can_activate, |
958 | + G_TYPE_INVALID)) |
959 | + { |
960 | + g_warning ("Failed to call CanActivateSessions: %s", error->message); |
961 | + g_error_free (error); |
962 | + |
963 | + return NULL; |
964 | + } |
965 | + |
966 | + if (!can_activate) |
967 | + { |
968 | + return NULL; |
969 | + } |
970 | + |
971 | + error = NULL; |
972 | + if (!dbus_g_proxy_call (priv->seat_proxy, |
973 | + "GetSessions", |
974 | + &error, |
975 | + G_TYPE_INVALID, |
976 | + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, |
977 | + G_TYPE_INVALID)) |
978 | + { |
979 | + g_warning ("Failed to call GetSessions: %s", error->message); |
980 | + g_error_free (error); |
981 | + |
982 | + return NULL; |
983 | + } |
984 | + |
985 | + for (i = 0; i < sessions->len; i++) |
986 | + { |
987 | + char *s = g_ptr_array_index (sessions, i); |
988 | + |
989 | + if (session_is_login_window (self, s)) |
990 | + { |
991 | + ssid = g_strdup (s); |
992 | + break; |
993 | + } |
994 | + } |
995 | + |
996 | + g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); |
997 | + g_ptr_array_free (sessions, TRUE); |
998 | + |
999 | + return ssid; |
1000 | +} |
1001 | + |
1002 | +static gboolean |
1003 | +activate_user_session (UsersServiceDbus *self, |
1004 | + const char *seat, |
1005 | + const char *ssid) |
1006 | +{ |
1007 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1008 | + DBusMessage *message = NULL; |
1009 | + DBusMessage *reply = NULL; |
1010 | + DBusError error; |
1011 | + |
1012 | + if (!(message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", |
1013 | + seat, |
1014 | + "org.freedesktop.ConsoleKit.Seat", |
1015 | + "ActivateSession"))) |
1016 | + { |
1017 | + return FALSE; |
1018 | + } |
1019 | + |
1020 | + if (!dbus_message_append_args (message, |
1021 | + DBUS_TYPE_OBJECT_PATH, &ssid, |
1022 | + DBUS_TYPE_INVALID)) |
1023 | + { |
1024 | + return FALSE; |
1025 | + } |
1026 | + |
1027 | + dbus_error_init (&error); |
1028 | + if (!(reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (priv->system_bus), |
1029 | + message, |
1030 | + -1, |
1031 | + &error))) |
1032 | + { |
1033 | + if (dbus_error_is_set (&error)) |
1034 | + { |
1035 | + g_warning ("Can't activate session: %s", error.message); |
1036 | + dbus_error_free (&error); |
1037 | + |
1038 | + return FALSE; |
1039 | + } |
1040 | + } |
1041 | + |
1042 | + if (message) |
1043 | + { |
1044 | + dbus_message_unref (message); |
1045 | + } |
1046 | + |
1047 | + if (reply) |
1048 | + { |
1049 | + dbus_message_unref (reply); |
1050 | + } |
1051 | + |
1052 | + return TRUE; |
1053 | +} |
1054 | + |
1055 | +gboolean |
1056 | +start_new_user_session (UsersServiceDbus *self, |
1057 | + UserData *user) |
1058 | +{ |
1059 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1060 | + GError *error = NULL; |
1061 | + char *ssid; |
1062 | + |
1063 | + ssid = get_login_session (self); |
1064 | + if (ssid) |
1065 | + { |
1066 | + if (!activate_user_session (self, priv->seat, ssid)) |
1067 | + { |
1068 | + return FALSE; |
1069 | + } |
1070 | + } |
1071 | + |
1072 | + if (!g_spawn_command_line_async ("gdmflexiserver -s", &error)) |
1073 | + { |
1074 | + g_warning ("Failed to start new login session: %s", error->message); |
1075 | + g_error_free (error); |
1076 | + |
1077 | + return FALSE; |
1078 | + } |
1079 | + |
1080 | + return TRUE; |
1081 | +} |
1082 | + |
1083 | +static void |
1084 | +user_added (DBusGProxy *proxy, |
1085 | + guint uid, |
1086 | + gpointer user_data) |
1087 | +{ |
1088 | + UsersServiceDbus *service = (UsersServiceDbus *)user_data; |
1089 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
1090 | + UserData *user = g_new0 (UserData, 1); |
1091 | + GError *error = NULL; |
1092 | + |
1093 | + priv->count++; |
1094 | + |
1095 | + if (priv->count < MAXIMUM_USERS) |
1096 | + { |
1097 | + if ((priv->count - g_hash_table_size (priv->users)) > 1) |
1098 | + { |
1099 | + sync_users (service); |
1100 | + } |
1101 | + else |
1102 | + { |
1103 | + if (!org_gnome_DisplayManager_UserManager_get_user_info (proxy, |
1104 | + uid, |
1105 | + &user->user_name, |
1106 | + &user->real_name, |
1107 | + &user->shell, |
1108 | + &user->login_count, |
1109 | + &user->icon_url, |
1110 | + &error)) |
1111 | + { |
1112 | + g_warning ("unable to retrieve user info: %s", error->message); |
1113 | + g_error_free (error); |
1114 | + |
1115 | + g_free (user); |
1116 | + |
1117 | + return; |
1118 | + } |
1119 | + |
1120 | + user->uid = uid; |
1121 | + |
1122 | + g_hash_table_insert (priv->users, |
1123 | + g_strdup (user->user_name), |
1124 | + user); |
1125 | + |
1126 | + g_signal_emit (G_OBJECT (service), signals[USER_ADDED], 0, user, TRUE); |
1127 | + } |
1128 | + } |
1129 | +} |
1130 | + |
1131 | +static gboolean |
1132 | +compare_users_by_uid (gpointer key, |
1133 | + gpointer value, |
1134 | + gpointer user_data) |
1135 | +{ |
1136 | + return (GPOINTER_TO_UINT (value) == GPOINTER_TO_UINT (user_data)); |
1137 | +} |
1138 | + |
1139 | +static void |
1140 | +user_removed (DBusGProxy *proxy, |
1141 | + guint uid, |
1142 | + gpointer user_data) |
1143 | +{ |
1144 | + UsersServiceDbus *service = (UsersServiceDbus *)user_data; |
1145 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
1146 | + UserData *user; |
1147 | + gint size; |
1148 | + |
1149 | + size = g_hash_table_size (priv->users); |
1150 | + |
1151 | + priv->count--; |
1152 | + |
1153 | + if (size == 0 || (size - priv->count) > 1) |
1154 | + { |
1155 | + sync_users (service); |
1156 | + } |
1157 | + else |
1158 | + { |
1159 | + user = g_hash_table_find (priv->users, |
1160 | + compare_users_by_uid, |
1161 | + GUINT_TO_POINTER (uid)); |
1162 | + |
1163 | + if (user != NULL) |
1164 | + { |
1165 | + g_hash_table_remove (priv->users, |
1166 | + user->user_name); |
1167 | + } |
1168 | + } |
1169 | +} |
1170 | + |
1171 | +static void |
1172 | +user_updated (DBusGProxy *proxy, |
1173 | + guint uid, |
1174 | + gpointer user_data) |
1175 | +{ |
1176 | +#if 0 |
1177 | + // XXX - TODO |
1178 | + UsersServiceDbus *service = (UsersServiceDbus *)user_data; |
1179 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); |
1180 | + UserData *user; |
1181 | + |
1182 | + user = g_hash_table_find (priv->users, |
1183 | + compare_users_by_uid, |
1184 | + GUINT_TO_POINTER (uid)); |
1185 | +#endif |
1186 | +} |
1187 | + |
1188 | +gint |
1189 | +users_service_dbus_get_user_count (UsersServiceDbus *self) |
1190 | +{ |
1191 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1192 | + |
1193 | + return priv->count; |
1194 | +} |
1195 | + |
1196 | +GList * |
1197 | +users_service_dbus_get_user_list (UsersServiceDbus *self) |
1198 | +{ |
1199 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1200 | + |
1201 | + return g_hash_table_get_values (priv->users); |
1202 | +} |
1203 | + |
1204 | +/* |
1205 | + * XXX - TODO: Right now we switch to a session that another user |
1206 | + * already has open, but if there are no open sessions |
1207 | + * for this user we go to the login screen and the |
1208 | + * user at the seat must select a user and enter a |
1209 | + * password. This kind of defeats the purpose of |
1210 | + * actually selecting a username, since selecting any |
1211 | + * user will do the same thing here. We need to change |
1212 | + * it so you only need to enter a password for the |
1213 | + * specified user. |
1214 | + */ |
1215 | +gboolean |
1216 | +users_service_dbus_activate_user_session (UsersServiceDbus *self, |
1217 | + UserData *user) |
1218 | +{ |
1219 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1220 | + DBusMessage *message = NULL; |
1221 | + DBusMessage *reply = NULL; |
1222 | + DBusError error; |
1223 | + gchar *ssid; |
1224 | + |
1225 | + dbus_error_init (&error); |
1226 | + |
1227 | + if (!priv->seat) |
1228 | + priv->seat = get_seat (self); |
1229 | + |
1230 | + ssid = get_session_for_user (self, user); |
1231 | + |
1232 | + if (!ssid) |
1233 | + { |
1234 | + return start_new_user_session (self, user); |
1235 | + } |
1236 | + |
1237 | + if (!(message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", |
1238 | + priv->seat, |
1239 | + "org.freedesktop.ConsoleKit.Seat", |
1240 | + "ActivateSession"))) |
1241 | + { |
1242 | + g_warning ("failed to create new message"); |
1243 | + return FALSE; |
1244 | + } |
1245 | + |
1246 | + if (!dbus_message_append_args (message, |
1247 | + DBUS_TYPE_OBJECT_PATH, |
1248 | + &ssid, |
1249 | + DBUS_TYPE_INVALID)) |
1250 | + { |
1251 | + g_warning ("failed to append args"); |
1252 | + return FALSE; |
1253 | + } |
1254 | + |
1255 | + if (!(reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (priv->system_bus), |
1256 | + message, |
1257 | + -1, |
1258 | + &error))) |
1259 | + { |
1260 | + if (dbus_error_is_set (&error)) |
1261 | + { |
1262 | + g_warning ("Failed to send message: %s", error.message); |
1263 | + dbus_error_free (&error); |
1264 | + |
1265 | + return FALSE; |
1266 | + } |
1267 | + } |
1268 | + |
1269 | + if (message) |
1270 | + { |
1271 | + dbus_message_unref (message); |
1272 | + } |
1273 | + |
1274 | + if (reply) |
1275 | + { |
1276 | + dbus_message_unref (reply); |
1277 | + } |
1278 | + |
1279 | + return TRUE; |
1280 | +} |
1281 | + |
1282 | +gboolean |
1283 | +users_service_dbus_can_activate_session (UsersServiceDbus *self) |
1284 | +{ |
1285 | + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); |
1286 | + gboolean can_activate = FALSE; |
1287 | + GError *error = NULL; |
1288 | + |
1289 | + if (!priv->seat_proxy) |
1290 | + { |
1291 | + create_seat_proxy (self); |
1292 | + } |
1293 | + |
1294 | + if (!priv->seat || priv->seat[0] == '\0') |
1295 | + { |
1296 | + return FALSE; |
1297 | + } |
1298 | + |
1299 | + if (!dbus_g_proxy_call (priv->seat_proxy, |
1300 | + "CanActivateSessions", |
1301 | + &error, |
1302 | + G_TYPE_INVALID, |
1303 | + G_TYPE_BOOLEAN, &can_activate, |
1304 | + G_TYPE_INVALID)) |
1305 | + { |
1306 | + g_warning ("Failed to determine if seat can activate sessions: %s", error->message); |
1307 | + g_error_free (error); |
1308 | + |
1309 | + return FALSE; |
1310 | + } |
1311 | + |
1312 | + return can_activate; |
1313 | +} |
1314 | |
1315 | === added file 'src/users-service-dbus.h' |
1316 | --- src/users-service-dbus.h 1970-01-01 00:00:00 +0000 |
1317 | +++ src/users-service-dbus.h 2009-09-24 16:28:09 +0000 |
1318 | @@ -0,0 +1,81 @@ |
1319 | +/* |
1320 | + * Copyright 2009 Canonical Ltd. |
1321 | + * |
1322 | + * Authors: |
1323 | + * Cody Russell <crussell@canonical.com> |
1324 | + * |
1325 | + * This program is free software: you can redistribute it and/or modify it |
1326 | + * under the terms of the GNU General Public License version 3, as published |
1327 | + * by the Free Software Foundation. |
1328 | + * |
1329 | + * This program is distributed in the hope that it will be useful, but |
1330 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1331 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1332 | + * PURPOSE. See the GNU General Public License for more details. |
1333 | + * |
1334 | + * You should have received a copy of the GNU General Public License along |
1335 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1336 | + */ |
1337 | + |
1338 | +#ifndef __USERS_SERVICE_DBUS_H__ |
1339 | +#define __USERS_SERVICE_DBUS_H__ |
1340 | + |
1341 | +#include <glib.h> |
1342 | +#include <glib-object.h> |
1343 | + |
1344 | +G_BEGIN_DECLS |
1345 | + |
1346 | +#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ()) |
1347 | +#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus)) |
1348 | +#define USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass)) |
1349 | +#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE)) |
1350 | +#define IS_USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), USERS_SERVICE_DBUS_TYPE)) |
1351 | +#define USERS_SERVICE_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass)) |
1352 | + |
1353 | +typedef struct _UsersServiceDbus UsersServiceDbus; |
1354 | +typedef struct _UsersServiceDbusClass UsersServiceDbusClass; |
1355 | +typedef struct _UserData UserData; |
1356 | + |
1357 | +struct _UserData |
1358 | +{ |
1359 | + gint64 uid; |
1360 | + gchar *user_name; |
1361 | + gchar *real_name; |
1362 | + gchar *shell; |
1363 | + gint login_count; |
1364 | + gchar *icon_url; |
1365 | + |
1366 | + GList *sessions; |
1367 | + |
1368 | + UsersServiceDbus *service; |
1369 | +}; |
1370 | + |
1371 | +#define MINIMUM_USERS 1 |
1372 | +#define MAXIMUM_USERS 7 |
1373 | + |
1374 | +struct _UsersServiceDbus { |
1375 | + GObject parent; |
1376 | +}; |
1377 | + |
1378 | +struct _UsersServiceDbusClass { |
1379 | + GObjectClass parent_class; |
1380 | + |
1381 | + /* Signals */ |
1382 | + void (* users_loaded) (UsersServiceDbus *self, gpointer user_data); |
1383 | + |
1384 | + void (* user_added) (UsersServiceDbus *self, gint64 uid, gpointer user_data); |
1385 | + void (* user_removed) (UsersServiceDbus *self, gint64 uid, gpointer user_data); |
1386 | + void (* user_updated) (UsersServiceDbus *self, gint64 uid, gpointer user_data); |
1387 | +}; |
1388 | + |
1389 | +GType users_service_dbus_get_type (void) G_GNUC_CONST; |
1390 | + |
1391 | +gint users_service_dbus_get_user_count (UsersServiceDbus *self); |
1392 | +GList *users_service_dbus_get_user_list (UsersServiceDbus *self); |
1393 | +gboolean users_service_dbus_can_activate_session (UsersServiceDbus *self); |
1394 | +gboolean users_service_dbus_activate_user_session (UsersServiceDbus *self, |
1395 | + UserData *user); |
1396 | + |
1397 | +G_END_DECLS |
1398 | + |
1399 | +#endif |
1400 | |
1401 | === modified file 'src/users-service.c' |
1402 | --- src/users-service.c 2009-09-16 16:34:26 +0000 |
1403 | +++ src/users-service.c 2009-09-24 16:28:09 +0000 |
1404 | @@ -1,24 +1,25 @@ |
1405 | /* |
1406 | -A small wrapper utility to load indicators and put them as menu items |
1407 | -into the gnome-panel using it's applet interface. |
1408 | - |
1409 | -Copyright 2009 Canonical Ltd. |
1410 | - |
1411 | -Authors: |
1412 | - Ted Gould <ted@canonical.com> |
1413 | - |
1414 | -This program is free software: you can redistribute it and/or modify it |
1415 | -under the terms of the GNU General Public License version 3, as published |
1416 | -by the Free Software Foundation. |
1417 | - |
1418 | -This program is distributed in the hope that it will be useful, but |
1419 | -WITHOUT ANY WARRANTY; without even the implied warranties of |
1420 | -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1421 | -PURPOSE. See the GNU General Public License for more details. |
1422 | - |
1423 | -You should have received a copy of the GNU General Public License along |
1424 | -with this program. If not, see <http://www.gnu.org/licenses/>. |
1425 | -*/ |
1426 | + * A small wrapper utility to load indicators and put them as menu items |
1427 | + * into the gnome-panel using it's applet interface. |
1428 | + * |
1429 | + * Copyright 2009 Canonical Ltd. |
1430 | + * |
1431 | + * Authors: |
1432 | + * Ted Gould <ted@canonical.com> |
1433 | + * Cody Russell <crussell@canonical.com> |
1434 | + * |
1435 | + * This program is free software: you can redistribute it and/or modify it |
1436 | + * under the terms of the GNU General Public License version 3, as published |
1437 | + * by the Free Software Foundation. |
1438 | + * |
1439 | + * This program is distributed in the hope that it will be useful, but |
1440 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1441 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1442 | + * PURPOSE. See the GNU General Public License for more details. |
1443 | + * |
1444 | + * You should have received a copy of the GNU General Public License along |
1445 | + *with this program. If not, see <http://www.gnu.org/licenses/>. |
1446 | + */ |
1447 | |
1448 | #include <config.h> |
1449 | |
1450 | @@ -33,15 +34,27 @@ |
1451 | #include <libdbusmenu-glib/menuitem.h> |
1452 | |
1453 | #include "dbus-shared-names.h" |
1454 | +#include "users-service-dbus.h" |
1455 | |
1456 | #define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch" |
1457 | |
1458 | -static DBusGConnection * session_bus = NULL; |
1459 | -static DBusGConnection * system_bus = NULL; |
1460 | -static DBusGProxy * bus_proxy = NULL; |
1461 | -static DBusGProxy * gdm_proxy = NULL; |
1462 | -static DbusmenuMenuitem * root_menuitem = NULL; |
1463 | -static GMainLoop * mainloop = NULL; |
1464 | +typedef struct _ActivateData ActivateData; |
1465 | +struct _ActivateData |
1466 | +{ |
1467 | + UsersServiceDbus *service; |
1468 | + UserData *user; |
1469 | +}; |
1470 | + |
1471 | +static DBusGConnection *session_bus = NULL; |
1472 | +static DBusGConnection *system_bus = NULL; |
1473 | +static DBusGProxy *bus_proxy = NULL; |
1474 | +static DBusGProxy *gdm_proxy = NULL; |
1475 | +static DbusmenuMenuitem *root_menuitem = NULL; |
1476 | +static GMainLoop *mainloop = NULL; |
1477 | +static UsersServiceDbus *dbus_interface = NULL; |
1478 | + |
1479 | +static gint count; |
1480 | +static GList *users; |
1481 | |
1482 | static gboolean |
1483 | check_guest_session (void) |
1484 | @@ -137,29 +150,134 @@ |
1485 | } |
1486 | |
1487 | static void |
1488 | -create_items (DbusmenuMenuitem * root) { |
1489 | - DbusmenuMenuitem * mi = NULL; |
1490 | - |
1491 | - mi = dbusmenu_menuitem_new(); |
1492 | - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen")); |
1493 | - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL); |
1494 | - dbusmenu_menuitem_child_append(root, mi); |
1495 | - |
1496 | - if (check_guest_session()) { |
1497 | - mi = dbusmenu_menuitem_new(); |
1498 | - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Guest Session")); |
1499 | - dbusmenu_menuitem_child_append(root, mi); |
1500 | - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_guest_session), NULL); |
1501 | - } |
1502 | - |
1503 | - if (check_new_session()) { |
1504 | - mi = dbusmenu_menuitem_new(); |
1505 | - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Switch User...")); |
1506 | - dbusmenu_menuitem_child_append(root, mi); |
1507 | - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_new_session), NULL); |
1508 | - } |
1509 | - |
1510 | - return; |
1511 | +activate_user_session (DbusmenuMenuitem *mi, gpointer user_data) |
1512 | +{ |
1513 | + UserData *user = (UserData *)user_data; |
1514 | + UsersServiceDbus *service = user->service; |
1515 | + |
1516 | + users_service_dbus_activate_user_session (service, user); |
1517 | +} |
1518 | + |
1519 | +static void |
1520 | +remove_menu_item (DbusmenuMenuitem *root, gpointer user_data) |
1521 | +{ |
1522 | + DbusmenuMenuitem *child = (DbusmenuMenuitem *)user_data; |
1523 | + |
1524 | + dbusmenu_menuitem_child_delete (root, child); |
1525 | +} |
1526 | + |
1527 | +static gint |
1528 | +compare_users_by_username (const gchar *a, |
1529 | + const gchar *b) |
1530 | +{ |
1531 | + UserData *user1 = (UserData *)a; |
1532 | + UserData *user2 = (UserData *)b; |
1533 | + |
1534 | + return g_strcmp0 (user1->user_name, user2->user_name); |
1535 | +} |
1536 | + |
1537 | +static void |
1538 | +rebuild_items (DbusmenuMenuitem *root, |
1539 | + UsersServiceDbus *service) |
1540 | +{ |
1541 | + DbusmenuMenuitem *mi = NULL; |
1542 | + GList *u; |
1543 | + UserData *user; |
1544 | + gboolean can_activate; |
1545 | + |
1546 | + can_activate = users_service_dbus_can_activate_session (service); |
1547 | + |
1548 | + dbusmenu_menuitem_foreach (root, remove_menu_item, NULL); |
1549 | + |
1550 | + mi = dbusmenu_menuitem_new(); |
1551 | + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen")); |
1552 | + g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL); |
1553 | + dbusmenu_menuitem_child_append(root, mi); |
1554 | + |
1555 | + if (can_activate == TRUE) |
1556 | + { |
1557 | + if (check_guest_session ()) |
1558 | + { |
1559 | + mi = dbusmenu_menuitem_new (); |
1560 | + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Guest Session")); |
1561 | + dbusmenu_menuitem_child_append (root, mi); |
1562 | + g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), NULL); |
1563 | + } |
1564 | + |
1565 | + if (count > MINIMUM_USERS && count < MAXIMUM_USERS) |
1566 | + { |
1567 | + if (users != NULL) |
1568 | + { |
1569 | + GList *l = NULL; |
1570 | + |
1571 | + for (l = users; l != NULL; l = l->next) |
1572 | + { |
1573 | + users = g_list_delete_link (users, l); |
1574 | + } |
1575 | + |
1576 | + users = NULL; |
1577 | + } |
1578 | + |
1579 | + users = users_service_dbus_get_user_list (service); |
1580 | + |
1581 | + users = g_list_sort (users, (GCompareFunc)compare_users_by_username); |
1582 | + |
1583 | + for (u = users; u != NULL; u = g_list_next (u)) |
1584 | + { |
1585 | + user = u->data; |
1586 | + |
1587 | + user->service = service; |
1588 | + |
1589 | + mi = dbusmenu_menuitem_new (); |
1590 | + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, user->real_name); |
1591 | + dbusmenu_menuitem_child_append (root, mi); |
1592 | + g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_user_session), user); |
1593 | + } |
1594 | + } |
1595 | + |
1596 | + if (check_new_session ()) |
1597 | + { |
1598 | + mi = dbusmenu_menuitem_new (); |
1599 | + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, _("New Session...")); |
1600 | + dbusmenu_menuitem_child_append (root, mi); |
1601 | + g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), NULL); |
1602 | + } |
1603 | + } |
1604 | +} |
1605 | + |
1606 | +static void |
1607 | +user_added (UsersServiceDbus *service, |
1608 | + UserData *user, |
1609 | + gpointer user_data) |
1610 | +{ |
1611 | + DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data; |
1612 | + |
1613 | + count++; |
1614 | + |
1615 | + rebuild_items (root, service); |
1616 | +} |
1617 | + |
1618 | +static void |
1619 | +user_removed (UsersServiceDbus *service, |
1620 | + UserData *user, |
1621 | + gpointer user_data) |
1622 | +{ |
1623 | + DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data; |
1624 | + |
1625 | + count--; |
1626 | + |
1627 | + rebuild_items (root, service); |
1628 | +} |
1629 | + |
1630 | +static void |
1631 | +create_items (DbusmenuMenuitem *root, |
1632 | + UsersServiceDbus *service) |
1633 | +{ |
1634 | + g_return_if_fail (IS_USERS_SERVICE_DBUS (service)); |
1635 | + |
1636 | + count = users_service_dbus_get_user_count (service); |
1637 | + |
1638 | + rebuild_items (root, service); |
1639 | } |
1640 | |
1641 | int |
1642 | @@ -167,35 +285,46 @@ |
1643 | { |
1644 | g_type_init(); |
1645 | |
1646 | - /* Setting up i18n and gettext. Apparently, we need |
1647 | - all of these. */ |
1648 | - setlocale (LC_ALL, ""); |
1649 | - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
1650 | - textdomain (GETTEXT_PACKAGE); |
1651 | + /* Setting up i18n and gettext. Apparently, we need |
1652 | + all of these. */ |
1653 | + setlocale (LC_ALL, ""); |
1654 | + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
1655 | + textdomain (GETTEXT_PACKAGE); |
1656 | |
1657 | session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); |
1658 | - bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); |
1659 | + bus_proxy = dbus_g_proxy_new_for_name (session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); |
1660 | GError * error = NULL; |
1661 | guint nameret = 0; |
1662 | |
1663 | if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_USERS_DBUS_NAME, 0, &nameret, &error)) { |
1664 | g_error("Unable to call to request name"); |
1665 | return 1; |
1666 | - } |
1667 | + } |
1668 | |
1669 | if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { |
1670 | g_error("Unable to get name"); |
1671 | return 1; |
1672 | - } |
1673 | - |
1674 | - root_menuitem = dbusmenu_menuitem_new(); |
1675 | - g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem)); |
1676 | - |
1677 | - create_items(root_menuitem); |
1678 | + } |
1679 | + |
1680 | + dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); |
1681 | + |
1682 | + root_menuitem = dbusmenu_menuitem_new (); |
1683 | + g_debug ("Root ID: %d", dbusmenu_menuitem_get_id (root_menuitem)); |
1684 | + |
1685 | + create_items (root_menuitem, dbus_interface); |
1686 | |
1687 | DbusmenuServer * server = dbusmenu_server_new(INDICATOR_USERS_DBUS_OBJECT); |
1688 | dbusmenu_server_set_root(server, root_menuitem); |
1689 | |
1690 | + g_signal_connect (G_OBJECT (dbus_interface), |
1691 | + "user-added", |
1692 | + G_CALLBACK (user_added), |
1693 | + root_menuitem); |
1694 | + g_signal_connect (G_OBJECT (dbus_interface), |
1695 | + "user-removed", |
1696 | + G_CALLBACK (user_removed), |
1697 | + root_menuitem); |
1698 | + |
1699 | mainloop = g_main_loop_new(NULL, FALSE); |
1700 | g_main_loop_run(mainloop); |
1701 | |
1702 | |
1703 | === added file 'src/users-service.list' |
1704 | --- src/users-service.list 1970-01-01 00:00:00 +0000 |
1705 | +++ src/users-service.list 2009-09-24 16:28:09 +0000 |
1706 | @@ -0,0 +1,1 @@ |
1707 | +VOID:INT64 |
1708 | |
1709 | === added file 'src/users-service.xml' |
1710 | --- src/users-service.xml 1970-01-01 00:00:00 +0000 |
1711 | +++ src/users-service.xml 2009-09-24 16:28:09 +0000 |
1712 | @@ -0,0 +1,56 @@ |
1713 | +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
1714 | +<node name="/org/gnome/DisplayManager/UserManager"> |
1715 | + <interface name="org.gnome.DisplayManager.UserManager"> |
1716 | + |
1717 | + <!-- Get the number of known users --> |
1718 | + <method name="CountUsers"> |
1719 | + <arg name="user_count" direction="out" type="i"/> |
1720 | + </method> |
1721 | + |
1722 | + <!-- Get the list of known UIDs --> |
1723 | + <method name="GetUserList"> |
1724 | + <arg name="uids" direction="out" type="ax"/> |
1725 | + </method> |
1726 | + |
1727 | + <!-- Get user info for a user --> |
1728 | + <method name="GetUserInfo"> |
1729 | + <arg name="uid" direction="in" type="x"/> |
1730 | + <arg name="user_name" direction="out" type="s"/> |
1731 | + <arg name="real_name" direction="out" type="s"/> |
1732 | + <arg name="shell" direction="out" type="s"/> |
1733 | + <arg name="login_count" direction="out" type="i"/> |
1734 | + <arg name="icon_url" direction="out" type="s"/> |
1735 | + </method> |
1736 | + |
1737 | + <!-- Get user info for a list of users --> |
1738 | + <method name="GetUsersInfo"> |
1739 | + <arg name="uid" direction="in" type="ax"/> |
1740 | + <!-- (uid, user_name, real_name, shell, icon_url) --> |
1741 | + <arg name="user_info" direction="out" type="a(xsssis)"/> |
1742 | + </method> |
1743 | + |
1744 | + <!-- Query if the initial user list is loaded --> |
1745 | + <method name="GetUsersLoaded"> |
1746 | + <arg name="is_loaded" direction="out" type="b"/> |
1747 | + </method> |
1748 | + |
1749 | + <!-- Triggered when the initial user list is loaded --> |
1750 | + <signal name="UsersLoaded"></signal> |
1751 | + |
1752 | + <!-- Triggered when a users are added to/removed from the system. |
1753 | + Clients should monitor these signals as soon as they connect to |
1754 | + this object --> |
1755 | + <signal name="UserAdded"> |
1756 | + <arg name="uid" type="x"/> |
1757 | + </signal> |
1758 | + <signal name="UserRemoved"> |
1759 | + <arg name="uid" type="x"/> |
1760 | + </signal> |
1761 | + |
1762 | + <!-- Triggered when a user has updated information --> |
1763 | + <signal name="UserUpdated"> |
1764 | + <arg name="uid" type="x"/> |
1765 | + </signal> |
1766 | + |
1767 | + </interface> |
1768 | +</node> |
* In users-service.c I don't see where count is updated. I think decremented on user added/removed.
dbus_g_ object_ type_install_ info, that should only be needed if connection_ register_ g_object can be dropped server. h. Drop that file. sions" call to ConsoleKit. Do
it should be incremented/
* There should be icons on the users if they are set (probably
should go in another branch/bug)
* There doesn't seem to be any sorting of the user list. They
should be sorted alphabetical by first name.
* There are six signals defined in the Class structure but only 4
created on class init.
* I don't think that you need a call to
this object is being shared over DBus (server) but I think it's
only a client.
* Confirm with Robert, but I'm pretty sure the excludes list is
already being applied on the GDM side. We shouldn't need to
apply it on this side as well. That way there's only one copy
of the list.
* I think that dbus_g_
as well. Which I think is the only reason you're using the
session bus, so I think that can be dropped.
* Oh, now realizing more of the issue. Makefile.am shouldn't even
be generating user-service-
* I don't think that dbus_proxy_system and dbus_proxy_session are
needed as we're not asking DBus itself for any information.
We're just using it to communicate. We'd only need those
proxies to query information about the bus itself.
* Can session_compare be replaced with g_strcmp0? It seems about
the same.
* I was looking at "CanActivateSes
you think we should check this earlier and make the menu items
sensitive or insensitive based on this?
* It looks like you're always getting the information on all the
users. I think that we really don't care if it's over our max,
so can we just not bother getting all that data if we're in
overflow?
* The guest user needs to be handled as well. If there is a guest
already logged in selecting the guest on the menu shouldn't
start a new session, but should go to the guest that is already
running.
review needs-fixing