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