]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/session.c
Do not insert null session into sessions
[sojka/lightdm.git] / liblightdm-gobject / session.c
1 /*
2  * Copyright (C) 2010 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  * 
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the Free
7  * Software Foundation; either version 3 of the License, or (at your option) any
8  * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
9  * license.
10  */
11
12 #include <string.h>
13 #include <gio/gdesktopappinfo.h>
14
15 #include "lightdm/session.h"
16
17 enum {
18     PROP_0,
19     PROP_KEY,
20     PROP_NAME,
21     PROP_COMMENT
22 };
23
24 typedef struct
25 {
26     gchar *key;
27     gchar *name;
28     gchar *comment;
29 } LightDMSessionPrivate;
30
31 G_DEFINE_TYPE (LightDMSession, lightdm_session, G_TYPE_OBJECT);
32
33 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_SESSION, LightDMSessionPrivate)
34
35 static gboolean have_sessions = FALSE;
36 static GList *local_sessions = NULL;
37 static GList *remote_sessions = NULL;
38
39 static gint 
40 compare_session (gconstpointer a, gconstpointer b)
41 {
42     LightDMSessionPrivate *priv_a = GET_PRIVATE (a);
43     LightDMSessionPrivate *priv_b = GET_PRIVATE (b);
44     return strcmp (priv_a->name, priv_b->name);
45 }
46
47 static LightDMSession *
48 load_session (GKeyFile *key_file, const gchar *key)
49 {
50     gchar *domain, *name;
51     LightDMSession *session;
52     LightDMSessionPrivate *priv;
53     gchar *try_exec;
54   
55     if (g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL) ||
56         g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_HIDDEN, NULL))
57         return NULL;
58
59 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
60     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
61 #else
62     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
63 #endif
64     name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
65     if (!name)
66     {
67         g_warning ("Ignoring session without name");
68         g_free (domain);
69         return NULL;
70     }
71
72     try_exec = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TRY_EXEC, domain, NULL);
73     if (try_exec)
74     {
75         gchar *full_path;
76
77         full_path = g_find_program_in_path (try_exec);
78         g_free (try_exec);
79
80         if (!full_path)
81         {
82             g_free (name);
83             g_free (domain);
84             return NULL;
85         }
86         g_free (full_path);
87     }
88
89     session = g_object_new (LIGHTDM_TYPE_SESSION, NULL);
90     priv = GET_PRIVATE (session);
91
92     g_free (priv->key);
93     priv->key = g_strdup (key);
94
95     g_free (priv->name);
96     priv->name = name;
97
98     g_free (priv->comment);
99     priv->comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
100     if (!priv->comment)
101         priv->comment = g_strdup ("");
102
103     g_free (domain);
104
105     return session;
106 }
107
108 static GList *
109 load_sessions (const gchar *sessions_dir)
110 {
111     GDir *directory;
112     GList *sessions = NULL;
113     GError *error = NULL;
114
115     directory = g_dir_open (sessions_dir, 0, &error);
116     if (error)
117         g_warning ("Failed to open sessions directory: %s", error->message);
118     g_clear_error (&error);
119     if (!directory)
120         return NULL;
121
122     while (TRUE)
123     {
124         const gchar *filename;
125         gchar *path;
126         GKeyFile *key_file;
127         gboolean result;
128
129         filename = g_dir_read_name (directory);
130         if (filename == NULL)
131             break;
132
133         if (!g_str_has_suffix (filename, ".desktop"))
134             continue;
135
136         path = g_build_filename (sessions_dir, filename, NULL);
137
138         key_file = g_key_file_new ();
139         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
140         if (error)
141             g_warning ("Failed to load session file %s: %s:", path, error->message);
142         g_clear_error (&error);
143
144         if (result)
145         {
146             gchar *key;
147             LightDMSession *session;
148
149             key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
150             session = load_session (key_file, key);
151             if (session)
152             {
153                 g_debug ("Loaded session %s (%s, %s)", path, GET_PRIVATE (session)->name, GET_PRIVATE (session)->comment);
154                 sessions = g_list_insert_sorted (sessions, session, compare_session);
155             }
156             else
157                 g_debug ("Ignoring session %s", path);
158             g_free (key);
159         }
160
161         g_free (path);
162         g_key_file_free (key_file);
163     }
164
165     g_dir_close (directory);
166   
167     return sessions;
168 }
169
170 static void
171 update_sessions (void)
172 {
173     GKeyFile *config_key_file = NULL;
174     gchar *config_path = NULL;
175     gchar *xsessions_dir;
176     gchar *remote_sessions_dir;
177     gboolean result;
178     GError *error = NULL;
179
180     if (have_sessions)
181         return;
182
183     xsessions_dir = g_strdup (XSESSIONS_DIR);
184     remote_sessions_dir = g_strdup (REMOTE_SESSIONS_DIR);
185
186     /* Use session directory from configuration */
187     /* FIXME: This should be sent in the greeter connection */
188     config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL);
189     config_key_file = g_key_file_new ();
190     result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error);
191     if (error)
192         g_warning ("Failed to open configuration file: %s", error->message);
193     g_clear_error (&error);
194     if (result)
195     {
196         gchar *value;
197       
198         value = g_key_file_get_string (config_key_file, "LightDM", "xsessions-directory", NULL);
199         if (value)
200         {
201             g_free (xsessions_dir);
202             xsessions_dir = value;
203         }
204
205         value = g_key_file_get_string (config_key_file, "LightDM", "remote-sessions-directory", NULL);
206         if (value)
207         {
208             g_free (remote_sessions_dir);
209             remote_sessions_dir = value;
210         }
211     }
212     g_key_file_free (config_key_file);
213     g_free (config_path);
214
215     local_sessions = load_sessions (xsessions_dir);
216     remote_sessions = load_sessions (remote_sessions_dir);
217
218     g_free (xsessions_dir);
219     g_free (remote_sessions_dir);
220
221     have_sessions = TRUE;
222 }
223
224 /**
225  * lightdm_get_sessions:
226  *
227  * Get the available sessions.
228  *
229  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
230  **/
231 GList *
232 lightdm_get_sessions (void)
233 {
234     update_sessions ();
235     return local_sessions;
236 }
237
238 /**
239  * lightdm_get_remote_sessions:
240  *
241  * Get the available remote sessions.
242  *
243  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
244  **/
245 GList *
246 lightdm_get_remote_sessions (void)
247 {
248     update_sessions ();
249     return remote_sessions;
250 }
251
252 /**
253  * lightdm_session_get_key:
254  * @session: A #LightDMSession
255  * 
256  * Get the key for a session
257  * 
258  * Return value: The session key
259  **/
260 const gchar *
261 lightdm_session_get_key (LightDMSession *session)
262 {
263     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
264     return GET_PRIVATE (session)->key;
265 }
266
267 /**
268  * lightdm_session_get_name:
269  * @session: A #LightDMSession
270  * 
271  * Get the name for a session
272  * 
273  * Return value: The session name
274  **/
275 const gchar *
276 lightdm_session_get_name (LightDMSession *session)
277 {
278     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
279     return GET_PRIVATE (session)->name;
280 }
281
282 /**
283  * lightdm_session_get_comment:
284  * @session: A #LightDMSession
285  * 
286  * Get the comment for a session
287  * 
288  * Return value: The session comment
289  **/
290 const gchar *
291 lightdm_session_get_comment (LightDMSession *session)
292 {
293     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
294     return GET_PRIVATE (session)->comment;
295 }
296
297 static void
298 lightdm_session_init (LightDMSession *session)
299 {
300 }
301
302 static void
303 lightdm_session_set_property (GObject      *object,
304                           guint         prop_id,
305                           const GValue *value,
306                           GParamSpec   *pspec)
307 {
308     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
309 }
310
311 static void
312 lightdm_session_get_property (GObject    *object,
313                           guint       prop_id,
314                           GValue     *value,
315                           GParamSpec *pspec)
316 {
317     LightDMSession *self;
318
319     self = LIGHTDM_SESSION (object);
320
321     switch (prop_id) {
322     case PROP_KEY:
323         g_value_set_string (value, lightdm_session_get_key (self));
324         break;
325     case PROP_NAME:
326         g_value_set_string (value, lightdm_session_get_name (self));
327         break;
328     case PROP_COMMENT:
329         g_value_set_string (value, lightdm_session_get_comment (self));
330         break;
331     default:
332         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
333         break;
334     }
335 }
336
337 static void
338 lightdm_session_finalize (GObject *object)
339 {
340     LightDMSession *self = LIGHTDM_SESSION (object);
341     LightDMSessionPrivate *priv = GET_PRIVATE (self);
342
343     g_free (priv->key);
344     g_free (priv->name);
345     g_free (priv->comment);
346 }
347
348 static void
349 lightdm_session_class_init (LightDMSessionClass *klass)
350 {
351     GObjectClass *object_class = G_OBJECT_CLASS (klass);
352   
353     g_type_class_add_private (klass, sizeof (LightDMSessionPrivate));
354
355     object_class->set_property = lightdm_session_set_property;
356     object_class->get_property = lightdm_session_get_property;
357     object_class->finalize = lightdm_session_finalize;
358
359     g_object_class_install_property (object_class,
360                                      PROP_KEY,
361                                      g_param_spec_string ("key",
362                                                           "key",
363                                                           "Session key",
364                                                           NULL,
365                                                           G_PARAM_READABLE));
366     g_object_class_install_property (object_class,
367                                      PROP_NAME,
368                                      g_param_spec_string ("name",
369                                                           "name",
370                                                           "Session name",
371                                                           NULL,
372                                                           G_PARAM_READABLE));
373     g_object_class_install_property (object_class,
374                                      PROP_COMMENT,
375                                      g_param_spec_string ("comment",
376                                                           "comment",
377                                                           "Session comment",
378                                                           NULL,
379                                                           G_PARAM_READABLE));
380 }