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:
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_finish() to get the result of the operation.
736 * See lightdm_greeter_connect_sync() for the synchronous version.
739 lightdm_greeter_connect (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_finish:
755 * @result: A #GAsyncResult.
756 * @error: return location for a #GError, or %NULL
758 * Finishes an operation started with lightdm_greeter_connect().
760 * Return value: #TRUE if successfully connected
763 lightdm_greeter_connect_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_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_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_get_hint:
811 * @greeter: A #LightDMGreeter
812 * @name: The hint name to query.
816 * Return value: The value for this hint or #NULL if not set.
819 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
821 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
822 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
826 * lightdm_greeter_get_default_session_hint:
827 * @greeter: A #LightDMGreeter
829 * Get the default session to use.
831 * Return value: The session name
834 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
836 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
837 return lightdm_greeter_get_hint (greeter, "default-session");
841 * lightdm_greeter_get_hide_users_hint:
842 * @greeter: A #LightDMGreeter
844 * Check if user accounts should be shown. If this is TRUE then the list of
845 * accounts should be taken from #LightDMUserList and displayed in the greeter
846 * for the user to choose from. Note that this list can be empty and it is
847 * recommended you show a method for the user to enter a username manually.
849 * If this option is shown the greeter should only allow these users to be
850 * chosen for login unless the manual login hint is set.
852 * Return value: #TRUE if the available users should not be shown.
855 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
859 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
860 value = lightdm_greeter_get_hint (greeter, "hide-users");
862 return g_strcmp0 (value, "true") == 0;
866 * lightdm_greeter_get_show_manual_login_hint:
867 * @greeter: A #LightDMGreeter
869 * Check if a manual login option should be shown. If set the GUI
870 * should provide a way for a username to be entered manually.
871 * Without this hint a greeter which is showing a user list can
872 * limit logins to only those users.
874 * Return value: #TRUE if a manual login option should be shown.
877 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
881 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
882 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
884 return g_strcmp0 (value, "true") == 0;
888 * lightdm_greeter_get_show_remote_login_hint:
889 * @greeter: A #LightDMGreeter
891 * Check if a remote login option should be shown. If set the GUI
892 * should provide a way for a user to log into a remote desktop server.
894 * Return value: #TRUE if a remote login option should be shown.
897 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
901 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
902 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
904 return g_strcmp0 (value, "true") == 0;
908 * lightdm_greeter_get_lock_hint:
909 * @greeter: A #LightDMGreeter
911 * Check if the greeter is acting as a lock screen.
913 * Return value: #TRUE if the greeter was triggered by locking the seat.
916 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
920 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
921 value = lightdm_greeter_get_hint (greeter, "lock-screen");
923 return g_strcmp0 (value, "true") == 0;
927 * lightdm_greeter_get_has_guest_account_hint:
928 * @greeter: A #LightDMGreeter
930 * Check if guest sessions are supported.
932 * Return value: #TRUE if guest sessions are supported.
935 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
939 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
940 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
942 return g_strcmp0 (value, "true") == 0;
946 * lightdm_greeter_get_select_user_hint:
947 * @greeter: A #LightDMGreeter
949 * Get the user to select by default.
951 * Return value: A username
954 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
956 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
957 return lightdm_greeter_get_hint (greeter, "select-user");
961 * lightdm_greeter_get_select_guest_hint:
962 * @greeter: A #LightDMGreeter
964 * Check if the guest account should be selected by default.
966 * Return value: #TRUE if the guest account should be selected by default.
969 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
973 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
974 value = lightdm_greeter_get_hint (greeter, "select-guest");
976 return g_strcmp0 (value, "true") == 0;
980 * lightdm_greeter_get_autologin_user_hint:
981 * @greeter: A #LightDMGreeter
983 * Get the user account to automatically logg into when the timer expires.
985 * Return value: The user account to automatically log into.
988 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
990 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
991 return lightdm_greeter_get_hint (greeter, "autologin-user");
995 * lightdm_greeter_get_autologin_guest_hint:
996 * @greeter: A #LightDMGreeter
998 * Check if the guest account should be automatically logged into when the timer expires.
1000 * Return value: #TRUE if the guest account should be automatically logged into.
1003 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1007 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1008 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1010 return g_strcmp0 (value, "true") == 0;
1014 * lightdm_greeter_get_autologin_timeout_hint:
1015 * @greeter: A #LightDMGreeter
1017 * Get the number of seconds to wait before automaitcally logging in.
1019 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1022 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1027 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1028 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1030 timeout = atoi (value);
1038 * lightdm_greeter_cancel_autologin:
1039 * @greeter: A #LightDMGreeter
1041 * Cancel the automatic login.
1044 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1046 LightDMGreeterPrivate *priv;
1048 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1050 priv = GET_PRIVATE (greeter);
1052 if (priv->autologin_timeout)
1053 g_source_remove (priv->autologin_timeout);
1054 priv->autologin_timeout = 0;
1058 * lightdm_greeter_authenticate:
1059 * @greeter: A #LightDMGreeter
1060 * @username: (allow-none): A username or #NULL to prompt for a username.
1062 * Starts the authentication procedure for a user.
1065 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
1067 LightDMGreeterPrivate *priv;
1068 guint8 message[MAX_MESSAGE_LENGTH];
1071 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1073 priv = GET_PRIVATE (greeter);
1075 g_return_if_fail (priv->connected);
1077 priv->cancelling_authentication = FALSE;
1078 priv->authenticate_sequence_number++;
1079 priv->in_authentication = TRUE;
1080 priv->is_authenticated = FALSE;
1081 if (username != priv->authentication_user)
1083 g_free (priv->authentication_user);
1084 priv->authentication_user = g_strdup (username);
1087 g_debug ("Starting authentication for user %s...", username);
1088 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
1089 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1090 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1091 send_message (greeter, message, offset);
1095 * lightdm_greeter_authenticate_as_guest:
1096 * @greeter: A #LightDMGreeter
1098 * Starts the authentication procedure for the guest user.
1101 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
1103 LightDMGreeterPrivate *priv;
1104 guint8 message[MAX_MESSAGE_LENGTH];
1107 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1109 priv = GET_PRIVATE (greeter);
1111 g_return_if_fail (priv->connected);
1113 priv->cancelling_authentication = FALSE;
1114 priv->authenticate_sequence_number++;
1115 priv->in_authentication = TRUE;
1116 priv->is_authenticated = FALSE;
1117 g_free (priv->authentication_user);
1118 priv->authentication_user = NULL;
1120 g_debug ("Starting authentication for guest account...");
1121 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
1122 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1123 send_message (greeter, message, offset);
1127 * lightdm_greeter_authenticate_autologin:
1128 * @greeter: A #LightDMGreeter
1130 * Starts the authentication procedure for the automatic login user.
1133 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
1137 user = lightdm_greeter_get_autologin_user_hint (greeter);
1138 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1139 lightdm_greeter_authenticate_as_guest (greeter);
1141 lightdm_greeter_authenticate (greeter, user);
1145 * lightdm_greeter_authenticate_remote:
1146 * @greeter: A #LightDMGreeter
1147 * @session: The name of a remote session
1148 * @username: (allow-none): A username of #NULL to prompt for a username.
1150 * Start authentication for a remote session type.
1153 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
1155 LightDMGreeterPrivate *priv;
1156 guint8 message[MAX_MESSAGE_LENGTH];
1159 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1161 priv = GET_PRIVATE (greeter);
1163 g_return_if_fail (priv->connected);
1165 priv->cancelling_authentication = FALSE;
1166 priv->authenticate_sequence_number++;
1167 priv->in_authentication = TRUE;
1168 priv->is_authenticated = FALSE;
1169 g_free (priv->authentication_user);
1170 priv->authentication_user = NULL;
1173 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1175 g_debug ("Starting authentication for remote session %s...", session);
1176 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
1177 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1178 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1179 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1180 send_message (greeter, message, offset);
1184 * lightdm_greeter_respond:
1185 * @greeter: A #LightDMGreeter
1186 * @response: Response to a prompt
1188 * Provide response to a prompt. May be one in a series.
1191 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
1193 LightDMGreeterPrivate *priv;
1194 guint8 message[MAX_MESSAGE_LENGTH];
1197 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1198 g_return_if_fail (response != NULL);
1200 priv = GET_PRIVATE (greeter);
1202 g_return_if_fail (priv->connected);
1203 g_return_if_fail (priv->n_responses_waiting > 0);
1205 priv->n_responses_waiting--;
1206 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1208 if (priv->n_responses_waiting == 0)
1213 g_debug ("Providing response to display manager");
1215 msg_length = int_length ();
1216 for (iter = priv->responses_received; iter; iter = iter->next)
1217 msg_length += string_length ((gchar *)iter->data);
1219 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
1220 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
1221 for (iter = priv->responses_received; iter; iter = iter->next)
1222 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
1223 send_message (greeter, message, offset);
1225 g_list_free_full (priv->responses_received, g_free);
1226 priv->responses_received = NULL;
1231 * lightdm_greeter_cancel_authentication:
1232 * @greeter: A #LightDMGreeter
1234 * Cancel the current user authentication.
1237 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
1239 LightDMGreeterPrivate *priv;
1240 guint8 message[MAX_MESSAGE_LENGTH];
1243 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1245 priv = GET_PRIVATE (greeter);
1247 g_return_if_fail (priv->connected);
1249 priv->cancelling_authentication = TRUE;
1250 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1251 send_message (greeter, message, offset);
1255 * lightdm_greeter_get_in_authentication:
1256 * @greeter: A #LightDMGreeter
1258 * Checks if the greeter is in the process of authenticating.
1260 * Return value: #TRUE if the greeter is authenticating a user.
1263 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1265 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1266 return GET_PRIVATE (greeter)->in_authentication;
1270 * lightdm_greeter_get_is_authenticated:
1271 * @greeter: A #LightDMGreeter
1273 * Checks if the greeter has successfully authenticated.
1275 * Return value: #TRUE if the greeter is authenticated for login.
1278 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1280 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1281 return GET_PRIVATE (greeter)->is_authenticated;
1285 * lightdm_greeter_get_authentication_user:
1286 * @greeter: A #LightDMGreeter
1288 * Get the user that is being authenticated.
1290 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1293 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1295 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1296 return GET_PRIVATE (greeter)->authentication_user;
1300 * lightdm_greeter_set_language:
1301 * @greeter: A #LightDMGreeter
1302 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1304 * Set the language for the currently authenticated user.
1307 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1309 LightDMGreeterPrivate *priv;
1310 guint8 message[MAX_MESSAGE_LENGTH];
1313 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1315 priv = GET_PRIVATE (greeter);
1317 g_return_if_fail (priv->connected);
1319 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1320 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1321 send_message (greeter, message, offset);
1325 * lightdm_greeter_start_session:
1326 * @greeter: A #LightDMGreeter
1327 * @session: (allow-none): The session to log into or #NULL to use the default.
1328 * @cancellable: (allow-none): A #GCancellable or %NULL.
1329 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1330 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1332 * Asynchronously start a session for the authenticated user.
1334 * 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.
1336 * See lightdm_greeter_start_session_sync() for the synchronous version.
1339 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1341 LightDMGreeterPrivate *priv;
1344 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1346 priv = GET_PRIVATE (greeter);
1348 send_start_session (greeter, session);
1349 request = request_new (cancellable, callback, user_data);
1350 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1354 * lightdm_greeter_start_session_finish:
1355 * @greeter: A #LightDMGreeter
1356 * @result: A #GAsyncResult.
1357 * @error: return location for a #GError, or %NULL
1359 * Start a session for the authenticated user.
1361 * Return value: TRUE if the session was started.
1364 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1366 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1367 return REQUEST (result)->return_code == 0;
1371 * lightdm_greeter_start_session_sync:
1372 * @greeter: A #LightDMGreeter
1373 * @session: (allow-none): The session to log into or #NULL to use the default.
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_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1383 LightDMGreeterPrivate *priv;
1385 guint32 return_code;
1387 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1389 priv = GET_PRIVATE (greeter);
1391 g_return_val_if_fail (priv->connected, FALSE);
1392 g_return_val_if_fail (priv->is_authenticated, FALSE);
1394 /* Read until the session is started */
1395 send_start_session (greeter, session);
1396 request = request_new (NULL, NULL, NULL);
1397 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1401 gsize message_length;
1403 message = recv_message (greeter, &message_length, TRUE);
1406 handle_message (greeter, message, message_length);
1408 } while (!request->complete);
1410 return_code = request->return_code;
1411 g_object_unref (request);
1413 return return_code == 0;
1417 * lightdm_greeter_ensure_shared_data_dir:
1418 * @greeter: A #LightDMGreeter
1419 * @username: A username
1420 * @cancellable: (allow-none): A #GCancellable or %NULL.
1421 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1422 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1424 * Ensure that a shared data dir for the given user is available. Both the
1425 * greeter user and @username will have write access to that folder. The
1426 * intention is that larger pieces of shared data would be stored there (files
1427 * that the greeter creates but wants to give to a user -- like camera
1428 * photos -- or files that the user creates but wants the greeter to
1429 * see -- like contact avatars).
1431 * LightDM will automatically create these if the user actually logs in, so
1432 * greeters only need to call this method if they want to store something in
1433 * the directory themselves.
1436 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1438 LightDMGreeterPrivate *priv;
1441 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1443 priv = GET_PRIVATE (greeter);
1445 send_ensure_shared_data_dir (greeter, username);
1446 request = request_new (cancellable, callback, user_data);
1447 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1451 * lightdm_greeter_ensure_shared_data_dir_finish:
1452 * @result: A #GAsyncResult.
1453 * @greeter: A #LightDMGreeter
1456 * Return value: The path to the shared directory, free with g_free.
1459 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result)
1461 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1462 return g_strdup (REQUEST (result)->dir);
1466 * lightdm_greeter_ensure_shared_data_dir_sync:
1467 * @greeter: A #LightDMGreeter
1468 * @username: A username
1470 * Ensure that a shared data dir for the given user is available. Both the
1471 * greeter user and @username will have write access to that folder. The
1472 * intention is that larger pieces of shared data would be stored there (files
1473 * that the greeter creates but wants to give to a user -- like camera
1474 * photos -- or files that the user creates but wants the greeter to
1475 * see -- like contact avatars).
1477 * LightDM will automatically create these if the user actually logs in, so
1478 * greeters only need to call this method if they want to store something in
1479 * the directory themselves.
1481 * Return value: The path to the shared directory, free with g_free.
1484 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username)
1486 LightDMGreeterPrivate *priv;
1490 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1492 priv = GET_PRIVATE (greeter);
1494 g_return_val_if_fail (priv->connected, NULL);
1496 /* Read until a response */
1497 send_ensure_shared_data_dir (greeter, username);
1498 request = request_new (NULL, NULL, NULL);
1499 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1503 gsize message_length;
1505 message = recv_message (greeter, &message_length, TRUE);
1508 handle_message (greeter, message, message_length);
1510 } while (!request->complete);
1512 data_dir = g_strdup (request->dir);
1513 g_object_unref (request);
1519 lightdm_greeter_init (LightDMGreeter *greeter)
1521 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1524 priv->read_buffer = g_malloc (HEADER_SIZE);
1525 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1527 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
1530 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
1531 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
1534 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
1536 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
1539 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
1540 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
1541 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
1544 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
1548 lightdm_greeter_set_property (GObject *object,
1550 const GValue *value,
1553 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1557 lightdm_greeter_get_property (GObject *object,
1562 LightDMGreeter *self;
1564 self = LIGHTDM_GREETER (object);
1567 case PROP_DEFAULT_SESSION_HINT:
1568 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1570 case PROP_HIDE_USERS_HINT:
1571 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1573 case PROP_SHOW_MANUAL_LOGIN_HINT:
1574 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1576 case PROP_SHOW_REMOTE_LOGIN_HINT:
1577 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1579 case PROP_LOCK_HINT:
1580 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1582 case PROP_HAS_GUEST_ACCOUNT_HINT:
1583 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1585 case PROP_SELECT_USER_HINT:
1586 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1588 case PROP_SELECT_GUEST_HINT:
1589 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1591 case PROP_AUTOLOGIN_USER_HINT:
1592 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1594 case PROP_AUTOLOGIN_GUEST_HINT:
1595 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1597 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1598 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1600 case PROP_AUTHENTICATION_USER:
1601 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1603 case PROP_IN_AUTHENTICATION:
1604 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1606 case PROP_IS_AUTHENTICATED:
1607 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1610 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1616 lightdm_greeter_finalize (GObject *object)
1618 LightDMGreeter *self = LIGHTDM_GREETER (object);
1619 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1621 if (priv->to_server_channel)
1622 g_io_channel_unref (priv->to_server_channel);
1623 if (priv->from_server_channel)
1624 g_io_channel_unref (priv->from_server_channel);
1625 g_free (priv->authentication_user);
1626 g_hash_table_unref (priv->hints);
1628 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1632 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1634 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1636 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1638 object_class->set_property = lightdm_greeter_set_property;
1639 object_class->get_property = lightdm_greeter_get_property;
1640 object_class->finalize = lightdm_greeter_finalize;
1642 g_object_class_install_property (object_class,
1643 PROP_DEFAULT_SESSION_HINT,
1644 g_param_spec_string ("default-session-hint",
1645 "default-session-hint",
1646 "Default session hint",
1648 G_PARAM_READWRITE));
1650 g_object_class_install_property (object_class,
1651 PROP_HIDE_USERS_HINT,
1652 g_param_spec_boolean ("hide-users-hint",
1658 g_object_class_install_property (object_class,
1659 PROP_SHOW_MANUAL_LOGIN_HINT,
1660 g_param_spec_boolean ("show-manual-login-hint",
1661 "show-manual-login-hint",
1662 "Show manual login hint",
1666 g_object_class_install_property (object_class,
1667 PROP_SHOW_REMOTE_LOGIN_HINT,
1668 g_param_spec_boolean ("show-remote-login-hint",
1669 "show-remote-login-hint",
1670 "Show remote login hint",
1674 g_object_class_install_property (object_class,
1676 g_param_spec_boolean ("lock-hint",
1682 g_object_class_install_property (object_class,
1683 PROP_HAS_GUEST_ACCOUNT_HINT,
1684 g_param_spec_boolean ("has-guest-account-hint",
1685 "has-guest-account-hint",
1686 "Has guest account hint",
1690 g_object_class_install_property (object_class,
1691 PROP_SELECT_USER_HINT,
1692 g_param_spec_string ("select-user-hint",
1698 g_object_class_install_property (object_class,
1699 PROP_SELECT_GUEST_HINT,
1700 g_param_spec_boolean ("select-guest-hint",
1701 "select-guest-hint",
1702 "Select guest account hint",
1706 g_object_class_install_property (object_class,
1707 PROP_AUTOLOGIN_USER_HINT,
1708 g_param_spec_string ("autologin-user-hint",
1709 "autologin-user-hint",
1710 "Autologin user hint",
1714 g_object_class_install_property (object_class,
1715 PROP_AUTOLOGIN_GUEST_HINT,
1716 g_param_spec_boolean ("autologin-guest-hint",
1717 "autologin-guest-hint",
1718 "Autologin guest account hint",
1722 g_object_class_install_property (object_class,
1723 PROP_AUTOLOGIN_TIMEOUT_HINT,
1724 g_param_spec_int ("autologin-timeout-hint",
1725 "autologin-timeout-hint",
1726 "Autologin timeout hint",
1730 g_object_class_install_property (object_class,
1731 PROP_AUTHENTICATION_USER,
1732 g_param_spec_string ("authentication-user",
1733 "authentication-user",
1734 "The user being authenticated",
1737 g_object_class_install_property (object_class,
1738 PROP_IN_AUTHENTICATION,
1739 g_param_spec_boolean ("in-authentication",
1740 "in-authentication",
1741 "TRUE if a user is being authenticated",
1744 g_object_class_install_property (object_class,
1745 PROP_IS_AUTHENTICATED,
1746 g_param_spec_boolean ("is-authenticated",
1748 "TRUE if the selected user is authenticated",
1753 * LightDMGreeter::show-prompt:
1754 * @greeter: A #LightDMGreeter
1755 * @text: Prompt text
1756 * @type: Prompt type
1758 * The ::show-prompt signal gets emitted when the greeter should show a
1759 * prompt to the user. The given text should be displayed and an input
1760 * field for the user to provide a response.
1762 * Call lightdm_greeter_respond() with the resultant input or
1763 * lightdm_greeter_cancel_authentication() to abort the authentication.
1765 signals[SHOW_PROMPT] =
1766 g_signal_new ("show-prompt",
1767 G_TYPE_FROM_CLASS (klass),
1769 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1772 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1775 * LightDMGreeter::show-message:
1776 * @greeter: A #LightDMGreeter
1777 * @text: Message text
1778 * @type: Message type
1780 * The ::show-message signal gets emitted when the greeter
1781 * should show a message to the user.
1783 signals[SHOW_MESSAGE] =
1784 g_signal_new ("show-message",
1785 G_TYPE_FROM_CLASS (klass),
1787 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1790 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1793 * LightDMGreeter::authentication-complete:
1794 * @greeter: A #LightDMGreeter
1796 * The ::authentication-complete signal gets emitted when the greeter
1797 * has completed authentication.
1799 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1802 signals[AUTHENTICATION_COMPLETE] =
1803 g_signal_new ("authentication-complete",
1804 G_TYPE_FROM_CLASS (klass),
1806 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1812 * LightDMGreeter::autologin-timer-expired:
1813 * @greeter: A #LightDMGreeter
1815 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1816 * The application should then call lightdm_greeter_login().
1818 signals[AUTOLOGIN_TIMER_EXPIRED] =
1819 g_signal_new ("autologin-timer-expired",
1820 G_TYPE_FROM_CLASS (klass),
1822 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1828 * LightDMGreeter::idle:
1829 * @greeter: A #LightDMGreeter
1831 * The ::idle signal gets emitted when the user has logged in and the
1832 * greeter is no longer needed.
1834 * This signal only matters if the greeter has marked itself as
1835 * resettable using lightdm_greeter_set_resettable().
1838 g_signal_new ("idle",
1839 G_TYPE_FROM_CLASS (klass),
1841 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
1847 * LightDMGreeter::reset:
1848 * @greeter: A #LightDMGreeter
1850 * The ::reset signal gets emitted when the user is returning to a greeter
1851 * that was previously marked idle.
1853 * This signal only matters if the greeter has marked itself as
1854 * resettable using lightdm_greeter_set_resettable().
1857 g_signal_new ("reset",
1858 G_TYPE_FROM_CLASS (klass),
1860 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
1867 request_init (Request *request)
1872 request_finalize (GObject *object)
1874 Request *request = REQUEST (object);
1876 g_free (request->dir);
1877 if (request->cancellable)
1878 g_object_unref (request->cancellable);
1880 G_OBJECT_CLASS (request_parent_class)->finalize (object);
1884 request_class_init (RequestClass *klass)
1886 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1887 object_class->finalize = request_finalize;
1891 request_get_user_data (GAsyncResult *result)
1893 return REQUEST (result)->user_data;
1897 request_get_source_object (GAsyncResult *res)
1903 request_is_tagged (GAsyncResult *res, gpointer source_tag)
1909 request_iface_init (GAsyncResultIface *iface)
1911 iface->get_user_data = request_get_user_data;
1912 iface->get_source_object = request_get_source_object;
1913 iface->is_tagged = request_is_tagged;