2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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.
15 #include <security/pam_appl.h>
17 #include "lightdm/greeter.h"
21 PROP_DEFAULT_SESSION_HINT,
23 PROP_SHOW_MANUAL_LOGIN_HINT,
24 PROP_SHOW_REMOTE_LOGIN_HINT,
26 PROP_HAS_GUEST_ACCOUNT_HINT,
27 PROP_SELECT_USER_HINT,
28 PROP_SELECT_GUEST_HINT,
29 PROP_AUTOLOGIN_USER_HINT,
30 PROP_AUTOLOGIN_GUEST_HINT,
31 PROP_AUTOLOGIN_TIMEOUT_HINT,
32 PROP_AUTHENTICATION_USER,
33 PROP_IN_AUTHENTICATION,
34 PROP_IS_AUTHENTICATED,
40 AUTHENTICATION_COMPLETE,
41 AUTOLOGIN_TIMER_EXPIRED,
46 static guint signals[LAST_SIGNAL] = { 0 };
50 /* TRUE if the daemon can reuse this greeter */
53 /* Channel to write to daemon */
54 GIOChannel *to_server_channel;
56 /* Channel to read from daemon */
57 GIOChannel *from_server_channel;
59 /* Data read from the daemon */
63 gsize n_responses_waiting;
64 GList *responses_received;
66 /* TRUE if have got a connect response */
69 /* Pending connect requests */
70 GList *connect_requests;
72 /* Pending start session requests */
73 GList *start_session_requests;
75 /* Pending ensure shared data dir requests */
76 GList *ensure_shared_data_dir_requests;
78 /* Hints provided by the daemon */
81 /* Timeout source to notify greeter to autologin */
82 guint autologin_timeout;
84 gchar *authentication_user;
85 gboolean in_authentication;
86 gboolean is_authenticated;
87 guint32 authenticate_sequence_number;
88 gboolean cancelling_authentication;
89 } LightDMGreeterPrivate;
91 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
93 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
96 #define MAX_MESSAGE_LENGTH 1024
98 /* Messages from the greeter to the server */
101 GREETER_MESSAGE_CONNECT = 0,
102 GREETER_MESSAGE_AUTHENTICATE,
103 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
104 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
105 GREETER_MESSAGE_START_SESSION,
106 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
107 GREETER_MESSAGE_SET_LANGUAGE,
108 GREETER_MESSAGE_AUTHENTICATE_REMOTE,
109 GREETER_MESSAGE_ENSURE_SHARED_DIR,
112 /* Messages from the server to the greeter */
115 SERVER_MESSAGE_CONNECTED = 0,
116 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
117 SERVER_MESSAGE_END_AUTHENTICATION,
118 SERVER_MESSAGE_SESSION_RESULT,
119 SERVER_MESSAGE_SHARED_DIR_RESULT,
121 SERVER_MESSAGE_RESET,
124 /* Request sent to server */
127 GObject parent_instance;
128 GCancellable *cancellable;
129 GAsyncReadyCallback callback;
137 GObjectClass parent_class;
139 GType request_get_type (void);
140 static void request_iface_init (GAsyncResultIface *iface);
141 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
142 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
145 * lightdm_greeter_new:
147 * Create a new greeter.
149 * Return value: the new #LightDMGreeter
152 lightdm_greeter_new (void)
154 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
158 * lightdm_greeter_set_resettable:
159 * @greeter: A #LightDMGreeter
160 * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
162 * Set whether the greeter will be reset instead of killed after the user logs in.
163 * This must be called before lightdm_greeter_connect is called.
166 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
168 LightDMGreeterPrivate *priv;
170 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
172 priv = GET_PRIVATE (greeter);
174 g_return_if_fail (!priv->connected);
175 priv->resettable = resettable;
179 request_new (GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
183 request = g_object_new (request_get_type (), NULL);
185 request->cancellable = g_object_ref (cancellable);
186 request->callback = callback;
187 request->user_data = user_data;
193 request_complete (Request *request, GObject *object)
195 request->complete = TRUE;
197 if (!request->callback)
200 if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
203 request->callback (object, G_ASYNC_RESULT (request), request->user_data);
207 timed_login_cb (gpointer data)
209 LightDMGreeter *greeter = data;
210 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
212 priv->autologin_timeout = 0;
213 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
225 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
227 if (*offset + 4 >= buffer_length)
229 buffer[*offset] = value >> 24;
230 buffer[*offset+1] = (value >> 16) & 0xFF;
231 buffer[*offset+2] = (value >> 8) & 0xFF;
232 buffer[*offset+3] = value & 0xFF;
237 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
242 length = strlen (value);
243 write_int (buffer, buffer_length, length, offset);
244 if (*offset + length >= buffer_length)
246 memcpy (buffer + *offset, value, length);
251 read_int (guint8 *message, gsize message_length, gsize *offset)
256 if (message_length - *offset < int_length ())
258 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
262 buffer = message + *offset;
263 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
264 *offset += int_length ();
270 read_string (guint8 *message, gsize message_length, gsize *offset)
275 length = read_int (message, message_length, offset);
276 if (message_length - *offset < length)
278 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
279 return g_strdup ("");
282 value = g_malloc (sizeof (gchar) * (length + 1));
283 memcpy (value, message + *offset, length);
284 value[length] = '\0';
291 string_length (const gchar *value)
294 return int_length () + strlen (value);
296 return int_length ();
300 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
302 write_int (buffer, buffer_length, id, offset);
303 write_int (buffer, buffer_length, length, offset);
307 get_message_length (guint8 *message, gsize message_length)
310 return read_int (message, message_length, &offset);
314 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
316 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
319 GError *error = NULL;
320 guint32 stated_length;
322 if (!priv->to_server_channel)
325 /* Double check that we're sending well-formed messages. If we say we're
326 sending more than we do, we end up DOS'ing lightdm as it waits for the
327 rest. If we say we're sending less than we do, we confuse the heck out
328 of lightdm, as it starts reading headers from the middle of our
330 stated_length = HEADER_SIZE + get_message_length (message, message_length);
331 if (stated_length != message_length)
333 g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
337 data = (gchar *) message;
338 data_length = message_length;
339 while (data_length > 0)
344 status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &error);
346 g_warning ("Error writing to daemon: %s", error->message);
347 g_clear_error (&error);
348 if (status != G_IO_STATUS_NORMAL)
350 data_length -= n_written;
354 g_debug ("Wrote %zi bytes to daemon", message_length);
355 g_io_channel_flush (priv->to_server_channel, &error);
357 g_warning ("Failed to flush data to daemon: %s", error->message);
358 g_clear_error (&error);
364 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
366 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
368 GString *hint_string;
372 version = read_string (message, message_length, offset);
373 hint_string = g_string_new ("");
374 while (*offset < message_length)
378 name = read_string (message, message_length, offset);
379 value = read_string (message, message_length, offset);
380 g_hash_table_insert (priv->hints, name, value);
381 g_string_append_printf (hint_string, " %s=%s", name, value);
384 priv->connected = TRUE;
385 g_debug ("Connected version=%s%s", version, hint_string->str);
387 g_string_free (hint_string, TRUE);
389 /* Set timeout for default login */
390 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
393 g_debug ("Setting autologin timer for %d seconds", timeout);
394 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
397 /* Notify asynchronous caller */
398 request = g_list_nth_data (priv->connect_requests, 0);
401 request_complete (request, G_OBJECT (greeter));
402 priv->connect_requests = g_list_remove (priv->connect_requests, request);
403 g_object_unref (request);
408 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
410 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
411 guint32 sequence_number, n_messages, i;
414 sequence_number = read_int (message, message_length, offset);
415 if (sequence_number != priv->authenticate_sequence_number)
417 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
421 if (priv->cancelling_authentication)
423 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
427 /* Update username */
428 username = read_string (message, message_length, offset);
429 if (strcmp (username, "") == 0)
434 g_free (priv->authentication_user);
435 priv->authentication_user = username;
437 g_list_free_full (priv->responses_received, g_free);
438 priv->responses_received = NULL;
439 priv->n_responses_waiting = 0;
441 n_messages = read_int (message, message_length, offset);
442 g_debug ("Prompt user with %d message(s)", n_messages);
444 for (i = 0; i < n_messages; i++)
449 style = read_int (message, message_length, offset);
450 text = read_string (message, message_length, offset);
452 // FIXME: Should stop on prompts?
455 case PAM_PROMPT_ECHO_OFF:
456 priv->n_responses_waiting++;
457 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
459 case PAM_PROMPT_ECHO_ON:
460 priv->n_responses_waiting++;
461 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
464 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
467 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
476 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
478 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
479 guint32 sequence_number, return_code;
482 sequence_number = read_int (message, message_length, offset);
484 if (sequence_number != priv->authenticate_sequence_number)
486 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
490 username = read_string (message, message_length, offset);
491 return_code = read_int (message, message_length, offset);
493 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
495 /* Update username */
496 if (strcmp (username, "") == 0)
501 g_free (priv->authentication_user);
502 priv->authentication_user = username;
504 priv->cancelling_authentication = FALSE;
505 priv->is_authenticated = (return_code == 0);
507 priv->in_authentication = FALSE;
508 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
512 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
514 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
518 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
520 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
521 GString *hint_string;
523 g_hash_table_remove_all (priv->hints);
525 hint_string = g_string_new ("");
526 while (*offset < message_length)
530 name = read_string (message, message_length, offset);
531 value = read_string (message, message_length, offset);
532 g_hash_table_insert (priv->hints, name, value);
533 g_string_append_printf (hint_string, " %s=%s", name, value);
536 g_debug ("Reset%s", hint_string->str);
537 g_string_free (hint_string, TRUE);
539 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
543 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
545 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
548 /* Notify asynchronous caller */
549 request = g_list_nth_data (priv->start_session_requests, 0);
552 request->return_code = read_int (message, message_length, offset);
553 request_complete (request, G_OBJECT (greeter));
554 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
555 g_object_unref (request);
560 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
562 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
565 /* Notify asynchronous caller */
566 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
569 request->dir = read_string (message, message_length, offset);
570 /* Blank data dir means invalid user */
571 if (g_strcmp0 (request->dir, "") == 0)
573 g_free (request->dir);
576 request_complete (request, G_OBJECT (greeter));
577 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
578 g_object_unref (request);
583 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
588 id = read_int (message, message_length, &offset);
589 read_int (message, message_length, &offset);
592 case SERVER_MESSAGE_CONNECTED:
593 handle_connected (greeter, message, message_length, &offset);
595 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
596 handle_prompt_authentication (greeter, message, message_length, &offset);
598 case SERVER_MESSAGE_END_AUTHENTICATION:
599 handle_end_authentication (greeter, message, message_length, &offset);
601 case SERVER_MESSAGE_SESSION_RESULT:
602 handle_session_result (greeter, message, message_length, &offset);
604 case SERVER_MESSAGE_SHARED_DIR_RESULT:
605 handle_shared_dir_result (greeter, message, message_length, &offset);
607 case SERVER_MESSAGE_IDLE:
608 handle_idle (greeter, message, message_length, &offset);
610 case SERVER_MESSAGE_RESET:
611 handle_reset (greeter, message, message_length, &offset);
614 g_warning ("Unknown message from server: %d", id);
620 recv_message (LightDMGreeter *greeter, gsize *length, gboolean block)
622 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
623 gsize n_to_read, n_read;
625 GError *error = NULL;
627 if (!priv->from_server_channel)
630 /* Read the header, or the whole message if we already have that */
631 n_to_read = HEADER_SIZE;
632 if (priv->n_read >= HEADER_SIZE)
633 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
638 status = g_io_channel_read_chars (priv->from_server_channel,
639 (gchar *) priv->read_buffer + priv->n_read,
640 n_to_read - priv->n_read,
644 g_warning ("Error reading from server: %s", error->message);
645 g_clear_error (&error);
646 if (status != G_IO_STATUS_NORMAL)
649 g_debug ("Read %zi bytes from daemon", n_read);
651 priv->n_read += n_read;
652 } while (priv->n_read < n_to_read && block);
654 /* Stop if haven't got all the data we want */
655 if (priv->n_read != n_to_read)
658 /* If have header, rerun for content */
659 if (priv->n_read == HEADER_SIZE)
661 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
664 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
665 return recv_message (greeter, length, block);
669 buffer = priv->read_buffer;
670 *length = priv->n_read;
672 priv->read_buffer = g_malloc (priv->n_read);
679 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
681 LightDMGreeter *greeter = data;
683 gsize message_length;
685 /* Read one message and process it */
686 message = recv_message (greeter, &message_length, FALSE);
689 handle_message (greeter, message, message_length);
697 send_connect (LightDMGreeter *greeter, gboolean resettable)
699 guint8 message[MAX_MESSAGE_LENGTH];
702 g_debug ("Connecting to display manager...");
703 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
704 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
705 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset);
707 return send_message (greeter, message, offset);
711 send_start_session (LightDMGreeter *greeter, const gchar *session)
713 guint8 message[MAX_MESSAGE_LENGTH];
717 g_debug ("Starting session %s", session);
719 g_debug ("Starting default session");
721 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
722 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
723 return send_message (greeter, message, offset);
727 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
729 guint8 message[MAX_MESSAGE_LENGTH];
732 g_debug ("Ensuring data directory for user %s", username);
734 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset);
735 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
736 return send_message (greeter, message, offset);
740 * lightdm_greeter_connect_to_daemon:
741 * @greeter: The greeter to connect
742 * @cancellable: (allow-none): A #GCancellable or %NULL.
743 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
744 * @user_data: (allow-none): data to pass to the @callback or %NULL.
746 * Asynchronously connects the greeter to the display manager.
748 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_to_daemon_finish() to get the result of the operation.
750 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
753 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
755 LightDMGreeterPrivate *priv;
758 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
760 priv = GET_PRIVATE (greeter);
762 request = request_new (cancellable, callback, user_data);
763 priv->connect_requests = g_list_append (priv->connect_requests, request);
764 send_connect (greeter, priv->resettable);
768 * lightdm_greeter_connect_to_daemon_finish:
769 * @result: A #GAsyncResult.
770 * @error: return location for a #GError, or %NULL
772 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
774 * Return value: #TRUE if successfully connected
777 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
779 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
780 return REQUEST (result)->complete;
784 * lightdm_greeter_connect_to_daemon_sync:
785 * @greeter: The greeter to connect
786 * @error: return location for a #GError, or %NULL
788 * Connects the greeter to the display manager. Will block until connected.
790 * Return value: #TRUE if successfully connected
793 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
795 LightDMGreeterPrivate *priv;
798 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
800 priv = GET_PRIVATE (greeter);
802 /* Read until we are connected */
803 send_connect (greeter, priv->resettable);
804 request = request_new (NULL, NULL, NULL);
805 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
809 gsize message_length;
811 message = recv_message (greeter, &message_length, TRUE);
814 handle_message (greeter, message, message_length);
816 } while (!request->complete);
818 g_object_unref (request);
820 return request->complete;
824 * lightdm_greeter_connect_sync:
825 * @greeter: The greeter to connect
826 * @error: return location for a #GError, or %NULL
828 * Connects the greeter to the display manager. Will block until connected.
830 * Return value: #TRUE if successfully connected
832 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
835 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
837 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
841 * lightdm_greeter_get_hint:
842 * @greeter: A #LightDMGreeter
843 * @name: The hint name to query.
847 * Return value: The value for this hint or #NULL if not set.
850 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
852 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
853 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
857 * lightdm_greeter_get_default_session_hint:
858 * @greeter: A #LightDMGreeter
860 * Get the default session to use.
862 * Return value: The session name
865 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
867 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
868 return lightdm_greeter_get_hint (greeter, "default-session");
872 * lightdm_greeter_get_hide_users_hint:
873 * @greeter: A #LightDMGreeter
875 * Check if user accounts should be shown. If this is TRUE then the list of
876 * accounts should be taken from #LightDMUserList and displayed in the greeter
877 * for the user to choose from. Note that this list can be empty and it is
878 * recommended you show a method for the user to enter a username manually.
880 * If this option is shown the greeter should only allow these users to be
881 * chosen for login unless the manual login hint is set.
883 * Return value: #TRUE if the available users should not be shown.
886 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
890 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
891 value = lightdm_greeter_get_hint (greeter, "hide-users");
893 return g_strcmp0 (value, "true") == 0;
897 * lightdm_greeter_get_show_manual_login_hint:
898 * @greeter: A #LightDMGreeter
900 * Check if a manual login option should be shown. If set the GUI
901 * should provide a way for a username to be entered manually.
902 * Without this hint a greeter which is showing a user list can
903 * limit logins to only those users.
905 * Return value: #TRUE if a manual login option should be shown.
908 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
912 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
913 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
915 return g_strcmp0 (value, "true") == 0;
919 * lightdm_greeter_get_show_remote_login_hint:
920 * @greeter: A #LightDMGreeter
922 * Check if a remote login option should be shown. If set the GUI
923 * should provide a way for a user to log into a remote desktop server.
925 * Return value: #TRUE if a remote login option should be shown.
928 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
932 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
933 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
935 return g_strcmp0 (value, "true") == 0;
939 * lightdm_greeter_get_lock_hint:
940 * @greeter: A #LightDMGreeter
942 * Check if the greeter is acting as a lock screen.
944 * Return value: #TRUE if the greeter was triggered by locking the seat.
947 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
951 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
952 value = lightdm_greeter_get_hint (greeter, "lock-screen");
954 return g_strcmp0 (value, "true") == 0;
958 * lightdm_greeter_get_has_guest_account_hint:
959 * @greeter: A #LightDMGreeter
961 * Check if guest sessions are supported.
963 * Return value: #TRUE if guest sessions are supported.
966 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
970 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
971 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
973 return g_strcmp0 (value, "true") == 0;
977 * lightdm_greeter_get_select_user_hint:
978 * @greeter: A #LightDMGreeter
980 * Get the user to select by default.
982 * Return value: A username
985 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
987 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
988 return lightdm_greeter_get_hint (greeter, "select-user");
992 * lightdm_greeter_get_select_guest_hint:
993 * @greeter: A #LightDMGreeter
995 * Check if the guest account should be selected by default.
997 * Return value: #TRUE if the guest account should be selected by default.
1000 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1004 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1005 value = lightdm_greeter_get_hint (greeter, "select-guest");
1007 return g_strcmp0 (value, "true") == 0;
1011 * lightdm_greeter_get_autologin_user_hint:
1012 * @greeter: A #LightDMGreeter
1014 * Get the user account to automatically logg into when the timer expires.
1016 * Return value: The user account to automatically log into.
1019 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1021 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1022 return lightdm_greeter_get_hint (greeter, "autologin-user");
1026 * lightdm_greeter_get_autologin_guest_hint:
1027 * @greeter: A #LightDMGreeter
1029 * Check if the guest account should be automatically logged into when the timer expires.
1031 * Return value: #TRUE if the guest account should be automatically logged into.
1034 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1038 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1039 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1041 return g_strcmp0 (value, "true") == 0;
1045 * lightdm_greeter_get_autologin_timeout_hint:
1046 * @greeter: A #LightDMGreeter
1048 * Get the number of seconds to wait before automaitcally logging in.
1050 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1053 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1058 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1059 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1061 timeout = atoi (value);
1069 * lightdm_greeter_cancel_autologin:
1070 * @greeter: A #LightDMGreeter
1072 * Cancel the automatic login.
1075 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1077 LightDMGreeterPrivate *priv;
1079 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1081 priv = GET_PRIVATE (greeter);
1083 if (priv->autologin_timeout)
1084 g_source_remove (priv->autologin_timeout);
1085 priv->autologin_timeout = 0;
1089 * lightdm_greeter_authenticate:
1090 * @greeter: A #LightDMGreeter
1091 * @username: (allow-none): A username or #NULL to prompt for a username.
1093 * Starts the authentication procedure for a user.
1096 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
1098 LightDMGreeterPrivate *priv;
1099 guint8 message[MAX_MESSAGE_LENGTH];
1102 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1104 priv = GET_PRIVATE (greeter);
1106 g_return_if_fail (priv->connected);
1108 priv->cancelling_authentication = FALSE;
1109 priv->authenticate_sequence_number++;
1110 priv->in_authentication = TRUE;
1111 priv->is_authenticated = FALSE;
1112 if (username != priv->authentication_user)
1114 g_free (priv->authentication_user);
1115 priv->authentication_user = g_strdup (username);
1118 g_debug ("Starting authentication for user %s...", username);
1119 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
1120 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1121 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1122 send_message (greeter, message, offset);
1126 * lightdm_greeter_authenticate_as_guest:
1127 * @greeter: A #LightDMGreeter
1129 * Starts the authentication procedure for the guest user.
1132 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
1134 LightDMGreeterPrivate *priv;
1135 guint8 message[MAX_MESSAGE_LENGTH];
1138 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1140 priv = GET_PRIVATE (greeter);
1142 g_return_if_fail (priv->connected);
1144 priv->cancelling_authentication = FALSE;
1145 priv->authenticate_sequence_number++;
1146 priv->in_authentication = TRUE;
1147 priv->is_authenticated = FALSE;
1148 g_free (priv->authentication_user);
1149 priv->authentication_user = NULL;
1151 g_debug ("Starting authentication for guest account...");
1152 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
1153 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1154 send_message (greeter, message, offset);
1158 * lightdm_greeter_authenticate_autologin:
1159 * @greeter: A #LightDMGreeter
1161 * Starts the authentication procedure for the automatic login user.
1164 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
1168 user = lightdm_greeter_get_autologin_user_hint (greeter);
1169 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1170 lightdm_greeter_authenticate_as_guest (greeter);
1172 lightdm_greeter_authenticate (greeter, user);
1176 * lightdm_greeter_authenticate_remote:
1177 * @greeter: A #LightDMGreeter
1178 * @session: The name of a remote session
1179 * @username: (allow-none): A username of #NULL to prompt for a username.
1181 * Start authentication for a remote session type.
1184 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
1186 LightDMGreeterPrivate *priv;
1187 guint8 message[MAX_MESSAGE_LENGTH];
1190 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1192 priv = GET_PRIVATE (greeter);
1194 g_return_if_fail (priv->connected);
1196 priv->cancelling_authentication = FALSE;
1197 priv->authenticate_sequence_number++;
1198 priv->in_authentication = TRUE;
1199 priv->is_authenticated = FALSE;
1200 g_free (priv->authentication_user);
1201 priv->authentication_user = NULL;
1204 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1206 g_debug ("Starting authentication for remote session %s...", session);
1207 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
1208 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1209 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1210 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1211 send_message (greeter, message, offset);
1215 * lightdm_greeter_respond:
1216 * @greeter: A #LightDMGreeter
1217 * @response: Response to a prompt
1219 * Provide response to a prompt. May be one in a series.
1222 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
1224 LightDMGreeterPrivate *priv;
1225 guint8 message[MAX_MESSAGE_LENGTH];
1228 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1229 g_return_if_fail (response != NULL);
1231 priv = GET_PRIVATE (greeter);
1233 g_return_if_fail (priv->connected);
1234 g_return_if_fail (priv->n_responses_waiting > 0);
1236 priv->n_responses_waiting--;
1237 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1239 if (priv->n_responses_waiting == 0)
1244 g_debug ("Providing response to display manager");
1246 msg_length = int_length ();
1247 for (iter = priv->responses_received; iter; iter = iter->next)
1248 msg_length += string_length ((gchar *)iter->data);
1250 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
1251 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
1252 for (iter = priv->responses_received; iter; iter = iter->next)
1253 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
1254 send_message (greeter, message, offset);
1256 g_list_free_full (priv->responses_received, g_free);
1257 priv->responses_received = NULL;
1262 * lightdm_greeter_cancel_authentication:
1263 * @greeter: A #LightDMGreeter
1265 * Cancel the current user authentication.
1268 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
1270 LightDMGreeterPrivate *priv;
1271 guint8 message[MAX_MESSAGE_LENGTH];
1274 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1276 priv = GET_PRIVATE (greeter);
1278 g_return_if_fail (priv->connected);
1280 priv->cancelling_authentication = TRUE;
1281 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1282 send_message (greeter, message, offset);
1286 * lightdm_greeter_get_in_authentication:
1287 * @greeter: A #LightDMGreeter
1289 * Checks if the greeter is in the process of authenticating.
1291 * Return value: #TRUE if the greeter is authenticating a user.
1294 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1296 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1297 return GET_PRIVATE (greeter)->in_authentication;
1301 * lightdm_greeter_get_is_authenticated:
1302 * @greeter: A #LightDMGreeter
1304 * Checks if the greeter has successfully authenticated.
1306 * Return value: #TRUE if the greeter is authenticated for login.
1309 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1311 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1312 return GET_PRIVATE (greeter)->is_authenticated;
1316 * lightdm_greeter_get_authentication_user:
1317 * @greeter: A #LightDMGreeter
1319 * Get the user that is being authenticated.
1321 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1324 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1326 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1327 return GET_PRIVATE (greeter)->authentication_user;
1331 * lightdm_greeter_set_language:
1332 * @greeter: A #LightDMGreeter
1333 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1335 * Set the language for the currently authenticated user.
1338 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1340 LightDMGreeterPrivate *priv;
1341 guint8 message[MAX_MESSAGE_LENGTH];
1344 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1346 priv = GET_PRIVATE (greeter);
1348 g_return_if_fail (priv->connected);
1350 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1351 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1352 send_message (greeter, message, offset);
1356 * lightdm_greeter_start_session:
1357 * @greeter: A #LightDMGreeter
1358 * @session: (allow-none): The session to log into or #NULL to use the default.
1359 * @cancellable: (allow-none): A #GCancellable or %NULL.
1360 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1361 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1363 * Asynchronously start a session for the authenticated user.
1365 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_start_session_finish() to get the result of the operation.
1367 * See lightdm_greeter_start_session_sync() for the synchronous version.
1370 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1372 LightDMGreeterPrivate *priv;
1375 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1377 priv = GET_PRIVATE (greeter);
1379 send_start_session (greeter, session);
1380 request = request_new (cancellable, callback, user_data);
1381 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1385 * lightdm_greeter_start_session_finish:
1386 * @greeter: A #LightDMGreeter
1387 * @result: A #GAsyncResult.
1388 * @error: return location for a #GError, or %NULL
1390 * Start a session for the authenticated user.
1392 * Return value: TRUE if the session was started.
1395 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1397 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1398 return REQUEST (result)->return_code == 0;
1402 * lightdm_greeter_start_session_sync:
1403 * @greeter: A #LightDMGreeter
1404 * @session: (allow-none): The session to log into or #NULL to use the default.
1405 * @error: return location for a #GError, or %NULL
1407 * Start a session for the authenticated user.
1409 * Return value: TRUE if the session was started.
1412 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1414 LightDMGreeterPrivate *priv;
1416 guint32 return_code;
1418 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1420 priv = GET_PRIVATE (greeter);
1422 g_return_val_if_fail (priv->connected, FALSE);
1423 g_return_val_if_fail (priv->is_authenticated, FALSE);
1425 /* Read until the session is started */
1426 send_start_session (greeter, session);
1427 request = request_new (NULL, NULL, NULL);
1428 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1432 gsize message_length;
1434 message = recv_message (greeter, &message_length, TRUE);
1437 handle_message (greeter, message, message_length);
1439 } while (!request->complete);
1441 return_code = request->return_code;
1442 g_object_unref (request);
1444 return return_code == 0;
1448 * lightdm_greeter_ensure_shared_data_dir:
1449 * @greeter: A #LightDMGreeter
1450 * @username: A username
1451 * @cancellable: (allow-none): A #GCancellable or %NULL.
1452 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1453 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1455 * Ensure that a shared data dir for the given user is available. Both the
1456 * greeter user and @username will have write access to that folder. The
1457 * intention is that larger pieces of shared data would be stored there (files
1458 * that the greeter creates but wants to give to a user -- like camera
1459 * photos -- or files that the user creates but wants the greeter to
1460 * see -- like contact avatars).
1462 * LightDM will automatically create these if the user actually logs in, so
1463 * greeters only need to call this method if they want to store something in
1464 * the directory themselves.
1467 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1469 LightDMGreeterPrivate *priv;
1472 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1474 priv = GET_PRIVATE (greeter);
1476 send_ensure_shared_data_dir (greeter, username);
1477 request = request_new (cancellable, callback, user_data);
1478 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1482 * lightdm_greeter_ensure_shared_data_dir_finish:
1483 * @result: A #GAsyncResult.
1484 * @greeter: A #LightDMGreeter
1487 * Return value: The path to the shared directory, free with g_free.
1490 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result)
1492 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1493 return g_strdup (REQUEST (result)->dir);
1497 * lightdm_greeter_ensure_shared_data_dir_sync:
1498 * @greeter: A #LightDMGreeter
1499 * @username: A username
1501 * Ensure that a shared data dir for the given user is available. Both the
1502 * greeter user and @username will have write access to that folder. The
1503 * intention is that larger pieces of shared data would be stored there (files
1504 * that the greeter creates but wants to give to a user -- like camera
1505 * photos -- or files that the user creates but wants the greeter to
1506 * see -- like contact avatars).
1508 * LightDM will automatically create these if the user actually logs in, so
1509 * greeters only need to call this method if they want to store something in
1510 * the directory themselves.
1512 * Return value: The path to the shared directory, free with g_free.
1515 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username)
1517 LightDMGreeterPrivate *priv;
1521 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1523 priv = GET_PRIVATE (greeter);
1525 g_return_val_if_fail (priv->connected, NULL);
1527 /* Read until a response */
1528 send_ensure_shared_data_dir (greeter, username);
1529 request = request_new (NULL, NULL, NULL);
1530 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1534 gsize message_length;
1536 message = recv_message (greeter, &message_length, TRUE);
1539 handle_message (greeter, message, message_length);
1541 } while (!request->complete);
1543 data_dir = g_strdup (request->dir);
1544 g_object_unref (request);
1550 lightdm_greeter_init (LightDMGreeter *greeter)
1552 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1555 priv->read_buffer = g_malloc (HEADER_SIZE);
1556 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1558 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
1561 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
1562 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
1565 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
1567 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
1570 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
1571 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
1572 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
1575 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
1579 lightdm_greeter_set_property (GObject *object,
1581 const GValue *value,
1584 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1588 lightdm_greeter_get_property (GObject *object,
1593 LightDMGreeter *self;
1595 self = LIGHTDM_GREETER (object);
1598 case PROP_DEFAULT_SESSION_HINT:
1599 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1601 case PROP_HIDE_USERS_HINT:
1602 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1604 case PROP_SHOW_MANUAL_LOGIN_HINT:
1605 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1607 case PROP_SHOW_REMOTE_LOGIN_HINT:
1608 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1610 case PROP_LOCK_HINT:
1611 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1613 case PROP_HAS_GUEST_ACCOUNT_HINT:
1614 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1616 case PROP_SELECT_USER_HINT:
1617 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1619 case PROP_SELECT_GUEST_HINT:
1620 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1622 case PROP_AUTOLOGIN_USER_HINT:
1623 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1625 case PROP_AUTOLOGIN_GUEST_HINT:
1626 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1628 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1629 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1631 case PROP_AUTHENTICATION_USER:
1632 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1634 case PROP_IN_AUTHENTICATION:
1635 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1637 case PROP_IS_AUTHENTICATED:
1638 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1641 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1647 lightdm_greeter_finalize (GObject *object)
1649 LightDMGreeter *self = LIGHTDM_GREETER (object);
1650 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1652 if (priv->to_server_channel)
1653 g_io_channel_unref (priv->to_server_channel);
1654 if (priv->from_server_channel)
1655 g_io_channel_unref (priv->from_server_channel);
1656 g_free (priv->authentication_user);
1657 g_hash_table_unref (priv->hints);
1659 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1663 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1665 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1667 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1669 object_class->set_property = lightdm_greeter_set_property;
1670 object_class->get_property = lightdm_greeter_get_property;
1671 object_class->finalize = lightdm_greeter_finalize;
1673 g_object_class_install_property (object_class,
1674 PROP_DEFAULT_SESSION_HINT,
1675 g_param_spec_string ("default-session-hint",
1676 "default-session-hint",
1677 "Default session hint",
1679 G_PARAM_READWRITE));
1681 g_object_class_install_property (object_class,
1682 PROP_HIDE_USERS_HINT,
1683 g_param_spec_boolean ("hide-users-hint",
1689 g_object_class_install_property (object_class,
1690 PROP_SHOW_MANUAL_LOGIN_HINT,
1691 g_param_spec_boolean ("show-manual-login-hint",
1692 "show-manual-login-hint",
1693 "Show manual login hint",
1697 g_object_class_install_property (object_class,
1698 PROP_SHOW_REMOTE_LOGIN_HINT,
1699 g_param_spec_boolean ("show-remote-login-hint",
1700 "show-remote-login-hint",
1701 "Show remote login hint",
1705 g_object_class_install_property (object_class,
1707 g_param_spec_boolean ("lock-hint",
1713 g_object_class_install_property (object_class,
1714 PROP_HAS_GUEST_ACCOUNT_HINT,
1715 g_param_spec_boolean ("has-guest-account-hint",
1716 "has-guest-account-hint",
1717 "Has guest account hint",
1721 g_object_class_install_property (object_class,
1722 PROP_SELECT_USER_HINT,
1723 g_param_spec_string ("select-user-hint",
1729 g_object_class_install_property (object_class,
1730 PROP_SELECT_GUEST_HINT,
1731 g_param_spec_boolean ("select-guest-hint",
1732 "select-guest-hint",
1733 "Select guest account hint",
1737 g_object_class_install_property (object_class,
1738 PROP_AUTOLOGIN_USER_HINT,
1739 g_param_spec_string ("autologin-user-hint",
1740 "autologin-user-hint",
1741 "Autologin user hint",
1745 g_object_class_install_property (object_class,
1746 PROP_AUTOLOGIN_GUEST_HINT,
1747 g_param_spec_boolean ("autologin-guest-hint",
1748 "autologin-guest-hint",
1749 "Autologin guest account hint",
1753 g_object_class_install_property (object_class,
1754 PROP_AUTOLOGIN_TIMEOUT_HINT,
1755 g_param_spec_int ("autologin-timeout-hint",
1756 "autologin-timeout-hint",
1757 "Autologin timeout hint",
1761 g_object_class_install_property (object_class,
1762 PROP_AUTHENTICATION_USER,
1763 g_param_spec_string ("authentication-user",
1764 "authentication-user",
1765 "The user being authenticated",
1768 g_object_class_install_property (object_class,
1769 PROP_IN_AUTHENTICATION,
1770 g_param_spec_boolean ("in-authentication",
1771 "in-authentication",
1772 "TRUE if a user is being authenticated",
1775 g_object_class_install_property (object_class,
1776 PROP_IS_AUTHENTICATED,
1777 g_param_spec_boolean ("is-authenticated",
1779 "TRUE if the selected user is authenticated",
1784 * LightDMGreeter::show-prompt:
1785 * @greeter: A #LightDMGreeter
1786 * @text: Prompt text
1787 * @type: Prompt type
1789 * The ::show-prompt signal gets emitted when the greeter should show a
1790 * prompt to the user. The given text should be displayed and an input
1791 * field for the user to provide a response.
1793 * Call lightdm_greeter_respond() with the resultant input or
1794 * lightdm_greeter_cancel_authentication() to abort the authentication.
1796 signals[SHOW_PROMPT] =
1797 g_signal_new ("show-prompt",
1798 G_TYPE_FROM_CLASS (klass),
1800 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1803 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1806 * LightDMGreeter::show-message:
1807 * @greeter: A #LightDMGreeter
1808 * @text: Message text
1809 * @type: Message type
1811 * The ::show-message signal gets emitted when the greeter
1812 * should show a message to the user.
1814 signals[SHOW_MESSAGE] =
1815 g_signal_new ("show-message",
1816 G_TYPE_FROM_CLASS (klass),
1818 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1821 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1824 * LightDMGreeter::authentication-complete:
1825 * @greeter: A #LightDMGreeter
1827 * The ::authentication-complete signal gets emitted when the greeter
1828 * has completed authentication.
1830 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1833 signals[AUTHENTICATION_COMPLETE] =
1834 g_signal_new ("authentication-complete",
1835 G_TYPE_FROM_CLASS (klass),
1837 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1843 * LightDMGreeter::autologin-timer-expired:
1844 * @greeter: A #LightDMGreeter
1846 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1847 * The application should then call lightdm_greeter_login().
1849 signals[AUTOLOGIN_TIMER_EXPIRED] =
1850 g_signal_new ("autologin-timer-expired",
1851 G_TYPE_FROM_CLASS (klass),
1853 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1859 * LightDMGreeter::idle:
1860 * @greeter: A #LightDMGreeter
1862 * The ::idle signal gets emitted when the user has logged in and the
1863 * greeter is no longer needed.
1865 * This signal only matters if the greeter has marked itself as
1866 * resettable using lightdm_greeter_set_resettable().
1869 g_signal_new ("idle",
1870 G_TYPE_FROM_CLASS (klass),
1872 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
1878 * LightDMGreeter::reset:
1879 * @greeter: A #LightDMGreeter
1881 * The ::reset signal gets emitted when the user is returning to a greeter
1882 * that was previously marked idle.
1884 * This signal only matters if the greeter has marked itself as
1885 * resettable using lightdm_greeter_set_resettable().
1888 g_signal_new ("reset",
1889 G_TYPE_FROM_CLASS (klass),
1891 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
1898 request_init (Request *request)
1903 request_finalize (GObject *object)
1905 Request *request = REQUEST (object);
1907 g_free (request->dir);
1908 if (request->cancellable)
1909 g_object_unref (request->cancellable);
1911 G_OBJECT_CLASS (request_parent_class)->finalize (object);
1915 request_class_init (RequestClass *klass)
1917 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1918 object_class->finalize = request_finalize;
1922 request_get_user_data (GAsyncResult *result)
1924 return REQUEST (result)->user_data;
1928 request_get_source_object (GAsyncResult *res)
1934 request_iface_init (GAsyncResultIface *iface)
1936 iface->get_user_data = request_get_user_data;
1937 iface->get_source_object = request_get_source_object;