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 /* Mapping of username to shared data directories */
79 GHashTable *shared_data_dirs;
81 /* Hints provided by the daemon */
84 /* Timeout source to notify greeter to autologin */
85 guint autologin_timeout;
87 gchar *authentication_user;
88 gboolean in_authentication;
89 gboolean is_authenticated;
90 guint32 authenticate_sequence_number;
91 gboolean cancelling_authentication;
92 } LightDMGreeterPrivate;
94 G_DEFINE_TYPE (LightDMGreeter, lightdm_greeter, G_TYPE_OBJECT);
96 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_GREETER, LightDMGreeterPrivate)
99 #define MAX_MESSAGE_LENGTH 1024
101 /* Messages from the greeter to the server */
104 GREETER_MESSAGE_CONNECT = 0,
105 GREETER_MESSAGE_AUTHENTICATE,
106 GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
107 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
108 GREETER_MESSAGE_START_SESSION,
109 GREETER_MESSAGE_CANCEL_AUTHENTICATION,
110 GREETER_MESSAGE_SET_LANGUAGE,
111 GREETER_MESSAGE_AUTHENTICATE_REMOTE,
112 GREETER_MESSAGE_ENSURE_SHARED_DIR,
115 /* Messages from the server to the greeter */
118 SERVER_MESSAGE_CONNECTED = 0,
119 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
120 SERVER_MESSAGE_END_AUTHENTICATION,
121 SERVER_MESSAGE_SESSION_RESULT,
122 SERVER_MESSAGE_SHARED_DIR_RESULT,
124 SERVER_MESSAGE_RESET,
127 /* Request sent to server */
130 GObject parent_instance;
131 GCancellable *cancellable;
132 GAsyncReadyCallback callback;
140 GObjectClass parent_class;
142 GType request_get_type (void);
143 static void request_iface_init (GAsyncResultIface *iface);
144 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
145 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
148 * lightdm_greeter_new:
150 * Create a new greeter.
152 * Return value: the new #LightDMGreeter
155 lightdm_greeter_new (void)
157 return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
161 * lightdm_greeter_set_resettable:
162 * @greeter: A #LightDMGreeter
163 * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
165 * Set whether the greeter will be reset instead of killed after the user logs in.
166 * This must be called before lightdm_greeter_connect is called.
169 lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
171 LightDMGreeterPrivate *priv;
173 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
175 priv = GET_PRIVATE (greeter);
177 g_return_if_fail (!priv->connected);
178 priv->resettable = resettable;
182 request_new (GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
186 request = g_object_new (request_get_type (), NULL);
188 request->cancellable = g_object_ref (cancellable);
189 request->callback = callback;
190 request->user_data = user_data;
196 request_call_callback (Request *request)
198 if (!request->callback)
201 if (request->cancellable && g_cancellable_is_cancelled (request->cancellable))
208 timed_login_cb (gpointer data)
210 LightDMGreeter *greeter = data;
211 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
213 priv->autologin_timeout = 0;
214 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
226 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
228 if (*offset + 4 >= buffer_length)
230 buffer[*offset] = value >> 24;
231 buffer[*offset+1] = (value >> 16) & 0xFF;
232 buffer[*offset+2] = (value >> 8) & 0xFF;
233 buffer[*offset+3] = value & 0xFF;
238 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
243 length = strlen (value);
244 write_int (buffer, buffer_length, length, offset);
245 if (*offset + length >= buffer_length)
247 memcpy (buffer + *offset, value, length);
252 read_int (guint8 *message, gsize message_length, gsize *offset)
257 if (message_length - *offset < int_length ())
259 g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset);
263 buffer = message + *offset;
264 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
265 *offset += int_length ();
271 read_string (guint8 *message, gsize message_length, gsize *offset)
276 length = read_int (message, message_length, offset);
277 if (message_length - *offset < length)
279 g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset);
280 return g_strdup ("");
283 value = g_malloc (sizeof (gchar) * (length + 1));
284 memcpy (value, message + *offset, length);
285 value[length] = '\0';
292 string_length (const gchar *value)
295 return int_length () + strlen (value);
297 return int_length ();
301 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
303 write_int (buffer, buffer_length, id, offset);
304 write_int (buffer, buffer_length, length, offset);
308 get_message_length (guint8 *message, gsize message_length)
311 return read_int (message, message_length, &offset);
315 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
317 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
319 GError *error = NULL;
320 guint32 stated_length;
322 if (!priv->to_server_channel)
325 /* Double check that we're sending well-formed messages. If we say we're
326 sending more than we do, we end up DOS'ing lightdm as it waits for the
327 rest. If we say we're sending less than we do, we confuse the heck out
328 of lightdm, as it starts reading headers from the middle of our
330 stated_length = HEADER_SIZE + get_message_length (message, message_length);
331 if (stated_length != message_length)
333 g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
337 status = g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, &error);
339 g_warning ("Error writing to daemon: %s", error->message);
340 g_clear_error (&error);
341 if (status != G_IO_STATUS_NORMAL)
344 g_debug ("Wrote %zi bytes to daemon", message_length);
345 g_io_channel_flush (priv->to_server_channel, NULL);
351 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
353 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
355 GString *hint_string;
359 version = read_string (message, message_length, offset);
360 hint_string = g_string_new ("");
361 while (*offset < message_length)
365 name = read_string (message, message_length, offset);
366 value = read_string (message, message_length, offset);
367 g_hash_table_insert (priv->hints, name, value);
368 g_string_append_printf (hint_string, " %s=%s", name, value);
371 priv->connected = TRUE;
372 g_debug ("Connected version=%s%s", version, hint_string->str);
374 g_string_free (hint_string, TRUE);
376 /* Set timeout for default login */
377 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
380 g_debug ("Setting autologin timer for %d seconds", timeout);
381 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
384 /* Notify asynchronous caller */
385 request = g_list_nth_data (priv->connect_requests, 0);
388 request->complete = TRUE;
389 if (request_call_callback (request))
390 request->callback (G_OBJECT (greeter), G_ASYNC_RESULT (request), request->user_data);
391 priv->connect_requests = g_list_remove (priv->connect_requests, request);
392 g_object_unref (request);
397 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
399 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
400 guint32 sequence_number, n_messages, i;
403 sequence_number = read_int (message, message_length, offset);
404 if (sequence_number != priv->authenticate_sequence_number)
406 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
410 if (priv->cancelling_authentication)
412 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
416 /* Update username */
417 username = read_string (message, message_length, offset);
418 if (strcmp (username, "") == 0)
423 g_free (priv->authentication_user);
424 priv->authentication_user = username;
426 g_list_free_full (priv->responses_received, g_free);
427 priv->responses_received = NULL;
428 priv->n_responses_waiting = 0;
430 n_messages = read_int (message, message_length, offset);
431 g_debug ("Prompt user with %d message(s)", n_messages);
433 for (i = 0; i < n_messages; i++)
438 style = read_int (message, message_length, offset);
439 text = read_string (message, message_length, offset);
441 // FIXME: Should stop on prompts?
444 case PAM_PROMPT_ECHO_OFF:
445 priv->n_responses_waiting++;
446 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
448 case PAM_PROMPT_ECHO_ON:
449 priv->n_responses_waiting++;
450 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
453 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
456 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
465 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
467 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
468 guint32 sequence_number, return_code;
471 sequence_number = read_int (message, message_length, offset);
473 if (sequence_number != priv->authenticate_sequence_number)
475 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
479 username = read_string (message, message_length, offset);
480 return_code = read_int (message, message_length, offset);
482 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
484 /* Update username */
485 if (strcmp (username, "") == 0)
490 g_free (priv->authentication_user);
491 priv->authentication_user = username;
493 priv->cancelling_authentication = FALSE;
494 priv->is_authenticated = (return_code == 0);
496 priv->in_authentication = FALSE;
497 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
501 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
503 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
507 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
509 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
510 GString *hint_string;
512 g_hash_table_remove_all (priv->hints);
514 hint_string = g_string_new ("");
515 while (*offset < message_length)
519 name = read_string (message, message_length, offset);
520 value = read_string (message, message_length, offset);
521 g_hash_table_insert (priv->hints, name, value);
522 g_string_append_printf (hint_string, " %s=%s", name, value);
525 g_debug ("Reset%s", hint_string->str);
526 g_string_free (hint_string, TRUE);
528 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
532 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
534 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
537 /* Notify asynchronous caller */
538 request = g_list_nth_data (priv->start_session_requests, 0);
541 request->return_code = read_int (message, message_length, offset);
542 request->complete = TRUE;
543 if (request_call_callback (request))
544 request->callback (G_OBJECT (greeter), G_ASYNC_RESULT (request), request->user_data);
545 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
546 g_object_unref (request);
551 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
553 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
556 /* Notify asynchronous caller */
557 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
560 request->dir = read_string (message, message_length, offset);
561 /* Blank data dir means invalid user */
562 if (g_strcmp0 (request->dir, "") == 0)
564 g_free (request->dir);
567 request->complete = TRUE;
568 if (request_call_callback (request))
569 request->callback (G_OBJECT (greeter), G_ASYNC_RESULT (request), request->user_data);
570 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
571 g_object_unref (request);
576 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
581 id = read_int (message, message_length, &offset);
582 read_int (message, message_length, &offset);
585 case SERVER_MESSAGE_CONNECTED:
586 handle_connected (greeter, message, message_length, &offset);
588 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
589 handle_prompt_authentication (greeter, message, message_length, &offset);
591 case SERVER_MESSAGE_END_AUTHENTICATION:
592 handle_end_authentication (greeter, message, message_length, &offset);
594 case SERVER_MESSAGE_SESSION_RESULT:
595 handle_session_result (greeter, message, message_length, &offset);
597 case SERVER_MESSAGE_SHARED_DIR_RESULT:
598 handle_shared_dir_result (greeter, message, message_length, &offset);
600 case SERVER_MESSAGE_IDLE:
601 handle_idle (greeter, message, message_length, &offset);
603 case SERVER_MESSAGE_RESET:
604 handle_reset (greeter, message, message_length, &offset);
607 g_warning ("Unknown message from server: %d", id);
613 recv_message (LightDMGreeter *greeter, gsize *length, gboolean block)
615 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
616 gsize n_to_read, n_read;
618 GError *error = NULL;
620 if (!priv->from_server_channel)
623 /* Read the header, or the whole message if we already have that */
624 n_to_read = HEADER_SIZE;
625 if (priv->n_read >= HEADER_SIZE)
626 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
631 status = g_io_channel_read_chars (priv->from_server_channel,
632 (gchar *) priv->read_buffer + priv->n_read,
633 n_to_read - priv->n_read,
637 g_warning ("Error reading from server: %s", error->message);
638 g_clear_error (&error);
639 if (status != G_IO_STATUS_NORMAL)
642 g_debug ("Read %zi bytes from daemon", n_read);
644 priv->n_read += n_read;
645 } while (priv->n_read < n_to_read && block);
647 /* Stop if haven't got all the data we want */
648 if (priv->n_read != n_to_read)
651 /* If have header, rerun for content */
652 if (priv->n_read == HEADER_SIZE)
654 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
657 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
658 return recv_message (greeter, length, block);
662 buffer = priv->read_buffer;
663 *length = priv->n_read;
665 priv->read_buffer = g_malloc (priv->n_read);
672 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
674 LightDMGreeter *greeter = data;
676 gsize message_length;
678 /* Read one message and process it */
679 message = recv_message (greeter, &message_length, FALSE);
682 handle_message (greeter, message, message_length);
690 send_connect (LightDMGreeter *greeter, gboolean resettable)
692 guint8 message[MAX_MESSAGE_LENGTH];
695 g_debug ("Connecting to display manager...");
696 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
697 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
698 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset);
700 return send_message (greeter, message, offset);
704 send_start_session (LightDMGreeter *greeter, const gchar *session)
706 guint8 message[MAX_MESSAGE_LENGTH];
710 g_debug ("Starting session %s", session);
712 g_debug ("Starting default session");
714 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
715 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
716 return send_message (greeter, message, offset);
720 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
722 guint8 message[MAX_MESSAGE_LENGTH];
725 g_debug ("Ensuring data directory for user %s", username);
727 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset);
728 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
729 return send_message (greeter, message, offset);
733 * lightdm_greeter_connect:
734 * @greeter: The greeter to connect
735 * @cancellable: (allow-none): A #GCancellable or %NULL.
736 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
737 * @user_data: (allow-none): data to pass to the @callback or %NULL.
739 * Asynchronously connects the greeter to the display manager.
741 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_finish() to get the result of the operation.
743 * See lightdm_greeter_connect_sync() for the synchronous version.
746 lightdm_greeter_connect (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
748 LightDMGreeterPrivate *priv;
751 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
753 priv = GET_PRIVATE (greeter);
755 request = request_new (cancellable, callback, user_data);
756 priv->connect_requests = g_list_append (priv->connect_requests, request);
757 send_connect (greeter, priv->resettable);
761 * lightdm_greeter_connect_finish:
762 * @result: A #GAsyncResult.
763 * @error: return location for a #GError, or %NULL
765 * Finishes an operation started with lightdm_greeter_connect().
767 * Return value: #TRUE if successfully connected
770 lightdm_greeter_connect_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
772 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
773 return REQUEST (result)->complete;
777 * lightdm_greeter_connect_sync:
778 * @greeter: The greeter to connect
779 * @error: return location for a #GError, or %NULL
781 * Connects the greeter to the display manager. Will block until connected.
783 * Return value: #TRUE if successfully connected
786 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
788 LightDMGreeterPrivate *priv;
791 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
793 priv = GET_PRIVATE (greeter);
795 /* Read until we are connected */
796 send_connect (greeter, priv->resettable);
797 request = request_new (NULL, NULL, NULL);
798 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
802 gsize message_length;
804 message = recv_message (greeter, &message_length, TRUE);
807 handle_message (greeter, message, message_length);
809 } while (!request->complete);
811 g_object_unref (request);
813 return request->complete;
817 * lightdm_greeter_get_hint:
818 * @greeter: A #LightDMGreeter
819 * @name: The hint name to query.
823 * Return value: The value for this hint or #NULL if not set.
826 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
828 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
829 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
833 * lightdm_greeter_get_default_session_hint:
834 * @greeter: A #LightDMGreeter
836 * Get the default session to use.
838 * Return value: The session name
841 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
843 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
844 return lightdm_greeter_get_hint (greeter, "default-session");
848 * lightdm_greeter_get_hide_users_hint:
849 * @greeter: A #LightDMGreeter
851 * Check if user accounts should be shown. If this is TRUE then the list of
852 * accounts should be taken from #LightDMUserList and displayed in the greeter
853 * for the user to choose from. Note that this list can be empty and it is
854 * recommended you show a method for the user to enter a username manually.
856 * If this option is shown the greeter should only allow these users to be
857 * chosen for login unless the manual login hint is set.
859 * Return value: #TRUE if the available users should not be shown.
862 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
866 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
867 value = lightdm_greeter_get_hint (greeter, "hide-users");
869 return g_strcmp0 (value, "true") == 0;
873 * lightdm_greeter_get_show_manual_login_hint:
874 * @greeter: A #LightDMGreeter
876 * Check if a manual login option should be shown. If set the GUI
877 * should provide a way for a username to be entered manually.
878 * Without this hint a greeter which is showing a user list can
879 * limit logins to only those users.
881 * Return value: #TRUE if a manual login option should be shown.
884 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
888 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
889 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
891 return g_strcmp0 (value, "true") == 0;
895 * lightdm_greeter_get_show_remote_login_hint:
896 * @greeter: A #LightDMGreeter
898 * Check if a remote login option should be shown. If set the GUI
899 * should provide a way for a user to log into a remote desktop server.
901 * Return value: #TRUE if a remote login option should be shown.
904 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
908 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
909 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
911 return g_strcmp0 (value, "true") == 0;
915 * lightdm_greeter_get_lock_hint:
916 * @greeter: A #LightDMGreeter
918 * Check if the greeter is acting as a lock screen.
920 * Return value: #TRUE if the greeter was triggered by locking the seat.
923 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
927 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
928 value = lightdm_greeter_get_hint (greeter, "lock-screen");
930 return g_strcmp0 (value, "true") == 0;
934 * lightdm_greeter_get_has_guest_account_hint:
935 * @greeter: A #LightDMGreeter
937 * Check if guest sessions are supported.
939 * Return value: #TRUE if guest sessions are supported.
942 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
946 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
947 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
949 return g_strcmp0 (value, "true") == 0;
953 * lightdm_greeter_get_select_user_hint:
954 * @greeter: A #LightDMGreeter
956 * Get the user to select by default.
958 * Return value: A username
961 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
963 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
964 return lightdm_greeter_get_hint (greeter, "select-user");
968 * lightdm_greeter_get_select_guest_hint:
969 * @greeter: A #LightDMGreeter
971 * Check if the guest account should be selected by default.
973 * Return value: #TRUE if the guest account should be selected by default.
976 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
980 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
981 value = lightdm_greeter_get_hint (greeter, "select-guest");
983 return g_strcmp0 (value, "true") == 0;
987 * lightdm_greeter_get_autologin_user_hint:
988 * @greeter: A #LightDMGreeter
990 * Get the user account to automatically logg into when the timer expires.
992 * Return value: The user account to automatically log into.
995 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
997 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
998 return lightdm_greeter_get_hint (greeter, "autologin-user");
1002 * lightdm_greeter_get_autologin_guest_hint:
1003 * @greeter: A #LightDMGreeter
1005 * Check if the guest account should be automatically logged into when the timer expires.
1007 * Return value: #TRUE if the guest account should be automatically logged into.
1010 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1014 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1015 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1017 return g_strcmp0 (value, "true") == 0;
1021 * lightdm_greeter_get_autologin_timeout_hint:
1022 * @greeter: A #LightDMGreeter
1024 * Get the number of seconds to wait before automaitcally logging in.
1026 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1029 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1034 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1035 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1037 timeout = atoi (value);
1045 * lightdm_greeter_cancel_autologin:
1046 * @greeter: A #LightDMGreeter
1048 * Cancel the automatic login.
1051 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1053 LightDMGreeterPrivate *priv;
1055 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1057 priv = GET_PRIVATE (greeter);
1059 if (priv->autologin_timeout)
1060 g_source_remove (priv->autologin_timeout);
1061 priv->autologin_timeout = 0;
1065 * lightdm_greeter_authenticate:
1066 * @greeter: A #LightDMGreeter
1067 * @username: (allow-none): A username or #NULL to prompt for a username.
1069 * Starts the authentication procedure for a user.
1072 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
1074 LightDMGreeterPrivate *priv;
1075 guint8 message[MAX_MESSAGE_LENGTH];
1078 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1080 priv = GET_PRIVATE (greeter);
1082 g_return_if_fail (priv->connected);
1084 priv->cancelling_authentication = FALSE;
1085 priv->authenticate_sequence_number++;
1086 priv->in_authentication = TRUE;
1087 priv->is_authenticated = FALSE;
1088 if (username != priv->authentication_user)
1090 g_free (priv->authentication_user);
1091 priv->authentication_user = g_strdup (username);
1094 g_debug ("Starting authentication for user %s...", username);
1095 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
1096 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1097 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1098 send_message (greeter, message, offset);
1102 * lightdm_greeter_authenticate_as_guest:
1103 * @greeter: A #LightDMGreeter
1105 * Starts the authentication procedure for the guest user.
1108 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
1110 LightDMGreeterPrivate *priv;
1111 guint8 message[MAX_MESSAGE_LENGTH];
1114 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1116 priv = GET_PRIVATE (greeter);
1118 g_return_if_fail (priv->connected);
1120 priv->cancelling_authentication = FALSE;
1121 priv->authenticate_sequence_number++;
1122 priv->in_authentication = TRUE;
1123 priv->is_authenticated = FALSE;
1124 g_free (priv->authentication_user);
1125 priv->authentication_user = NULL;
1127 g_debug ("Starting authentication for guest account...");
1128 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
1129 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1130 send_message (greeter, message, offset);
1134 * lightdm_greeter_authenticate_autologin:
1135 * @greeter: A #LightDMGreeter
1137 * Starts the authentication procedure for the automatic login user.
1140 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
1144 user = lightdm_greeter_get_autologin_user_hint (greeter);
1145 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1146 lightdm_greeter_authenticate_as_guest (greeter);
1148 lightdm_greeter_authenticate (greeter, user);
1152 * lightdm_greeter_authenticate_remote:
1153 * @greeter: A #LightDMGreeter
1154 * @session: The name of a remote session
1155 * @username: (allow-none): A username of #NULL to prompt for a username.
1157 * Start authentication for a remote session type.
1160 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
1162 LightDMGreeterPrivate *priv;
1163 guint8 message[MAX_MESSAGE_LENGTH];
1166 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1168 priv = GET_PRIVATE (greeter);
1170 g_return_if_fail (priv->connected);
1172 priv->cancelling_authentication = FALSE;
1173 priv->authenticate_sequence_number++;
1174 priv->in_authentication = TRUE;
1175 priv->is_authenticated = FALSE;
1176 g_free (priv->authentication_user);
1177 priv->authentication_user = NULL;
1180 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1182 g_debug ("Starting authentication for remote session %s...", session);
1183 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
1184 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1185 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1186 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1187 send_message (greeter, message, offset);
1191 * lightdm_greeter_respond:
1192 * @greeter: A #LightDMGreeter
1193 * @response: Response to a prompt
1195 * Provide response to a prompt. May be one in a series.
1198 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
1200 LightDMGreeterPrivate *priv;
1201 guint8 message[MAX_MESSAGE_LENGTH];
1204 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1205 g_return_if_fail (response != NULL);
1207 priv = GET_PRIVATE (greeter);
1209 g_return_if_fail (priv->connected);
1210 g_return_if_fail (priv->n_responses_waiting > 0);
1212 priv->n_responses_waiting--;
1213 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1215 if (priv->n_responses_waiting == 0)
1220 g_debug ("Providing response to display manager");
1222 msg_length = int_length ();
1223 for (iter = priv->responses_received; iter; iter = iter->next)
1224 msg_length += string_length ((gchar *)iter->data);
1226 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
1227 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
1228 for (iter = priv->responses_received; iter; iter = iter->next)
1229 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
1230 send_message (greeter, message, offset);
1232 g_list_free_full (priv->responses_received, g_free);
1233 priv->responses_received = NULL;
1238 * lightdm_greeter_cancel_authentication:
1239 * @greeter: A #LightDMGreeter
1241 * Cancel the current user authentication.
1244 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
1246 LightDMGreeterPrivate *priv;
1247 guint8 message[MAX_MESSAGE_LENGTH];
1250 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1252 priv = GET_PRIVATE (greeter);
1254 g_return_if_fail (priv->connected);
1256 priv->cancelling_authentication = TRUE;
1257 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1258 send_message (greeter, message, offset);
1262 * lightdm_greeter_get_in_authentication:
1263 * @greeter: A #LightDMGreeter
1265 * Checks if the greeter is in the process of authenticating.
1267 * Return value: #TRUE if the greeter is authenticating a user.
1270 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1272 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1273 return GET_PRIVATE (greeter)->in_authentication;
1277 * lightdm_greeter_get_is_authenticated:
1278 * @greeter: A #LightDMGreeter
1280 * Checks if the greeter has successfully authenticated.
1282 * Return value: #TRUE if the greeter is authenticated for login.
1285 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1287 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1288 return GET_PRIVATE (greeter)->is_authenticated;
1292 * lightdm_greeter_get_authentication_user:
1293 * @greeter: A #LightDMGreeter
1295 * Get the user that is being authenticated.
1297 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1300 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1302 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1303 return GET_PRIVATE (greeter)->authentication_user;
1307 * lightdm_greeter_set_language:
1308 * @greeter: A #LightDMGreeter
1309 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1311 * Set the language for the currently authenticated user.
1314 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1316 LightDMGreeterPrivate *priv;
1317 guint8 message[MAX_MESSAGE_LENGTH];
1320 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1322 priv = GET_PRIVATE (greeter);
1324 g_return_if_fail (priv->connected);
1326 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1327 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1328 send_message (greeter, message, offset);
1332 * lightdm_greeter_start_session:
1333 * @greeter: A #LightDMGreeter
1334 * @session: (allow-none): The session to log into or #NULL to use the default.
1335 * @cancellable: (allow-none): A #GCancellable or %NULL.
1336 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1337 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1339 * Asynchronously start a session for the authenticated user.
1341 * 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.
1343 * See lightdm_greeter_start_session_sync() for the synchronous version.
1346 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1348 LightDMGreeterPrivate *priv;
1351 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1353 priv = GET_PRIVATE (greeter);
1355 send_start_session (greeter, session);
1356 request = request_new (cancellable, callback, user_data);
1357 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1361 * lightdm_greeter_start_session_finish:
1362 * @greeter: A #LightDMGreeter
1363 * @result: A #GAsyncResult.
1364 * @error: return location for a #GError, or %NULL
1366 * Start a session for the authenticated user.
1368 * Return value: TRUE if the session was started.
1371 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1373 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1374 return REQUEST (result)->return_code == 0;
1378 * lightdm_greeter_start_session_sync:
1379 * @greeter: A #LightDMGreeter
1380 * @session: (allow-none): The session to log into or #NULL to use the default.
1381 * @error: return location for a #GError, or %NULL
1383 * Start a session for the authenticated user.
1385 * Return value: TRUE if the session was started.
1388 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1390 LightDMGreeterPrivate *priv;
1392 guint32 return_code;
1394 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1396 priv = GET_PRIVATE (greeter);
1398 g_return_val_if_fail (priv->connected, FALSE);
1399 g_return_val_if_fail (priv->is_authenticated, FALSE);
1401 /* Read until the session is started */
1402 send_start_session (greeter, session);
1403 request = request_new (NULL, NULL, NULL);
1404 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1408 gsize message_length;
1410 message = recv_message (greeter, &message_length, TRUE);
1413 handle_message (greeter, message, message_length);
1415 } while (!request->complete);
1417 return_code = request->return_code;
1418 g_object_unref (request);
1420 return return_code == 0;
1424 * lightdm_greeter_ensure_shared_data_dir:
1425 * @greeter: A #LightDMGreeter
1426 * @username: A username
1427 * @cancellable: (allow-none): A #GCancellable or %NULL.
1428 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1429 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1431 * Ensure that a shared data dir for the given user is available. Both the
1432 * greeter user and @username will have write access to that folder. The
1433 * intention is that larger pieces of shared data would be stored there (files
1434 * that the greeter creates but wants to give to a user -- like camera
1435 * photos -- or files that the user creates but wants the greeter to
1436 * see -- like contact avatars).
1438 * LightDM will automatically create these if the user actually logs in, so
1439 * greeters only need to call this method if they want to store something in
1440 * the directory themselves.
1443 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1445 LightDMGreeterPrivate *priv;
1448 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1450 priv = GET_PRIVATE (greeter);
1452 send_ensure_shared_data_dir (greeter, username);
1453 request = request_new (cancellable, callback, user_data);
1454 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1458 * lightdm_greeter_ensure_shared_data_dir_finish:
1459 * @result: A #GAsyncResult.
1460 * @greeter: A #LightDMGreeter
1463 * Return value: The path to the shared directory, free with g_free.
1466 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result)
1468 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1469 return g_strdup (REQUEST (result)->dir);
1473 * lightdm_greeter_ensure_shared_data_dir_sync:
1474 * @greeter: A #LightDMGreeter
1475 * @username: A username
1477 * Ensure that a shared data dir for the given user is available. Both the
1478 * greeter user and @username will have write access to that folder. The
1479 * intention is that larger pieces of shared data would be stored there (files
1480 * that the greeter creates but wants to give to a user -- like camera
1481 * photos -- or files that the user creates but wants the greeter to
1482 * see -- like contact avatars).
1484 * LightDM will automatically create these if the user actually logs in, so
1485 * greeters only need to call this method if they want to store something in
1486 * the directory themselves.
1488 * Return value: The path to the shared directory, free with g_free.
1491 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username)
1493 LightDMGreeterPrivate *priv;
1497 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1499 priv = GET_PRIVATE (greeter);
1501 g_return_val_if_fail (priv->connected, NULL);
1503 /* Read until a response */
1504 send_ensure_shared_data_dir (greeter, username);
1505 request = request_new (NULL, NULL, NULL);
1506 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1510 gsize message_length;
1512 message = recv_message (greeter, &message_length, TRUE);
1515 handle_message (greeter, message, message_length);
1517 } while (!request->complete);
1519 data_dir = g_strdup (request->dir);
1520 g_object_unref (request);
1526 lightdm_greeter_init (LightDMGreeter *greeter)
1528 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1531 priv->read_buffer = g_malloc (HEADER_SIZE);
1532 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1534 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
1537 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
1538 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
1541 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
1543 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
1546 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
1547 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
1548 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
1551 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
1555 lightdm_greeter_set_property (GObject *object,
1557 const GValue *value,
1560 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1564 lightdm_greeter_get_property (GObject *object,
1569 LightDMGreeter *self;
1571 self = LIGHTDM_GREETER (object);
1574 case PROP_DEFAULT_SESSION_HINT:
1575 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1577 case PROP_HIDE_USERS_HINT:
1578 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1580 case PROP_SHOW_MANUAL_LOGIN_HINT:
1581 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1583 case PROP_SHOW_REMOTE_LOGIN_HINT:
1584 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1586 case PROP_LOCK_HINT:
1587 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1589 case PROP_HAS_GUEST_ACCOUNT_HINT:
1590 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1592 case PROP_SELECT_USER_HINT:
1593 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1595 case PROP_SELECT_GUEST_HINT:
1596 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1598 case PROP_AUTOLOGIN_USER_HINT:
1599 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1601 case PROP_AUTOLOGIN_GUEST_HINT:
1602 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1604 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1605 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1607 case PROP_AUTHENTICATION_USER:
1608 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1610 case PROP_IN_AUTHENTICATION:
1611 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1613 case PROP_IS_AUTHENTICATED:
1614 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1617 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1623 lightdm_greeter_finalize (GObject *object)
1625 LightDMGreeter *self = LIGHTDM_GREETER (object);
1626 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1628 if (priv->to_server_channel)
1629 g_io_channel_unref (priv->to_server_channel);
1630 if (priv->from_server_channel)
1631 g_io_channel_unref (priv->from_server_channel);
1632 g_free (priv->authentication_user);
1633 g_hash_table_unref (priv->hints);
1635 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1639 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1641 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1643 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1645 object_class->set_property = lightdm_greeter_set_property;
1646 object_class->get_property = lightdm_greeter_get_property;
1647 object_class->finalize = lightdm_greeter_finalize;
1649 g_object_class_install_property (object_class,
1650 PROP_DEFAULT_SESSION_HINT,
1651 g_param_spec_string ("default-session-hint",
1652 "default-session-hint",
1653 "Default session hint",
1655 G_PARAM_READWRITE));
1657 g_object_class_install_property (object_class,
1658 PROP_HIDE_USERS_HINT,
1659 g_param_spec_boolean ("hide-users-hint",
1665 g_object_class_install_property (object_class,
1666 PROP_SHOW_MANUAL_LOGIN_HINT,
1667 g_param_spec_boolean ("show-manual-login-hint",
1668 "show-manual-login-hint",
1669 "Show manual login hint",
1673 g_object_class_install_property (object_class,
1674 PROP_SHOW_REMOTE_LOGIN_HINT,
1675 g_param_spec_boolean ("show-remote-login-hint",
1676 "show-remote-login-hint",
1677 "Show remote login hint",
1681 g_object_class_install_property (object_class,
1683 g_param_spec_boolean ("lock-hint",
1689 g_object_class_install_property (object_class,
1690 PROP_HAS_GUEST_ACCOUNT_HINT,
1691 g_param_spec_boolean ("has-guest-account-hint",
1692 "has-guest-account-hint",
1693 "Has guest account hint",
1697 g_object_class_install_property (object_class,
1698 PROP_SELECT_USER_HINT,
1699 g_param_spec_string ("select-user-hint",
1705 g_object_class_install_property (object_class,
1706 PROP_SELECT_GUEST_HINT,
1707 g_param_spec_boolean ("select-guest-hint",
1708 "select-guest-hint",
1709 "Select guest account hint",
1713 g_object_class_install_property (object_class,
1714 PROP_AUTOLOGIN_USER_HINT,
1715 g_param_spec_string ("autologin-user-hint",
1716 "autologin-user-hint",
1717 "Autologin user hint",
1721 g_object_class_install_property (object_class,
1722 PROP_AUTOLOGIN_GUEST_HINT,
1723 g_param_spec_boolean ("autologin-guest-hint",
1724 "autologin-guest-hint",
1725 "Autologin guest account hint",
1729 g_object_class_install_property (object_class,
1730 PROP_AUTOLOGIN_TIMEOUT_HINT,
1731 g_param_spec_int ("autologin-timeout-hint",
1732 "autologin-timeout-hint",
1733 "Autologin timeout hint",
1737 g_object_class_install_property (object_class,
1738 PROP_AUTHENTICATION_USER,
1739 g_param_spec_string ("authentication-user",
1740 "authentication-user",
1741 "The user being authenticated",
1744 g_object_class_install_property (object_class,
1745 PROP_IN_AUTHENTICATION,
1746 g_param_spec_boolean ("in-authentication",
1747 "in-authentication",
1748 "TRUE if a user is being authenticated",
1751 g_object_class_install_property (object_class,
1752 PROP_IS_AUTHENTICATED,
1753 g_param_spec_boolean ("is-authenticated",
1755 "TRUE if the selected user is authenticated",
1760 * LightDMGreeter::show-prompt:
1761 * @greeter: A #LightDMGreeter
1762 * @text: Prompt text
1763 * @type: Prompt type
1765 * The ::show-prompt signal gets emitted when the greeter should show a
1766 * prompt to the user. The given text should be displayed and an input
1767 * field for the user to provide a response.
1769 * Call lightdm_greeter_respond() with the resultant input or
1770 * lightdm_greeter_cancel_authentication() to abort the authentication.
1772 signals[SHOW_PROMPT] =
1773 g_signal_new ("show-prompt",
1774 G_TYPE_FROM_CLASS (klass),
1776 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1779 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1782 * LightDMGreeter::show-message:
1783 * @greeter: A #LightDMGreeter
1784 * @text: Message text
1785 * @type: Message type
1787 * The ::show-message signal gets emitted when the greeter
1788 * should show a message to the user.
1790 signals[SHOW_MESSAGE] =
1791 g_signal_new ("show-message",
1792 G_TYPE_FROM_CLASS (klass),
1794 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1797 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1800 * LightDMGreeter::authentication-complete:
1801 * @greeter: A #LightDMGreeter
1803 * The ::authentication-complete signal gets emitted when the greeter
1804 * has completed authentication.
1806 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1809 signals[AUTHENTICATION_COMPLETE] =
1810 g_signal_new ("authentication-complete",
1811 G_TYPE_FROM_CLASS (klass),
1813 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1819 * LightDMGreeter::autologin-timer-expired:
1820 * @greeter: A #LightDMGreeter
1822 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1823 * The application should then call lightdm_greeter_login().
1825 signals[AUTOLOGIN_TIMER_EXPIRED] =
1826 g_signal_new ("autologin-timer-expired",
1827 G_TYPE_FROM_CLASS (klass),
1829 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1835 * LightDMGreeter::idle:
1836 * @greeter: A #LightDMGreeter
1838 * The ::idle signal gets emitted when the user has logged in and the
1839 * greeter is no longer needed.
1841 * This signal only matters if the greeter has marked itself as
1842 * resettable using lightdm_greeter_set_resettable().
1845 g_signal_new ("idle",
1846 G_TYPE_FROM_CLASS (klass),
1848 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
1854 * LightDMGreeter::reset:
1855 * @greeter: A #LightDMGreeter
1857 * The ::reset signal gets emitted when the user is returning to a greeter
1858 * that was previously marked idle.
1860 * This signal only matters if the greeter has marked itself as
1861 * resettable using lightdm_greeter_set_resettable().
1864 g_signal_new ("reset",
1865 G_TYPE_FROM_CLASS (klass),
1867 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
1874 request_init (Request *request)
1879 request_finalize (GObject *object)
1881 Request *request = REQUEST (object);
1883 g_free (request->dir);
1884 if (request->cancellable)
1885 g_object_unref (request->cancellable);
1887 G_OBJECT_CLASS (request_parent_class)->finalize (object);
1891 request_class_init (RequestClass *klass)
1893 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1894 object_class->finalize = request_finalize;
1898 request_get_user_data (GAsyncResult *result)
1900 return REQUEST (result)->user_data;
1904 request_get_source_object (GAsyncResult *res)
1910 request_is_tagged (GAsyncResult *res, gpointer source_tag)
1916 request_iface_init (GAsyncResultIface *iface)
1918 iface->get_user_data = request_get_user_data;
1919 iface->get_source_object = request_get_source_object;
1920 iface->is_tagged = request_is_tagged;