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);
318 GError *error = NULL;
319 guint32 stated_length;
321 if (!priv->to_server_channel)
324 /* Double check that we're sending well-formed messages. If we say we're
325 sending more than we do, we end up DOS'ing lightdm as it waits for the
326 rest. If we say we're sending less than we do, we confuse the heck out
327 of lightdm, as it starts reading headers from the middle of our
329 stated_length = HEADER_SIZE + get_message_length (message, message_length);
330 if (stated_length != message_length)
332 g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
336 status = g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, &error);
338 g_warning ("Error writing to daemon: %s", error->message);
339 g_clear_error (&error);
340 if (status != G_IO_STATUS_NORMAL)
343 g_debug ("Wrote %zi bytes to daemon", message_length);
344 g_io_channel_flush (priv->to_server_channel, NULL);
350 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
352 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
354 GString *hint_string;
358 version = read_string (message, message_length, offset);
359 hint_string = g_string_new ("");
360 while (*offset < message_length)
364 name = read_string (message, message_length, offset);
365 value = read_string (message, message_length, offset);
366 g_hash_table_insert (priv->hints, name, value);
367 g_string_append_printf (hint_string, " %s=%s", name, value);
370 priv->connected = TRUE;
371 g_debug ("Connected version=%s%s", version, hint_string->str);
373 g_string_free (hint_string, TRUE);
375 /* Set timeout for default login */
376 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
379 g_debug ("Setting autologin timer for %d seconds", timeout);
380 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
383 /* Notify asynchronous caller */
384 request = g_list_nth_data (priv->connect_requests, 0);
387 request_complete (request, G_OBJECT (greeter));
388 priv->connect_requests = g_list_remove (priv->connect_requests, request);
389 g_object_unref (request);
394 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
396 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
397 guint32 sequence_number, n_messages, i;
400 sequence_number = read_int (message, message_length, offset);
401 if (sequence_number != priv->authenticate_sequence_number)
403 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
407 if (priv->cancelling_authentication)
409 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
413 /* Update username */
414 username = read_string (message, message_length, offset);
415 if (strcmp (username, "") == 0)
420 g_free (priv->authentication_user);
421 priv->authentication_user = username;
423 g_list_free_full (priv->responses_received, g_free);
424 priv->responses_received = NULL;
425 priv->n_responses_waiting = 0;
427 n_messages = read_int (message, message_length, offset);
428 g_debug ("Prompt user with %d message(s)", n_messages);
430 for (i = 0; i < n_messages; i++)
435 style = read_int (message, message_length, offset);
436 text = read_string (message, message_length, offset);
438 // FIXME: Should stop on prompts?
441 case PAM_PROMPT_ECHO_OFF:
442 priv->n_responses_waiting++;
443 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
445 case PAM_PROMPT_ECHO_ON:
446 priv->n_responses_waiting++;
447 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
450 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
453 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
462 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
464 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
465 guint32 sequence_number, return_code;
468 sequence_number = read_int (message, message_length, offset);
470 if (sequence_number != priv->authenticate_sequence_number)
472 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
476 username = read_string (message, message_length, offset);
477 return_code = read_int (message, message_length, offset);
479 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
481 /* Update username */
482 if (strcmp (username, "") == 0)
487 g_free (priv->authentication_user);
488 priv->authentication_user = username;
490 priv->cancelling_authentication = FALSE;
491 priv->is_authenticated = (return_code == 0);
493 priv->in_authentication = FALSE;
494 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
498 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
500 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
504 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
506 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
507 GString *hint_string;
509 g_hash_table_remove_all (priv->hints);
511 hint_string = g_string_new ("");
512 while (*offset < message_length)
516 name = read_string (message, message_length, offset);
517 value = read_string (message, message_length, offset);
518 g_hash_table_insert (priv->hints, name, value);
519 g_string_append_printf (hint_string, " %s=%s", name, value);
522 g_debug ("Reset%s", hint_string->str);
523 g_string_free (hint_string, TRUE);
525 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
529 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
531 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
534 /* Notify asynchronous caller */
535 request = g_list_nth_data (priv->start_session_requests, 0);
538 request->return_code = read_int (message, message_length, offset);
539 request_complete (request, G_OBJECT (greeter));
540 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
541 g_object_unref (request);
546 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
548 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
551 /* Notify asynchronous caller */
552 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
555 request->dir = read_string (message, message_length, offset);
556 /* Blank data dir means invalid user */
557 if (g_strcmp0 (request->dir, "") == 0)
559 g_free (request->dir);
562 request_complete (request, G_OBJECT (greeter));
563 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
564 g_object_unref (request);
569 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
574 id = read_int (message, message_length, &offset);
575 read_int (message, message_length, &offset);
578 case SERVER_MESSAGE_CONNECTED:
579 handle_connected (greeter, message, message_length, &offset);
581 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
582 handle_prompt_authentication (greeter, message, message_length, &offset);
584 case SERVER_MESSAGE_END_AUTHENTICATION:
585 handle_end_authentication (greeter, message, message_length, &offset);
587 case SERVER_MESSAGE_SESSION_RESULT:
588 handle_session_result (greeter, message, message_length, &offset);
590 case SERVER_MESSAGE_SHARED_DIR_RESULT:
591 handle_shared_dir_result (greeter, message, message_length, &offset);
593 case SERVER_MESSAGE_IDLE:
594 handle_idle (greeter, message, message_length, &offset);
596 case SERVER_MESSAGE_RESET:
597 handle_reset (greeter, message, message_length, &offset);
600 g_warning ("Unknown message from server: %d", id);
606 recv_message (LightDMGreeter *greeter, gsize *length, gboolean block)
608 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
609 gsize n_to_read, n_read;
611 GError *error = NULL;
613 if (!priv->from_server_channel)
616 /* Read the header, or the whole message if we already have that */
617 n_to_read = HEADER_SIZE;
618 if (priv->n_read >= HEADER_SIZE)
619 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
624 status = g_io_channel_read_chars (priv->from_server_channel,
625 (gchar *) priv->read_buffer + priv->n_read,
626 n_to_read - priv->n_read,
630 g_warning ("Error reading from server: %s", error->message);
631 g_clear_error (&error);
632 if (status != G_IO_STATUS_NORMAL)
635 g_debug ("Read %zi bytes from daemon", n_read);
637 priv->n_read += n_read;
638 } while (priv->n_read < n_to_read && block);
640 /* Stop if haven't got all the data we want */
641 if (priv->n_read != n_to_read)
644 /* If have header, rerun for content */
645 if (priv->n_read == HEADER_SIZE)
647 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
650 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
651 return recv_message (greeter, length, block);
655 buffer = priv->read_buffer;
656 *length = priv->n_read;
658 priv->read_buffer = g_malloc (priv->n_read);
665 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
667 LightDMGreeter *greeter = data;
669 gsize message_length;
671 /* Read one message and process it */
672 message = recv_message (greeter, &message_length, FALSE);
675 handle_message (greeter, message, message_length);
683 send_connect (LightDMGreeter *greeter, gboolean resettable)
685 guint8 message[MAX_MESSAGE_LENGTH];
688 g_debug ("Connecting to display manager...");
689 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
690 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
691 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset);
693 return send_message (greeter, message, offset);
697 send_start_session (LightDMGreeter *greeter, const gchar *session)
699 guint8 message[MAX_MESSAGE_LENGTH];
703 g_debug ("Starting session %s", session);
705 g_debug ("Starting default session");
707 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
708 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
709 return send_message (greeter, message, offset);
713 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
715 guint8 message[MAX_MESSAGE_LENGTH];
718 g_debug ("Ensuring data directory for user %s", username);
720 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset);
721 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
722 return send_message (greeter, message, offset);
726 * lightdm_greeter_connect_to_daemon:
727 * @greeter: The greeter to connect
728 * @cancellable: (allow-none): A #GCancellable or %NULL.
729 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
730 * @user_data: (allow-none): data to pass to the @callback or %NULL.
732 * Asynchronously connects the greeter to the display manager.
734 * 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.
736 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
739 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
741 LightDMGreeterPrivate *priv;
744 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
746 priv = GET_PRIVATE (greeter);
748 request = request_new (cancellable, callback, user_data);
749 priv->connect_requests = g_list_append (priv->connect_requests, request);
750 send_connect (greeter, priv->resettable);
754 * lightdm_greeter_connect_to_daemon_finish:
755 * @result: A #GAsyncResult.
756 * @error: return location for a #GError, or %NULL
758 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
760 * Return value: #TRUE if successfully connected
763 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
765 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
766 return REQUEST (result)->complete;
770 * lightdm_greeter_connect_to_daemon_sync:
771 * @greeter: The greeter to connect
772 * @error: return location for a #GError, or %NULL
774 * Connects the greeter to the display manager. Will block until connected.
776 * Return value: #TRUE if successfully connected
779 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
781 LightDMGreeterPrivate *priv;
784 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
786 priv = GET_PRIVATE (greeter);
788 /* Read until we are connected */
789 send_connect (greeter, priv->resettable);
790 request = request_new (NULL, NULL, NULL);
791 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
795 gsize message_length;
797 message = recv_message (greeter, &message_length, TRUE);
800 handle_message (greeter, message, message_length);
802 } while (!request->complete);
804 g_object_unref (request);
806 return request->complete;
810 * lightdm_greeter_connect_sync:
811 * @greeter: The greeter to connect
812 * @error: return location for a #GError, or %NULL
814 * Connects the greeter to the display manager. Will block until connected.
816 * Return value: #TRUE if successfully connected
818 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
821 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
823 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
827 * lightdm_greeter_get_hint:
828 * @greeter: A #LightDMGreeter
829 * @name: The hint name to query.
833 * Return value: The value for this hint or #NULL if not set.
836 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
838 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
839 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
843 * lightdm_greeter_get_default_session_hint:
844 * @greeter: A #LightDMGreeter
846 * Get the default session to use.
848 * Return value: The session name
851 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
853 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
854 return lightdm_greeter_get_hint (greeter, "default-session");
858 * lightdm_greeter_get_hide_users_hint:
859 * @greeter: A #LightDMGreeter
861 * Check if user accounts should be shown. If this is TRUE then the list of
862 * accounts should be taken from #LightDMUserList and displayed in the greeter
863 * for the user to choose from. Note that this list can be empty and it is
864 * recommended you show a method for the user to enter a username manually.
866 * If this option is shown the greeter should only allow these users to be
867 * chosen for login unless the manual login hint is set.
869 * Return value: #TRUE if the available users should not be shown.
872 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
876 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
877 value = lightdm_greeter_get_hint (greeter, "hide-users");
879 return g_strcmp0 (value, "true") == 0;
883 * lightdm_greeter_get_show_manual_login_hint:
884 * @greeter: A #LightDMGreeter
886 * Check if a manual login option should be shown. If set the GUI
887 * should provide a way for a username to be entered manually.
888 * Without this hint a greeter which is showing a user list can
889 * limit logins to only those users.
891 * Return value: #TRUE if a manual login option should be shown.
894 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
898 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
899 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
901 return g_strcmp0 (value, "true") == 0;
905 * lightdm_greeter_get_show_remote_login_hint:
906 * @greeter: A #LightDMGreeter
908 * Check if a remote login option should be shown. If set the GUI
909 * should provide a way for a user to log into a remote desktop server.
911 * Return value: #TRUE if a remote login option should be shown.
914 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
918 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
919 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
921 return g_strcmp0 (value, "true") == 0;
925 * lightdm_greeter_get_lock_hint:
926 * @greeter: A #LightDMGreeter
928 * Check if the greeter is acting as a lock screen.
930 * Return value: #TRUE if the greeter was triggered by locking the seat.
933 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
937 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
938 value = lightdm_greeter_get_hint (greeter, "lock-screen");
940 return g_strcmp0 (value, "true") == 0;
944 * lightdm_greeter_get_has_guest_account_hint:
945 * @greeter: A #LightDMGreeter
947 * Check if guest sessions are supported.
949 * Return value: #TRUE if guest sessions are supported.
952 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
956 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
957 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
959 return g_strcmp0 (value, "true") == 0;
963 * lightdm_greeter_get_select_user_hint:
964 * @greeter: A #LightDMGreeter
966 * Get the user to select by default.
968 * Return value: A username
971 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
973 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
974 return lightdm_greeter_get_hint (greeter, "select-user");
978 * lightdm_greeter_get_select_guest_hint:
979 * @greeter: A #LightDMGreeter
981 * Check if the guest account should be selected by default.
983 * Return value: #TRUE if the guest account should be selected by default.
986 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
990 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
991 value = lightdm_greeter_get_hint (greeter, "select-guest");
993 return g_strcmp0 (value, "true") == 0;
997 * lightdm_greeter_get_autologin_user_hint:
998 * @greeter: A #LightDMGreeter
1000 * Get the user account to automatically logg into when the timer expires.
1002 * Return value: The user account to automatically log into.
1005 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1007 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1008 return lightdm_greeter_get_hint (greeter, "autologin-user");
1012 * lightdm_greeter_get_autologin_guest_hint:
1013 * @greeter: A #LightDMGreeter
1015 * Check if the guest account should be automatically logged into when the timer expires.
1017 * Return value: #TRUE if the guest account should be automatically logged into.
1020 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1024 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1025 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1027 return g_strcmp0 (value, "true") == 0;
1031 * lightdm_greeter_get_autologin_timeout_hint:
1032 * @greeter: A #LightDMGreeter
1034 * Get the number of seconds to wait before automaitcally logging in.
1036 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1039 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1044 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1045 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1047 timeout = atoi (value);
1055 * lightdm_greeter_cancel_autologin:
1056 * @greeter: A #LightDMGreeter
1058 * Cancel the automatic login.
1061 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1063 LightDMGreeterPrivate *priv;
1065 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1067 priv = GET_PRIVATE (greeter);
1069 if (priv->autologin_timeout)
1070 g_source_remove (priv->autologin_timeout);
1071 priv->autologin_timeout = 0;
1075 * lightdm_greeter_authenticate:
1076 * @greeter: A #LightDMGreeter
1077 * @username: (allow-none): A username or #NULL to prompt for a username.
1079 * Starts the authentication procedure for a user.
1082 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
1084 LightDMGreeterPrivate *priv;
1085 guint8 message[MAX_MESSAGE_LENGTH];
1088 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1090 priv = GET_PRIVATE (greeter);
1092 g_return_if_fail (priv->connected);
1094 priv->cancelling_authentication = FALSE;
1095 priv->authenticate_sequence_number++;
1096 priv->in_authentication = TRUE;
1097 priv->is_authenticated = FALSE;
1098 if (username != priv->authentication_user)
1100 g_free (priv->authentication_user);
1101 priv->authentication_user = g_strdup (username);
1104 g_debug ("Starting authentication for user %s...", username);
1105 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
1106 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1107 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1108 send_message (greeter, message, offset);
1112 * lightdm_greeter_authenticate_as_guest:
1113 * @greeter: A #LightDMGreeter
1115 * Starts the authentication procedure for the guest user.
1118 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
1120 LightDMGreeterPrivate *priv;
1121 guint8 message[MAX_MESSAGE_LENGTH];
1124 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1126 priv = GET_PRIVATE (greeter);
1128 g_return_if_fail (priv->connected);
1130 priv->cancelling_authentication = FALSE;
1131 priv->authenticate_sequence_number++;
1132 priv->in_authentication = TRUE;
1133 priv->is_authenticated = FALSE;
1134 g_free (priv->authentication_user);
1135 priv->authentication_user = NULL;
1137 g_debug ("Starting authentication for guest account...");
1138 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
1139 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1140 send_message (greeter, message, offset);
1144 * lightdm_greeter_authenticate_autologin:
1145 * @greeter: A #LightDMGreeter
1147 * Starts the authentication procedure for the automatic login user.
1150 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
1154 user = lightdm_greeter_get_autologin_user_hint (greeter);
1155 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1156 lightdm_greeter_authenticate_as_guest (greeter);
1158 lightdm_greeter_authenticate (greeter, user);
1162 * lightdm_greeter_authenticate_remote:
1163 * @greeter: A #LightDMGreeter
1164 * @session: The name of a remote session
1165 * @username: (allow-none): A username of #NULL to prompt for a username.
1167 * Start authentication for a remote session type.
1170 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
1172 LightDMGreeterPrivate *priv;
1173 guint8 message[MAX_MESSAGE_LENGTH];
1176 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1178 priv = GET_PRIVATE (greeter);
1180 g_return_if_fail (priv->connected);
1182 priv->cancelling_authentication = FALSE;
1183 priv->authenticate_sequence_number++;
1184 priv->in_authentication = TRUE;
1185 priv->is_authenticated = FALSE;
1186 g_free (priv->authentication_user);
1187 priv->authentication_user = NULL;
1190 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1192 g_debug ("Starting authentication for remote session %s...", session);
1193 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
1194 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1195 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1196 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1197 send_message (greeter, message, offset);
1201 * lightdm_greeter_respond:
1202 * @greeter: A #LightDMGreeter
1203 * @response: Response to a prompt
1205 * Provide response to a prompt. May be one in a series.
1208 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
1210 LightDMGreeterPrivate *priv;
1211 guint8 message[MAX_MESSAGE_LENGTH];
1214 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1215 g_return_if_fail (response != NULL);
1217 priv = GET_PRIVATE (greeter);
1219 g_return_if_fail (priv->connected);
1220 g_return_if_fail (priv->n_responses_waiting > 0);
1222 priv->n_responses_waiting--;
1223 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1225 if (priv->n_responses_waiting == 0)
1230 g_debug ("Providing response to display manager");
1232 msg_length = int_length ();
1233 for (iter = priv->responses_received; iter; iter = iter->next)
1234 msg_length += string_length ((gchar *)iter->data);
1236 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
1237 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
1238 for (iter = priv->responses_received; iter; iter = iter->next)
1239 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
1240 send_message (greeter, message, offset);
1242 g_list_free_full (priv->responses_received, g_free);
1243 priv->responses_received = NULL;
1248 * lightdm_greeter_cancel_authentication:
1249 * @greeter: A #LightDMGreeter
1251 * Cancel the current user authentication.
1254 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
1256 LightDMGreeterPrivate *priv;
1257 guint8 message[MAX_MESSAGE_LENGTH];
1260 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1262 priv = GET_PRIVATE (greeter);
1264 g_return_if_fail (priv->connected);
1266 priv->cancelling_authentication = TRUE;
1267 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1268 send_message (greeter, message, offset);
1272 * lightdm_greeter_get_in_authentication:
1273 * @greeter: A #LightDMGreeter
1275 * Checks if the greeter is in the process of authenticating.
1277 * Return value: #TRUE if the greeter is authenticating a user.
1280 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1282 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1283 return GET_PRIVATE (greeter)->in_authentication;
1287 * lightdm_greeter_get_is_authenticated:
1288 * @greeter: A #LightDMGreeter
1290 * Checks if the greeter has successfully authenticated.
1292 * Return value: #TRUE if the greeter is authenticated for login.
1295 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1297 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1298 return GET_PRIVATE (greeter)->is_authenticated;
1302 * lightdm_greeter_get_authentication_user:
1303 * @greeter: A #LightDMGreeter
1305 * Get the user that is being authenticated.
1307 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1310 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1312 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1313 return GET_PRIVATE (greeter)->authentication_user;
1317 * lightdm_greeter_set_language:
1318 * @greeter: A #LightDMGreeter
1319 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1321 * Set the language for the currently authenticated user.
1324 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1326 LightDMGreeterPrivate *priv;
1327 guint8 message[MAX_MESSAGE_LENGTH];
1330 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1332 priv = GET_PRIVATE (greeter);
1334 g_return_if_fail (priv->connected);
1336 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1337 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1338 send_message (greeter, message, offset);
1342 * lightdm_greeter_start_session:
1343 * @greeter: A #LightDMGreeter
1344 * @session: (allow-none): The session to log into or #NULL to use the default.
1345 * @cancellable: (allow-none): A #GCancellable or %NULL.
1346 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1347 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1349 * Asynchronously start a session for the authenticated user.
1351 * 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.
1353 * See lightdm_greeter_start_session_sync() for the synchronous version.
1356 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1358 LightDMGreeterPrivate *priv;
1361 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1363 priv = GET_PRIVATE (greeter);
1365 send_start_session (greeter, session);
1366 request = request_new (cancellable, callback, user_data);
1367 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1371 * lightdm_greeter_start_session_finish:
1372 * @greeter: A #LightDMGreeter
1373 * @result: A #GAsyncResult.
1374 * @error: return location for a #GError, or %NULL
1376 * Start a session for the authenticated user.
1378 * Return value: TRUE if the session was started.
1381 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1383 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1384 return REQUEST (result)->return_code == 0;
1388 * lightdm_greeter_start_session_sync:
1389 * @greeter: A #LightDMGreeter
1390 * @session: (allow-none): The session to log into or #NULL to use the default.
1391 * @error: return location for a #GError, or %NULL
1393 * Start a session for the authenticated user.
1395 * Return value: TRUE if the session was started.
1398 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1400 LightDMGreeterPrivate *priv;
1402 guint32 return_code;
1404 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1406 priv = GET_PRIVATE (greeter);
1408 g_return_val_if_fail (priv->connected, FALSE);
1409 g_return_val_if_fail (priv->is_authenticated, FALSE);
1411 /* Read until the session is started */
1412 send_start_session (greeter, session);
1413 request = request_new (NULL, NULL, NULL);
1414 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1418 gsize message_length;
1420 message = recv_message (greeter, &message_length, TRUE);
1423 handle_message (greeter, message, message_length);
1425 } while (!request->complete);
1427 return_code = request->return_code;
1428 g_object_unref (request);
1430 return return_code == 0;
1434 * lightdm_greeter_ensure_shared_data_dir:
1435 * @greeter: A #LightDMGreeter
1436 * @username: A username
1437 * @cancellable: (allow-none): A #GCancellable or %NULL.
1438 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1439 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1441 * Ensure that a shared data dir for the given user is available. Both the
1442 * greeter user and @username will have write access to that folder. The
1443 * intention is that larger pieces of shared data would be stored there (files
1444 * that the greeter creates but wants to give to a user -- like camera
1445 * photos -- or files that the user creates but wants the greeter to
1446 * see -- like contact avatars).
1448 * LightDM will automatically create these if the user actually logs in, so
1449 * greeters only need to call this method if they want to store something in
1450 * the directory themselves.
1453 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1455 LightDMGreeterPrivate *priv;
1458 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1460 priv = GET_PRIVATE (greeter);
1462 send_ensure_shared_data_dir (greeter, username);
1463 request = request_new (cancellable, callback, user_data);
1464 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1468 * lightdm_greeter_ensure_shared_data_dir_finish:
1469 * @result: A #GAsyncResult.
1470 * @greeter: A #LightDMGreeter
1473 * Return value: The path to the shared directory, free with g_free.
1476 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result)
1478 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1479 return g_strdup (REQUEST (result)->dir);
1483 * lightdm_greeter_ensure_shared_data_dir_sync:
1484 * @greeter: A #LightDMGreeter
1485 * @username: A username
1487 * Ensure that a shared data dir for the given user is available. Both the
1488 * greeter user and @username will have write access to that folder. The
1489 * intention is that larger pieces of shared data would be stored there (files
1490 * that the greeter creates but wants to give to a user -- like camera
1491 * photos -- or files that the user creates but wants the greeter to
1492 * see -- like contact avatars).
1494 * LightDM will automatically create these if the user actually logs in, so
1495 * greeters only need to call this method if they want to store something in
1496 * the directory themselves.
1498 * Return value: The path to the shared directory, free with g_free.
1501 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username)
1503 LightDMGreeterPrivate *priv;
1507 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1509 priv = GET_PRIVATE (greeter);
1511 g_return_val_if_fail (priv->connected, NULL);
1513 /* Read until a response */
1514 send_ensure_shared_data_dir (greeter, username);
1515 request = request_new (NULL, NULL, NULL);
1516 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1520 gsize message_length;
1522 message = recv_message (greeter, &message_length, TRUE);
1525 handle_message (greeter, message, message_length);
1527 } while (!request->complete);
1529 data_dir = g_strdup (request->dir);
1530 g_object_unref (request);
1536 lightdm_greeter_init (LightDMGreeter *greeter)
1538 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1541 priv->read_buffer = g_malloc (HEADER_SIZE);
1542 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1544 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
1547 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
1548 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
1551 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
1553 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
1556 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
1557 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
1558 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
1561 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
1565 lightdm_greeter_set_property (GObject *object,
1567 const GValue *value,
1570 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1574 lightdm_greeter_get_property (GObject *object,
1579 LightDMGreeter *self;
1581 self = LIGHTDM_GREETER (object);
1584 case PROP_DEFAULT_SESSION_HINT:
1585 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1587 case PROP_HIDE_USERS_HINT:
1588 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1590 case PROP_SHOW_MANUAL_LOGIN_HINT:
1591 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1593 case PROP_SHOW_REMOTE_LOGIN_HINT:
1594 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1596 case PROP_LOCK_HINT:
1597 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1599 case PROP_HAS_GUEST_ACCOUNT_HINT:
1600 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1602 case PROP_SELECT_USER_HINT:
1603 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1605 case PROP_SELECT_GUEST_HINT:
1606 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1608 case PROP_AUTOLOGIN_USER_HINT:
1609 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1611 case PROP_AUTOLOGIN_GUEST_HINT:
1612 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1614 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1615 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1617 case PROP_AUTHENTICATION_USER:
1618 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1620 case PROP_IN_AUTHENTICATION:
1621 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1623 case PROP_IS_AUTHENTICATED:
1624 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1627 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1633 lightdm_greeter_finalize (GObject *object)
1635 LightDMGreeter *self = LIGHTDM_GREETER (object);
1636 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1638 if (priv->to_server_channel)
1639 g_io_channel_unref (priv->to_server_channel);
1640 if (priv->from_server_channel)
1641 g_io_channel_unref (priv->from_server_channel);
1642 g_free (priv->authentication_user);
1643 g_hash_table_unref (priv->hints);
1645 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1649 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1651 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1653 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1655 object_class->set_property = lightdm_greeter_set_property;
1656 object_class->get_property = lightdm_greeter_get_property;
1657 object_class->finalize = lightdm_greeter_finalize;
1659 g_object_class_install_property (object_class,
1660 PROP_DEFAULT_SESSION_HINT,
1661 g_param_spec_string ("default-session-hint",
1662 "default-session-hint",
1663 "Default session hint",
1665 G_PARAM_READWRITE));
1667 g_object_class_install_property (object_class,
1668 PROP_HIDE_USERS_HINT,
1669 g_param_spec_boolean ("hide-users-hint",
1675 g_object_class_install_property (object_class,
1676 PROP_SHOW_MANUAL_LOGIN_HINT,
1677 g_param_spec_boolean ("show-manual-login-hint",
1678 "show-manual-login-hint",
1679 "Show manual login hint",
1683 g_object_class_install_property (object_class,
1684 PROP_SHOW_REMOTE_LOGIN_HINT,
1685 g_param_spec_boolean ("show-remote-login-hint",
1686 "show-remote-login-hint",
1687 "Show remote login hint",
1691 g_object_class_install_property (object_class,
1693 g_param_spec_boolean ("lock-hint",
1699 g_object_class_install_property (object_class,
1700 PROP_HAS_GUEST_ACCOUNT_HINT,
1701 g_param_spec_boolean ("has-guest-account-hint",
1702 "has-guest-account-hint",
1703 "Has guest account hint",
1707 g_object_class_install_property (object_class,
1708 PROP_SELECT_USER_HINT,
1709 g_param_spec_string ("select-user-hint",
1715 g_object_class_install_property (object_class,
1716 PROP_SELECT_GUEST_HINT,
1717 g_param_spec_boolean ("select-guest-hint",
1718 "select-guest-hint",
1719 "Select guest account hint",
1723 g_object_class_install_property (object_class,
1724 PROP_AUTOLOGIN_USER_HINT,
1725 g_param_spec_string ("autologin-user-hint",
1726 "autologin-user-hint",
1727 "Autologin user hint",
1731 g_object_class_install_property (object_class,
1732 PROP_AUTOLOGIN_GUEST_HINT,
1733 g_param_spec_boolean ("autologin-guest-hint",
1734 "autologin-guest-hint",
1735 "Autologin guest account hint",
1739 g_object_class_install_property (object_class,
1740 PROP_AUTOLOGIN_TIMEOUT_HINT,
1741 g_param_spec_int ("autologin-timeout-hint",
1742 "autologin-timeout-hint",
1743 "Autologin timeout hint",
1747 g_object_class_install_property (object_class,
1748 PROP_AUTHENTICATION_USER,
1749 g_param_spec_string ("authentication-user",
1750 "authentication-user",
1751 "The user being authenticated",
1754 g_object_class_install_property (object_class,
1755 PROP_IN_AUTHENTICATION,
1756 g_param_spec_boolean ("in-authentication",
1757 "in-authentication",
1758 "TRUE if a user is being authenticated",
1761 g_object_class_install_property (object_class,
1762 PROP_IS_AUTHENTICATED,
1763 g_param_spec_boolean ("is-authenticated",
1765 "TRUE if the selected user is authenticated",
1770 * LightDMGreeter::show-prompt:
1771 * @greeter: A #LightDMGreeter
1772 * @text: Prompt text
1773 * @type: Prompt type
1775 * The ::show-prompt signal gets emitted when the greeter should show a
1776 * prompt to the user. The given text should be displayed and an input
1777 * field for the user to provide a response.
1779 * Call lightdm_greeter_respond() with the resultant input or
1780 * lightdm_greeter_cancel_authentication() to abort the authentication.
1782 signals[SHOW_PROMPT] =
1783 g_signal_new ("show-prompt",
1784 G_TYPE_FROM_CLASS (klass),
1786 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1789 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1792 * LightDMGreeter::show-message:
1793 * @greeter: A #LightDMGreeter
1794 * @text: Message text
1795 * @type: Message type
1797 * The ::show-message signal gets emitted when the greeter
1798 * should show a message to the user.
1800 signals[SHOW_MESSAGE] =
1801 g_signal_new ("show-message",
1802 G_TYPE_FROM_CLASS (klass),
1804 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1807 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1810 * LightDMGreeter::authentication-complete:
1811 * @greeter: A #LightDMGreeter
1813 * The ::authentication-complete signal gets emitted when the greeter
1814 * has completed authentication.
1816 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1819 signals[AUTHENTICATION_COMPLETE] =
1820 g_signal_new ("authentication-complete",
1821 G_TYPE_FROM_CLASS (klass),
1823 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1829 * LightDMGreeter::autologin-timer-expired:
1830 * @greeter: A #LightDMGreeter
1832 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1833 * The application should then call lightdm_greeter_login().
1835 signals[AUTOLOGIN_TIMER_EXPIRED] =
1836 g_signal_new ("autologin-timer-expired",
1837 G_TYPE_FROM_CLASS (klass),
1839 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1845 * LightDMGreeter::idle:
1846 * @greeter: A #LightDMGreeter
1848 * The ::idle signal gets emitted when the user has logged in and the
1849 * greeter is no longer needed.
1851 * This signal only matters if the greeter has marked itself as
1852 * resettable using lightdm_greeter_set_resettable().
1855 g_signal_new ("idle",
1856 G_TYPE_FROM_CLASS (klass),
1858 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
1864 * LightDMGreeter::reset:
1865 * @greeter: A #LightDMGreeter
1867 * The ::reset signal gets emitted when the user is returning to a greeter
1868 * that was previously marked idle.
1870 * This signal only matters if the greeter has marked itself as
1871 * resettable using lightdm_greeter_set_resettable().
1874 g_signal_new ("reset",
1875 G_TYPE_FROM_CLASS (klass),
1877 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
1884 request_init (Request *request)
1889 request_finalize (GObject *object)
1891 Request *request = REQUEST (object);
1893 g_free (request->dir);
1894 if (request->cancellable)
1895 g_object_unref (request->cancellable);
1897 G_OBJECT_CLASS (request_parent_class)->finalize (object);
1901 request_class_init (RequestClass *klass)
1903 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1904 object_class->finalize = request_finalize;
1908 request_get_user_data (GAsyncResult *result)
1910 return REQUEST (result)->user_data;
1914 request_get_source_object (GAsyncResult *res)
1920 request_is_tagged (GAsyncResult *res, gpointer source_tag)
1926 request_iface_init (GAsyncResultIface *iface)
1928 iface->get_user_data = request_get_user_data;
1929 iface->get_source_object = request_get_source_object;
1930 iface->is_tagged = request_is_tagged;