]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/session.c
Relicense liblightdm to LGPL-2/LGPL-3 so GPL-2 code can link against it
[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 (const gchar *sessions_dir)
109 {
110     GDir *directory;
111     GList *sessions = NULL;
112     GError *error = NULL;
113
114     directory = g_dir_open (sessions_dir, 0, &error);
115     if (error)
116         g_warning ("Failed to open sessions directory: %s", error->message);
117     g_clear_error (&error);
118     if (!directory)
119         return NULL;
120
121     while (TRUE)
122     {
123         const gchar *filename;
124         gchar *path;
125         GKeyFile *key_file;
126         gboolean result;
127
128         filename = g_dir_read_name (directory);
129         if (filename == NULL)
130             break;
131
132         if (!g_str_has_suffix (filename, ".desktop"))
133             continue;
134
135         path = g_build_filename (sessions_dir, filename, NULL);
136
137         key_file = g_key_file_new ();
138         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
139         if (error)
140             g_warning ("Failed to load session file %s: %s:", path, error->message);
141         g_clear_error (&error);
142
143         if (result)
144         {
145             gchar *key;
146             LightDMSession *session;
147
148             key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
149             session = load_session (key_file, key);
150             if (session)
151             {
152                 g_debug ("Loaded session %s (%s, %s)", path, GET_PRIVATE (session)->name, GET_PRIVATE (session)->comment);
153                 sessions = g_list_insert_sorted (sessions, session, compare_session);
154             }
155             else
156                 g_debug ("Ignoring session %s", path);
157             g_free (key);
158         }
159
160         g_free (path);
161         g_key_file_free (key_file);
162     }
163
164     g_dir_close (directory);
165   
166     return sessions;
167 }
168
169 static void
170 update_sessions (void)
171 {
172     GKeyFile *config_key_file = NULL;
173     gchar *config_path = NULL;
174     gchar *xsessions_dir;
175     gchar *remote_sessions_dir;
176     gboolean result;
177     GError *error = NULL;
178
179     if (have_sessions)
180         return;
181
182     xsessions_dir = g_strdup (XSESSIONS_DIR);
183     remote_sessions_dir = g_strdup (REMOTE_SESSIONS_DIR);
184
185     /* Use session directory from configuration */
186     /* FIXME: This should be sent in the greeter connection */
187     config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL);
188     config_key_file = g_key_file_new ();
189     result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error);
190     if (error)
191         g_warning ("Failed to open configuration file: %s", error->message);
192     g_clear_error (&error);
193     if (result)
194     {
195         gchar *value;
196       
197         value = g_key_file_get_string (config_key_file, "LightDM", "xsessions-directory", NULL);
198         if (value)
199         {
200             g_free (xsessions_dir);
201             xsessions_dir = value;
202         }
203
204         value = g_key_file_get_string (config_key_file, "LightDM", "remote-sessions-directory", NULL);
205         if (value)
206         {
207             g_free (remote_sessions_dir);
208             remote_sessions_dir = value;
209         }
210     }
211     g_key_file_free (config_key_file);
212     g_free (config_path);
213
214     local_sessions = load_sessions (xsessions_dir);
215     remote_sessions = load_sessions (remote_sessions_dir);
216
217     g_free (xsessions_dir);
218     g_free (remote_sessions_dir);
219
220     have_sessions = TRUE;
221 }
222
223 /**
224  * lightdm_get_sessions:
225  *
226  * Get the available sessions.
227  *
228  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
229  **/
230 GList *
231 lightdm_get_sessions (void)
232 {
233     update_sessions ();
234     return local_sessions;
235 }
236
237 /**
238  * lightdm_get_remote_sessions:
239  *
240  * Get the available remote sessions.
241  *
242  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
243  **/
244 GList *
245 lightdm_get_remote_sessions (void)
246 {
247     update_sessions ();
248     return remote_sessions;
249 }
250
251 /**
252  * lightdm_session_get_key:
253  * @session: A #LightDMSession
254  * 
255  * Get the key for a session
256  * 
257  * Return value: The session key
258  **/
259 const gchar *
260 lightdm_session_get_key (LightDMSession *session)
261 {
262     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
263     return GET_PRIVATE (session)->key;
264 }
265
266 /**
267  * lightdm_session_get_name:
268  * @session: A #LightDMSession
269  * 
270  * Get the name for a session
271  * 
272  * Return value: The session name
273  **/
274 const gchar *
275 lightdm_session_get_name (LightDMSession *session)
276 {
277     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
278     return GET_PRIVATE (session)->name;
279 }
280
281 /**
282  * lightdm_session_get_comment:
283  * @session: A #LightDMSession
284  * 
285  * Get the comment for a session
286  * 
287  * Return value: The session comment
288  **/
289 const gchar *
290 lightdm_session_get_comment (LightDMSession *session)
291 {
292     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
293     return GET_PRIVATE (session)->comment;
294 }
295
296 static void
297 lightdm_session_init (LightDMSession *session)
298 {
299 }
300
301 static void
302 lightdm_session_set_property (GObject      *object,
303                           guint         prop_id,
304                           const GValue *value,
305                           GParamSpec   *pspec)
306 {
307     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
308 }
309
310 static void
311 lightdm_session_get_property (GObject    *object,
312                           guint       prop_id,
313                           GValue     *value,
314                           GParamSpec *pspec)
315 {
316     LightDMSession *self;
317
318     self = LIGHTDM_SESSION (object);
319
320     switch (prop_id) {
321     case PROP_KEY:
322         g_value_set_string (value, lightdm_session_get_key (self));
323         break;
324     case PROP_NAME:
325         g_value_set_string (value, lightdm_session_get_name (self));
326         break;
327     case PROP_COMMENT:
328         g_value_set_string (value, lightdm_session_get_comment (self));
329         break;
330     default:
331         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
332         break;
333     }
334 }
335
336 static void
337 lightdm_session_finalize (GObject *object)
338 {
339     LightDMSession *self = LIGHTDM_SESSION (object);
340     LightDMSessionPrivate *priv = GET_PRIVATE (self);
341
342     g_free (priv->key);
343     g_free (priv->name);
344     g_free (priv->comment);
345 }
346
347 static void
348 lightdm_session_class_init (LightDMSessionClass *klass)
349 {
350     GObjectClass *object_class = G_OBJECT_CLASS (klass);
351   
352     g_type_class_add_private (klass, sizeof (LightDMSessionPrivate));
353
354     object_class->set_property = lightdm_session_set_property;
355     object_class->get_property = lightdm_session_get_property;
356     object_class->finalize = lightdm_session_finalize;
357
358     g_object_class_install_property (object_class,
359                                      PROP_KEY,
360                                      g_param_spec_string ("key",
361                                                           "key",
362                                                           "Session key",
363                                                           NULL,
364                                                           G_PARAM_READABLE));
365     g_object_class_install_property (object_class,
366                                      PROP_NAME,
367                                      g_param_spec_string ("name",
368                                                           "name",
369                                                           "Session name",
370                                                           NULL,
371                                                           G_PARAM_READABLE));
372     g_object_class_install_property (object_class,
373                                      PROP_COMMENT,
374                                      g_param_spec_string ("comment",
375                                                           "comment",
376                                                           "Session comment",
377                                                           NULL,
378                                                           G_PARAM_READABLE));
379 }