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