]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/session.c
fix some memory leaks
[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 *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     sessions = g_list_insert_sorted (sessions, session, compare_session);
103
104     g_free (domain);
105
106     return session;
107 }
108
109 static void
110 update_sessions (void)
111 {
112     GDir *directory;
113     GError *error = NULL;
114
115     if (have_sessions)
116         return;
117
118     directory = g_dir_open (XSESSIONS_DIR, 0, &error);
119     if (error)
120         g_warning ("Failed to open sessions directory: %s", error->message);
121     g_clear_error (&error);
122     if (!directory)
123         return;
124
125     while (TRUE)
126     {
127         const gchar *filename;
128         gchar *path;
129         GKeyFile *key_file;
130         gboolean result;
131
132         filename = g_dir_read_name (directory);
133         if (filename == NULL)
134             break;
135
136         if (!g_str_has_suffix (filename, ".desktop"))
137             continue;
138
139         path = g_build_filename (XSESSIONS_DIR, filename, NULL);
140
141         key_file = g_key_file_new ();
142         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
143         if (error)
144             g_warning ("Failed to load session file %s: %s:", path, error->message);
145         g_clear_error (&error);
146
147         if (result)
148         {
149             gchar *key;
150             LightDMSession *session;
151
152             key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
153             session = load_session (key_file, key);
154             if (session)
155                 g_debug ("Loaded session %s (%s, %s)", path, GET_PRIVATE (session)->name, GET_PRIVATE (session)->comment);
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     have_sessions = TRUE;
168 }
169
170 /**
171  * lightdm_get_sessions:
172  *
173  * Get the available sessions.
174  *
175  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
176  **/
177 GList *
178 lightdm_get_sessions (void)
179 {
180     update_sessions ();
181     return sessions;
182 }
183
184 /**
185  * lightdm_session_get_key
186  * @session: A #LightDMSession
187  * 
188  * Get the key for a session
189  * 
190  * Return value: The session key
191  **/
192 const gchar *
193 lightdm_session_get_key (LightDMSession *session)
194 {
195     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
196     return GET_PRIVATE (session)->key;
197 }
198
199 /**
200  * lightdm_session_get_name
201  * @session: A #LightDMSession
202  * 
203  * Get the name for a session
204  * 
205  * Return value: The session name
206  **/
207 const gchar *
208 lightdm_session_get_name (LightDMSession *session)
209 {
210     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
211     return GET_PRIVATE (session)->name;
212 }
213
214 /**
215  * lightdm_session_get_comment
216  * @session: A #LightDMSession
217  * 
218  * Get the comment for a session
219  * 
220  * Return value: The session comment
221  **/
222 const gchar *
223 lightdm_session_get_comment (LightDMSession *session)
224 {
225     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
226     return GET_PRIVATE (session)->comment;
227 }
228
229 static void
230 lightdm_session_init (LightDMSession *session)
231 {
232 }
233
234 static void
235 lightdm_session_set_property (GObject      *object,
236                           guint         prop_id,
237                           const GValue *value,
238                           GParamSpec   *pspec)
239 {
240     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
241 }
242
243 static void
244 lightdm_session_get_property (GObject    *object,
245                           guint       prop_id,
246                           GValue     *value,
247                           GParamSpec *pspec)
248 {
249     LightDMSession *self;
250
251     self = LIGHTDM_SESSION (object);
252
253     switch (prop_id) {
254     case PROP_KEY:
255         g_value_set_string (value, lightdm_session_get_key (self));
256         break;
257     case PROP_NAME:
258         g_value_set_string (value, lightdm_session_get_name (self));
259         break;
260     case PROP_COMMENT:
261         g_value_set_string (value, lightdm_session_get_comment (self));
262         break;
263     default:
264         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
265         break;
266     }
267 }
268
269 static void
270 lightdm_session_finalize (GObject *object)
271 {
272     LightDMSession *self = LIGHTDM_SESSION (object);
273     LightDMSessionPrivate *priv = GET_PRIVATE (self);
274
275     g_free (priv->key);
276     g_free (priv->name);
277     g_free (priv->comment);
278 }
279
280 static void
281 lightdm_session_class_init (LightDMSessionClass *klass)
282 {
283     GObjectClass *object_class = G_OBJECT_CLASS (klass);
284   
285     g_type_class_add_private (klass, sizeof (LightDMSessionPrivate));
286
287     object_class->set_property = lightdm_session_set_property;
288     object_class->get_property = lightdm_session_get_property;
289     object_class->finalize = lightdm_session_finalize;
290
291     g_object_class_install_property (object_class,
292                                      PROP_KEY,
293                                      g_param_spec_string ("key",
294                                                           "key",
295                                                           "Session key",
296                                                           NULL,
297                                                           G_PARAM_READABLE));
298     g_object_class_install_property (object_class,
299                                      PROP_NAME,
300                                      g_param_spec_string ("name",
301                                                           "name",
302                                                           "Session name",
303                                                           NULL,
304                                                           G_PARAM_READABLE));
305     g_object_class_install_property (object_class,
306                                      PROP_COMMENT,
307                                      g_param_spec_string ("comment",
308                                                           "comment",
309                                                           "Session comment",
310                                                           NULL,
311                                                           G_PARAM_READABLE));
312 }