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)
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);
320 GError *error = NULL;
321 guint32 stated_length;
323 if (!priv->to_server_channel)
326 /* Double check that we're sending well-formed messages. If we say we're
327 sending more than we do, we end up DOS'ing lightdm as it waits for the
328 rest. If we say we're sending less than we do, we confuse the heck out
329 of lightdm, as it starts reading headers from the middle of our
331 stated_length = HEADER_SIZE + get_message_length (message, message_length);
332 if (stated_length != message_length)
334 g_warning ("Refusing to write malformed packet to daemon: declared size is %u, but actual size is %zu", stated_length, message_length);
338 data = (gchar *) message;
339 data_length = message_length;
340 while (data_length > 0)
345 status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &error);
347 g_warning ("Error writing to daemon: %s", error->message);
348 g_clear_error (&error);
349 if (status != G_IO_STATUS_NORMAL)
351 data_length -= n_written;
355 g_debug ("Wrote %zi bytes to daemon", message_length);
356 g_io_channel_flush (priv->to_server_channel, &error);
358 g_warning ("Failed to flush data to daemon: %s", error->message);
359 g_clear_error (&error);
365 handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
367 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
369 GString *hint_string;
373 version = read_string (message, message_length, offset);
374 hint_string = g_string_new ("");
375 while (*offset < message_length)
379 name = read_string (message, message_length, offset);
380 value = read_string (message, message_length, offset);
381 g_hash_table_insert (priv->hints, name, value);
382 g_string_append_printf (hint_string, " %s=%s", name, value);
385 priv->connected = TRUE;
386 g_debug ("Connected version=%s%s", version, hint_string->str);
388 g_string_free (hint_string, TRUE);
390 /* Set timeout for default login */
391 timeout = lightdm_greeter_get_autologin_timeout_hint (greeter);
394 g_debug ("Setting autologin timer for %d seconds", timeout);
395 priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
398 /* Notify asynchronous caller */
399 request = g_list_nth_data (priv->connect_requests, 0);
402 request_complete (request, G_OBJECT (greeter));
403 priv->connect_requests = g_list_remove (priv->connect_requests, request);
404 g_object_unref (request);
409 handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
411 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
412 guint32 sequence_number, n_messages, i;
415 sequence_number = read_int (message, message_length, offset);
416 if (sequence_number != priv->authenticate_sequence_number)
418 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
422 if (priv->cancelling_authentication)
424 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
428 /* Update username */
429 username = read_string (message, message_length, offset);
430 if (strcmp (username, "") == 0)
435 g_free (priv->authentication_user);
436 priv->authentication_user = username;
438 g_list_free_full (priv->responses_received, g_free);
439 priv->responses_received = NULL;
440 priv->n_responses_waiting = 0;
442 n_messages = read_int (message, message_length, offset);
443 g_debug ("Prompt user with %d message(s)", n_messages);
445 for (i = 0; i < n_messages; i++)
450 style = read_int (message, message_length, offset);
451 text = read_string (message, message_length, offset);
453 // FIXME: Should stop on prompts?
456 case PAM_PROMPT_ECHO_OFF:
457 priv->n_responses_waiting++;
458 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
460 case PAM_PROMPT_ECHO_ON:
461 priv->n_responses_waiting++;
462 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
465 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_ERROR);
468 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, text, LIGHTDM_MESSAGE_TYPE_INFO);
477 handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
479 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
480 guint32 sequence_number, return_code;
483 sequence_number = read_int (message, message_length, offset);
485 if (sequence_number != priv->authenticate_sequence_number)
487 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
491 username = read_string (message, message_length, offset);
492 return_code = read_int (message, message_length, offset);
494 g_debug ("Authentication complete for user %s with return code %d", username, return_code);
496 /* Update username */
497 if (strcmp (username, "") == 0)
502 g_free (priv->authentication_user);
503 priv->authentication_user = username;
505 priv->cancelling_authentication = FALSE;
506 priv->is_authenticated = (return_code == 0);
508 priv->in_authentication = FALSE;
509 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
513 handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
515 g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
519 handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
521 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
522 GString *hint_string;
524 g_hash_table_remove_all (priv->hints);
526 hint_string = g_string_new ("");
527 while (*offset < message_length)
531 name = read_string (message, message_length, offset);
532 value = read_string (message, message_length, offset);
533 g_hash_table_insert (priv->hints, name, value);
534 g_string_append_printf (hint_string, " %s=%s", name, value);
537 g_debug ("Reset%s", hint_string->str);
538 g_string_free (hint_string, TRUE);
540 g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
544 handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
546 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
549 /* Notify asynchronous caller */
550 request = g_list_nth_data (priv->start_session_requests, 0);
553 request->return_code = read_int (message, message_length, offset);
554 request_complete (request, G_OBJECT (greeter));
555 priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
556 g_object_unref (request);
561 handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
563 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
566 /* Notify asynchronous caller */
567 request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
570 request->dir = read_string (message, message_length, offset);
571 /* Blank data dir means invalid user */
572 if (g_strcmp0 (request->dir, "") == 0)
574 g_free (request->dir);
577 request_complete (request, G_OBJECT (greeter));
578 priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
579 g_object_unref (request);
584 handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
589 id = read_int (message, message_length, &offset);
590 read_int (message, message_length, &offset);
593 case SERVER_MESSAGE_CONNECTED:
594 handle_connected (greeter, message, message_length, &offset);
596 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
597 handle_prompt_authentication (greeter, message, message_length, &offset);
599 case SERVER_MESSAGE_END_AUTHENTICATION:
600 handle_end_authentication (greeter, message, message_length, &offset);
602 case SERVER_MESSAGE_SESSION_RESULT:
603 handle_session_result (greeter, message, message_length, &offset);
605 case SERVER_MESSAGE_SHARED_DIR_RESULT:
606 handle_shared_dir_result (greeter, message, message_length, &offset);
608 case SERVER_MESSAGE_IDLE:
609 handle_idle (greeter, message, message_length, &offset);
611 case SERVER_MESSAGE_RESET:
612 handle_reset (greeter, message, message_length, &offset);
615 g_warning ("Unknown message from server: %d", id);
621 recv_message (LightDMGreeter *greeter, gsize *length, gboolean block)
623 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
624 gsize n_to_read, n_read;
626 GError *error = NULL;
628 if (!priv->from_server_channel)
631 /* Read the header, or the whole message if we already have that */
632 n_to_read = HEADER_SIZE;
633 if (priv->n_read >= HEADER_SIZE)
634 n_to_read += get_message_length (priv->read_buffer, priv->n_read);
639 status = g_io_channel_read_chars (priv->from_server_channel,
640 (gchar *) priv->read_buffer + priv->n_read,
641 n_to_read - priv->n_read,
645 g_warning ("Error reading from server: %s", error->message);
646 g_clear_error (&error);
647 if (status != G_IO_STATUS_NORMAL)
650 g_debug ("Read %zi bytes from daemon", n_read);
652 priv->n_read += n_read;
653 } while (priv->n_read < n_to_read && block);
655 /* Stop if haven't got all the data we want */
656 if (priv->n_read != n_to_read)
659 /* If have header, rerun for content */
660 if (priv->n_read == HEADER_SIZE)
662 n_to_read = get_message_length (priv->read_buffer, priv->n_read);
665 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
666 return recv_message (greeter, length, block);
670 buffer = priv->read_buffer;
671 *length = priv->n_read;
673 priv->read_buffer = g_malloc (priv->n_read);
680 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
682 LightDMGreeter *greeter = data;
684 gsize message_length;
686 /* Read one message and process it */
687 message = recv_message (greeter, &message_length, FALSE);
690 handle_message (greeter, message, message_length);
698 send_connect (LightDMGreeter *greeter, gboolean resettable)
700 guint8 message[MAX_MESSAGE_LENGTH];
703 g_debug ("Connecting to display manager...");
704 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
705 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
706 write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset);
708 return send_message (greeter, message, offset);
712 send_start_session (LightDMGreeter *greeter, const gchar *session)
714 guint8 message[MAX_MESSAGE_LENGTH];
718 g_debug ("Starting session %s", session);
720 g_debug ("Starting default session");
722 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
723 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
724 return send_message (greeter, message, offset);
728 send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
730 guint8 message[MAX_MESSAGE_LENGTH];
733 g_debug ("Ensuring data directory for user %s", username);
735 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset);
736 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
737 return send_message (greeter, message, offset);
741 * lightdm_greeter_connect_to_daemon:
742 * @greeter: The greeter to connect
743 * @cancellable: (allow-none): A #GCancellable or %NULL.
744 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
745 * @user_data: (allow-none): data to pass to the @callback or %NULL.
747 * Asynchronously connects the greeter to the display manager.
749 * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_to_daemon_finish() to get the result of the operation.
751 * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
754 lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
756 LightDMGreeterPrivate *priv;
759 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
761 priv = GET_PRIVATE (greeter);
763 request = request_new (cancellable, callback, user_data);
764 priv->connect_requests = g_list_append (priv->connect_requests, request);
765 send_connect (greeter, priv->resettable);
769 * lightdm_greeter_connect_to_daemon_finish:
770 * @result: A #GAsyncResult.
771 * @error: return location for a #GError, or %NULL
773 * Finishes an operation started with lightdm_greeter_connect_to_daemon().
775 * Return value: #TRUE if successfully connected
778 lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
780 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
781 return REQUEST (result)->complete;
785 * lightdm_greeter_connect_to_daemon_sync:
786 * @greeter: The greeter to connect
787 * @error: return location for a #GError, or %NULL
789 * Connects the greeter to the display manager. Will block until connected.
791 * Return value: #TRUE if successfully connected
794 lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
796 LightDMGreeterPrivate *priv;
799 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
801 priv = GET_PRIVATE (greeter);
803 /* Read until we are connected */
804 send_connect (greeter, priv->resettable);
805 request = request_new (NULL, NULL, NULL);
806 priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
810 gsize message_length;
812 message = recv_message (greeter, &message_length, TRUE);
815 handle_message (greeter, message, message_length);
817 } while (!request->complete);
819 g_object_unref (request);
821 return request->complete;
825 * lightdm_greeter_connect_sync:
826 * @greeter: The greeter to connect
827 * @error: return location for a #GError, or %NULL
829 * Connects the greeter to the display manager. Will block until connected.
831 * Return value: #TRUE if successfully connected
833 * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
836 lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
838 return lightdm_greeter_connect_to_daemon_sync (greeter, error);
842 * lightdm_greeter_get_hint:
843 * @greeter: A #LightDMGreeter
844 * @name: The hint name to query.
848 * Return value: The value for this hint or #NULL if not set.
851 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
853 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
854 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
858 * lightdm_greeter_get_default_session_hint:
859 * @greeter: A #LightDMGreeter
861 * Get the default session to use.
863 * Return value: The session name
866 lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
868 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
869 return lightdm_greeter_get_hint (greeter, "default-session");
873 * lightdm_greeter_get_hide_users_hint:
874 * @greeter: A #LightDMGreeter
876 * Check if user accounts should be shown. If this is TRUE then the list of
877 * accounts should be taken from #LightDMUserList and displayed in the greeter
878 * for the user to choose from. Note that this list can be empty and it is
879 * recommended you show a method for the user to enter a username manually.
881 * If this option is shown the greeter should only allow these users to be
882 * chosen for login unless the manual login hint is set.
884 * Return value: #TRUE if the available users should not be shown.
887 lightdm_greeter_get_hide_users_hint (LightDMGreeter *greeter)
891 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
892 value = lightdm_greeter_get_hint (greeter, "hide-users");
894 return g_strcmp0 (value, "true") == 0;
898 * lightdm_greeter_get_show_manual_login_hint:
899 * @greeter: A #LightDMGreeter
901 * Check if a manual login option should be shown. If set the GUI
902 * should provide a way for a username to be entered manually.
903 * Without this hint a greeter which is showing a user list can
904 * limit logins to only those users.
906 * Return value: #TRUE if a manual login option should be shown.
909 lightdm_greeter_get_show_manual_login_hint (LightDMGreeter *greeter)
913 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
914 value = lightdm_greeter_get_hint (greeter, "show-manual-login");
916 return g_strcmp0 (value, "true") == 0;
920 * lightdm_greeter_get_show_remote_login_hint:
921 * @greeter: A #LightDMGreeter
923 * Check if a remote login option should be shown. If set the GUI
924 * should provide a way for a user to log into a remote desktop server.
926 * Return value: #TRUE if a remote login option should be shown.
929 lightdm_greeter_get_show_remote_login_hint (LightDMGreeter *greeter)
933 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
934 value = lightdm_greeter_get_hint (greeter, "show-remote-login");
936 return g_strcmp0 (value, "true") == 0;
940 * lightdm_greeter_get_lock_hint:
941 * @greeter: A #LightDMGreeter
943 * Check if the greeter is acting as a lock screen.
945 * Return value: #TRUE if the greeter was triggered by locking the seat.
948 lightdm_greeter_get_lock_hint (LightDMGreeter *greeter)
952 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
953 value = lightdm_greeter_get_hint (greeter, "lock-screen");
955 return g_strcmp0 (value, "true") == 0;
959 * lightdm_greeter_get_has_guest_account_hint:
960 * @greeter: A #LightDMGreeter
962 * Check if guest sessions are supported.
964 * Return value: #TRUE if guest sessions are supported.
967 lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
971 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
972 value = lightdm_greeter_get_hint (greeter, "has-guest-account");
974 return g_strcmp0 (value, "true") == 0;
978 * lightdm_greeter_get_select_user_hint:
979 * @greeter: A #LightDMGreeter
981 * Get the user to select by default.
983 * Return value: A username
986 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
988 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
989 return lightdm_greeter_get_hint (greeter, "select-user");
993 * lightdm_greeter_get_select_guest_hint:
994 * @greeter: A #LightDMGreeter
996 * Check if the guest account should be selected by default.
998 * Return value: #TRUE if the guest account should be selected by default.
1001 lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
1005 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1006 value = lightdm_greeter_get_hint (greeter, "select-guest");
1008 return g_strcmp0 (value, "true") == 0;
1012 * lightdm_greeter_get_autologin_user_hint:
1013 * @greeter: A #LightDMGreeter
1015 * Get the user account to automatically logg into when the timer expires.
1017 * Return value: The user account to automatically log into.
1020 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
1022 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1023 return lightdm_greeter_get_hint (greeter, "autologin-user");
1027 * lightdm_greeter_get_autologin_guest_hint:
1028 * @greeter: A #LightDMGreeter
1030 * Check if the guest account should be automatically logged into when the timer expires.
1032 * Return value: #TRUE if the guest account should be automatically logged into.
1035 lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
1039 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1040 value = lightdm_greeter_get_hint (greeter, "autologin-guest");
1042 return g_strcmp0 (value, "true") == 0;
1046 * lightdm_greeter_get_autologin_timeout_hint:
1047 * @greeter: A #LightDMGreeter
1049 * Get the number of seconds to wait before automaitcally logging in.
1051 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1054 lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter)
1059 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1060 value = lightdm_greeter_get_hint (greeter, "autologin-timeout");
1062 timeout = atoi (value);
1070 * lightdm_greeter_cancel_autologin:
1071 * @greeter: A #LightDMGreeter
1073 * Cancel the automatic login.
1076 lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
1078 LightDMGreeterPrivate *priv;
1080 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1082 priv = GET_PRIVATE (greeter);
1084 if (priv->autologin_timeout)
1085 g_source_remove (priv->autologin_timeout);
1086 priv->autologin_timeout = 0;
1090 * lightdm_greeter_authenticate:
1091 * @greeter: A #LightDMGreeter
1092 * @username: (allow-none): A username or #NULL to prompt for a username.
1094 * Starts the authentication procedure for a user.
1097 lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
1099 LightDMGreeterPrivate *priv;
1100 guint8 message[MAX_MESSAGE_LENGTH];
1103 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1105 priv = GET_PRIVATE (greeter);
1107 g_return_if_fail (priv->connected);
1109 priv->cancelling_authentication = FALSE;
1110 priv->authenticate_sequence_number++;
1111 priv->in_authentication = TRUE;
1112 priv->is_authenticated = FALSE;
1113 if (username != priv->authentication_user)
1115 g_free (priv->authentication_user);
1116 priv->authentication_user = g_strdup (username);
1119 g_debug ("Starting authentication for user %s...", username);
1120 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE, int_length () + string_length (username), &offset);
1121 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1122 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1123 send_message (greeter, message, offset);
1127 * lightdm_greeter_authenticate_as_guest:
1128 * @greeter: A #LightDMGreeter
1130 * Starts the authentication procedure for the guest user.
1133 lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
1135 LightDMGreeterPrivate *priv;
1136 guint8 message[MAX_MESSAGE_LENGTH];
1139 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1141 priv = GET_PRIVATE (greeter);
1143 g_return_if_fail (priv->connected);
1145 priv->cancelling_authentication = FALSE;
1146 priv->authenticate_sequence_number++;
1147 priv->in_authentication = TRUE;
1148 priv->is_authenticated = FALSE;
1149 g_free (priv->authentication_user);
1150 priv->authentication_user = NULL;
1152 g_debug ("Starting authentication for guest account...");
1153 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, int_length (), &offset);
1154 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1155 send_message (greeter, message, offset);
1159 * lightdm_greeter_authenticate_autologin:
1160 * @greeter: A #LightDMGreeter
1162 * Starts the authentication procedure for the automatic login user.
1165 lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
1169 user = lightdm_greeter_get_autologin_user_hint (greeter);
1170 if (lightdm_greeter_get_autologin_guest_hint (greeter))
1171 lightdm_greeter_authenticate_as_guest (greeter);
1173 lightdm_greeter_authenticate (greeter, user);
1177 * lightdm_greeter_authenticate_remote:
1178 * @greeter: A #LightDMGreeter
1179 * @session: The name of a remote session
1180 * @username: (allow-none): A username of #NULL to prompt for a username.
1182 * Start authentication for a remote session type.
1185 lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
1187 LightDMGreeterPrivate *priv;
1188 guint8 message[MAX_MESSAGE_LENGTH];
1191 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1193 priv = GET_PRIVATE (greeter);
1195 g_return_if_fail (priv->connected);
1197 priv->cancelling_authentication = FALSE;
1198 priv->authenticate_sequence_number++;
1199 priv->in_authentication = TRUE;
1200 priv->is_authenticated = FALSE;
1201 g_free (priv->authentication_user);
1202 priv->authentication_user = NULL;
1205 g_debug ("Starting authentication for remote session %s as user %s...", session, username);
1207 g_debug ("Starting authentication for remote session %s...", session);
1208 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
1209 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1210 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1211 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1212 send_message (greeter, message, offset);
1216 * lightdm_greeter_respond:
1217 * @greeter: A #LightDMGreeter
1218 * @response: Response to a prompt
1220 * Provide response to a prompt. May be one in a series.
1223 lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
1225 LightDMGreeterPrivate *priv;
1226 guint8 message[MAX_MESSAGE_LENGTH];
1229 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1230 g_return_if_fail (response != NULL);
1232 priv = GET_PRIVATE (greeter);
1234 g_return_if_fail (priv->connected);
1235 g_return_if_fail (priv->n_responses_waiting > 0);
1237 priv->n_responses_waiting--;
1238 priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
1240 if (priv->n_responses_waiting == 0)
1245 g_debug ("Providing response to display manager");
1247 msg_length = int_length ();
1248 for (iter = priv->responses_received; iter; iter = iter->next)
1249 msg_length += string_length ((gchar *)iter->data);
1251 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
1252 write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
1253 for (iter = priv->responses_received; iter; iter = iter->next)
1254 write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
1255 send_message (greeter, message, offset);
1257 g_list_free_full (priv->responses_received, g_free);
1258 priv->responses_received = NULL;
1263 * lightdm_greeter_cancel_authentication:
1264 * @greeter: A #LightDMGreeter
1266 * Cancel the current user authentication.
1269 lightdm_greeter_cancel_authentication (LightDMGreeter *greeter)
1271 LightDMGreeterPrivate *priv;
1272 guint8 message[MAX_MESSAGE_LENGTH];
1275 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1277 priv = GET_PRIVATE (greeter);
1279 g_return_if_fail (priv->connected);
1281 priv->cancelling_authentication = TRUE;
1282 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1283 send_message (greeter, message, offset);
1287 * lightdm_greeter_get_in_authentication:
1288 * @greeter: A #LightDMGreeter
1290 * Checks if the greeter is in the process of authenticating.
1292 * Return value: #TRUE if the greeter is authenticating a user.
1295 lightdm_greeter_get_in_authentication (LightDMGreeter *greeter)
1297 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1298 return GET_PRIVATE (greeter)->in_authentication;
1302 * lightdm_greeter_get_is_authenticated:
1303 * @greeter: A #LightDMGreeter
1305 * Checks if the greeter has successfully authenticated.
1307 * Return value: #TRUE if the greeter is authenticated for login.
1310 lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
1312 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1313 return GET_PRIVATE (greeter)->is_authenticated;
1317 * lightdm_greeter_get_authentication_user:
1318 * @greeter: A #LightDMGreeter
1320 * Get the user that is being authenticated.
1322 * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
1325 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
1327 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1328 return GET_PRIVATE (greeter)->authentication_user;
1332 * lightdm_greeter_set_language:
1333 * @greeter: A #LightDMGreeter
1334 * @language: The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
1336 * Set the language for the currently authenticated user.
1339 lightdm_greeter_set_language (LightDMGreeter *greeter, const gchar *language)
1341 LightDMGreeterPrivate *priv;
1342 guint8 message[MAX_MESSAGE_LENGTH];
1345 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1347 priv = GET_PRIVATE (greeter);
1349 g_return_if_fail (priv->connected);
1351 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_SET_LANGUAGE, string_length (language), &offset);
1352 write_string (message, MAX_MESSAGE_LENGTH, language, &offset);
1353 send_message (greeter, message, offset);
1357 * lightdm_greeter_start_session:
1358 * @greeter: A #LightDMGreeter
1359 * @session: (allow-none): The session to log into or #NULL to use the default.
1360 * @cancellable: (allow-none): A #GCancellable or %NULL.
1361 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1362 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1364 * Asynchronously start a session for the authenticated user.
1366 * 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.
1368 * See lightdm_greeter_start_session_sync() for the synchronous version.
1371 lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1373 LightDMGreeterPrivate *priv;
1376 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1378 priv = GET_PRIVATE (greeter);
1380 send_start_session (greeter, session);
1381 request = request_new (cancellable, callback, user_data);
1382 priv->start_session_requests = g_list_append (priv->start_session_requests, request);
1386 * lightdm_greeter_start_session_finish:
1387 * @greeter: A #LightDMGreeter
1388 * @result: A #GAsyncResult.
1389 * @error: return location for a #GError, or %NULL
1391 * Start a session for the authenticated user.
1393 * Return value: TRUE if the session was started.
1396 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
1398 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1399 return REQUEST (result)->return_code == 0;
1403 * lightdm_greeter_start_session_sync:
1404 * @greeter: A #LightDMGreeter
1405 * @session: (allow-none): The session to log into or #NULL to use the default.
1406 * @error: return location for a #GError, or %NULL
1408 * Start a session for the authenticated user.
1410 * Return value: TRUE if the session was started.
1413 lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session, GError **error)
1415 LightDMGreeterPrivate *priv;
1417 guint32 return_code;
1419 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
1421 priv = GET_PRIVATE (greeter);
1423 g_return_val_if_fail (priv->connected, FALSE);
1424 g_return_val_if_fail (priv->is_authenticated, FALSE);
1426 /* Read until the session is started */
1427 send_start_session (greeter, session);
1428 request = request_new (NULL, NULL, NULL);
1429 priv->start_session_requests = g_list_append (priv->start_session_requests, g_object_ref (request));
1433 gsize message_length;
1435 message = recv_message (greeter, &message_length, TRUE);
1438 handle_message (greeter, message, message_length);
1440 } while (!request->complete);
1442 return_code = request->return_code;
1443 g_object_unref (request);
1445 return return_code == 0;
1449 * lightdm_greeter_ensure_shared_data_dir:
1450 * @greeter: A #LightDMGreeter
1451 * @username: A username
1452 * @cancellable: (allow-none): A #GCancellable or %NULL.
1453 * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
1454 * @user_data: (allow-none): data to pass to the @callback or %NULL.
1456 * Ensure that a shared data dir for the given user is available. Both the
1457 * greeter user and @username will have write access to that folder. The
1458 * intention is that larger pieces of shared data would be stored there (files
1459 * that the greeter creates but wants to give to a user -- like camera
1460 * photos -- or files that the user creates but wants the greeter to
1461 * see -- like contact avatars).
1463 * LightDM will automatically create these if the user actually logs in, so
1464 * greeters only need to call this method if they want to store something in
1465 * the directory themselves.
1468 lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
1470 LightDMGreeterPrivate *priv;
1473 g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
1475 priv = GET_PRIVATE (greeter);
1477 send_ensure_shared_data_dir (greeter, username);
1478 request = request_new (cancellable, callback, user_data);
1479 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, request);
1483 * lightdm_greeter_ensure_shared_data_dir_finish:
1484 * @result: A #GAsyncResult.
1485 * @greeter: A #LightDMGreeter
1488 * Return value: The path to the shared directory, free with g_free.
1491 lightdm_greeter_ensure_shared_data_dir_finish (LightDMGreeter *greeter, GAsyncResult *result)
1493 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1494 return g_strdup (REQUEST (result)->dir);
1498 * lightdm_greeter_ensure_shared_data_dir_sync:
1499 * @greeter: A #LightDMGreeter
1500 * @username: A username
1502 * Ensure that a shared data dir for the given user is available. Both the
1503 * greeter user and @username will have write access to that folder. The
1504 * intention is that larger pieces of shared data would be stored there (files
1505 * that the greeter creates but wants to give to a user -- like camera
1506 * photos -- or files that the user creates but wants the greeter to
1507 * see -- like contact avatars).
1509 * LightDM will automatically create these if the user actually logs in, so
1510 * greeters only need to call this method if they want to store something in
1511 * the directory themselves.
1513 * Return value: The path to the shared directory, free with g_free.
1516 lightdm_greeter_ensure_shared_data_dir_sync (LightDMGreeter *greeter, const gchar *username)
1518 LightDMGreeterPrivate *priv;
1522 g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), NULL);
1524 priv = GET_PRIVATE (greeter);
1526 g_return_val_if_fail (priv->connected, NULL);
1528 /* Read until a response */
1529 send_ensure_shared_data_dir (greeter, username);
1530 request = request_new (NULL, NULL, NULL);
1531 priv->ensure_shared_data_dir_requests = g_list_append (priv->ensure_shared_data_dir_requests, g_object_ref (request));
1535 gsize message_length;
1537 message = recv_message (greeter, &message_length, TRUE);
1540 handle_message (greeter, message, message_length);
1542 } while (!request->complete);
1544 data_dir = g_strdup (request->dir);
1545 g_object_unref (request);
1551 lightdm_greeter_init (LightDMGreeter *greeter)
1553 LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
1556 priv->read_buffer = g_malloc (HEADER_SIZE);
1557 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1559 fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
1562 GError *error = NULL;
1564 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
1565 g_io_channel_set_encoding (priv->to_server_channel, NULL, &error);
1567 g_warning ("Failed to set encoding on to server channel to binary: %s\n", error->message);
1568 g_clear_error (&error);
1571 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
1573 fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
1576 GError *error = NULL;
1578 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
1579 g_io_channel_set_encoding (priv->from_server_channel, NULL, &error);
1581 g_warning ("Failed to set encoding on from server channel to binary: %s\n", error->message);
1582 g_clear_error (&error);
1583 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
1586 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
1590 lightdm_greeter_set_property (GObject *object,
1592 const GValue *value,
1595 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1599 lightdm_greeter_get_property (GObject *object,
1604 LightDMGreeter *self;
1606 self = LIGHTDM_GREETER (object);
1609 case PROP_DEFAULT_SESSION_HINT:
1610 g_value_set_string (value, lightdm_greeter_get_default_session_hint (self));
1612 case PROP_HIDE_USERS_HINT:
1613 g_value_set_boolean (value, lightdm_greeter_get_hide_users_hint (self));
1615 case PROP_SHOW_MANUAL_LOGIN_HINT:
1616 g_value_set_boolean (value, lightdm_greeter_get_show_manual_login_hint (self));
1618 case PROP_SHOW_REMOTE_LOGIN_HINT:
1619 g_value_set_boolean (value, lightdm_greeter_get_show_remote_login_hint (self));
1621 case PROP_LOCK_HINT:
1622 g_value_set_boolean (value, lightdm_greeter_get_lock_hint (self));
1624 case PROP_HAS_GUEST_ACCOUNT_HINT:
1625 g_value_set_boolean (value, lightdm_greeter_get_has_guest_account_hint (self));
1627 case PROP_SELECT_USER_HINT:
1628 g_value_set_string (value, lightdm_greeter_get_select_user_hint (self));
1630 case PROP_SELECT_GUEST_HINT:
1631 g_value_set_boolean (value, lightdm_greeter_get_select_guest_hint (self));
1633 case PROP_AUTOLOGIN_USER_HINT:
1634 g_value_set_string (value, lightdm_greeter_get_autologin_user_hint (self));
1636 case PROP_AUTOLOGIN_GUEST_HINT:
1637 g_value_set_boolean (value, lightdm_greeter_get_autologin_guest_hint (self));
1639 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1640 g_value_set_int (value, lightdm_greeter_get_autologin_timeout_hint (self));
1642 case PROP_AUTHENTICATION_USER:
1643 g_value_set_string (value, lightdm_greeter_get_authentication_user (self));
1645 case PROP_IN_AUTHENTICATION:
1646 g_value_set_boolean (value, lightdm_greeter_get_in_authentication (self));
1648 case PROP_IS_AUTHENTICATED:
1649 g_value_set_boolean (value, lightdm_greeter_get_is_authenticated (self));
1652 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1658 lightdm_greeter_finalize (GObject *object)
1660 LightDMGreeter *self = LIGHTDM_GREETER (object);
1661 LightDMGreeterPrivate *priv = GET_PRIVATE (self);
1663 if (priv->to_server_channel)
1664 g_io_channel_unref (priv->to_server_channel);
1665 if (priv->from_server_channel)
1666 g_io_channel_unref (priv->from_server_channel);
1667 g_free (priv->authentication_user);
1668 g_hash_table_unref (priv->hints);
1670 G_OBJECT_CLASS (lightdm_greeter_parent_class)->finalize (object);
1674 lightdm_greeter_class_init (LightDMGreeterClass *klass)
1676 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1678 g_type_class_add_private (klass, sizeof (LightDMGreeterPrivate));
1680 object_class->set_property = lightdm_greeter_set_property;
1681 object_class->get_property = lightdm_greeter_get_property;
1682 object_class->finalize = lightdm_greeter_finalize;
1684 g_object_class_install_property (object_class,
1685 PROP_DEFAULT_SESSION_HINT,
1686 g_param_spec_string ("default-session-hint",
1687 "default-session-hint",
1688 "Default session hint",
1690 G_PARAM_READWRITE));
1692 g_object_class_install_property (object_class,
1693 PROP_HIDE_USERS_HINT,
1694 g_param_spec_boolean ("hide-users-hint",
1700 g_object_class_install_property (object_class,
1701 PROP_SHOW_MANUAL_LOGIN_HINT,
1702 g_param_spec_boolean ("show-manual-login-hint",
1703 "show-manual-login-hint",
1704 "Show manual login hint",
1708 g_object_class_install_property (object_class,
1709 PROP_SHOW_REMOTE_LOGIN_HINT,
1710 g_param_spec_boolean ("show-remote-login-hint",
1711 "show-remote-login-hint",
1712 "Show remote login hint",
1716 g_object_class_install_property (object_class,
1718 g_param_spec_boolean ("lock-hint",
1724 g_object_class_install_property (object_class,
1725 PROP_HAS_GUEST_ACCOUNT_HINT,
1726 g_param_spec_boolean ("has-guest-account-hint",
1727 "has-guest-account-hint",
1728 "Has guest account hint",
1732 g_object_class_install_property (object_class,
1733 PROP_SELECT_USER_HINT,
1734 g_param_spec_string ("select-user-hint",
1740 g_object_class_install_property (object_class,
1741 PROP_SELECT_GUEST_HINT,
1742 g_param_spec_boolean ("select-guest-hint",
1743 "select-guest-hint",
1744 "Select guest account hint",
1748 g_object_class_install_property (object_class,
1749 PROP_AUTOLOGIN_USER_HINT,
1750 g_param_spec_string ("autologin-user-hint",
1751 "autologin-user-hint",
1752 "Autologin user hint",
1756 g_object_class_install_property (object_class,
1757 PROP_AUTOLOGIN_GUEST_HINT,
1758 g_param_spec_boolean ("autologin-guest-hint",
1759 "autologin-guest-hint",
1760 "Autologin guest account hint",
1764 g_object_class_install_property (object_class,
1765 PROP_AUTOLOGIN_TIMEOUT_HINT,
1766 g_param_spec_int ("autologin-timeout-hint",
1767 "autologin-timeout-hint",
1768 "Autologin timeout hint",
1772 g_object_class_install_property (object_class,
1773 PROP_AUTHENTICATION_USER,
1774 g_param_spec_string ("authentication-user",
1775 "authentication-user",
1776 "The user being authenticated",
1779 g_object_class_install_property (object_class,
1780 PROP_IN_AUTHENTICATION,
1781 g_param_spec_boolean ("in-authentication",
1782 "in-authentication",
1783 "TRUE if a user is being authenticated",
1786 g_object_class_install_property (object_class,
1787 PROP_IS_AUTHENTICATED,
1788 g_param_spec_boolean ("is-authenticated",
1790 "TRUE if the selected user is authenticated",
1795 * LightDMGreeter::show-prompt:
1796 * @greeter: A #LightDMGreeter
1797 * @text: Prompt text
1798 * @type: Prompt type
1800 * The ::show-prompt signal gets emitted when the greeter should show a
1801 * prompt to the user. The given text should be displayed and an input
1802 * field for the user to provide a response.
1804 * Call lightdm_greeter_respond() with the resultant input or
1805 * lightdm_greeter_cancel_authentication() to abort the authentication.
1807 signals[SHOW_PROMPT] =
1808 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
1809 G_TYPE_FROM_CLASS (klass),
1811 G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
1814 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1817 * LightDMGreeter::show-message:
1818 * @greeter: A #LightDMGreeter
1819 * @text: Message text
1820 * @type: Message type
1822 * The ::show-message signal gets emitted when the greeter
1823 * should show a message to the user.
1825 signals[SHOW_MESSAGE] =
1826 g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
1827 G_TYPE_FROM_CLASS (klass),
1829 G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
1832 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
1835 * LightDMGreeter::authentication-complete:
1836 * @greeter: A #LightDMGreeter
1838 * The ::authentication-complete signal gets emitted when the greeter
1839 * has completed authentication.
1841 * Call lightdm_greeter_get_is_authenticated() to check if the authentication
1844 signals[AUTHENTICATION_COMPLETE] =
1845 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
1846 G_TYPE_FROM_CLASS (klass),
1848 G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
1854 * LightDMGreeter::autologin-timer-expired:
1855 * @greeter: A #LightDMGreeter
1857 * The ::timed-login signal gets emitted when the automatic login timer has expired.
1858 * The application should then call lightdm_greeter_login().
1860 signals[AUTOLOGIN_TIMER_EXPIRED] =
1861 g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
1862 G_TYPE_FROM_CLASS (klass),
1864 G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
1870 * LightDMGreeter::idle:
1871 * @greeter: A #LightDMGreeter
1873 * The ::idle signal gets emitted when the user has logged in and the
1874 * greeter is no longer needed.
1876 * This signal only matters if the greeter has marked itself as
1877 * resettable using lightdm_greeter_set_resettable().
1880 g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
1881 G_TYPE_FROM_CLASS (klass),
1883 G_STRUCT_OFFSET (LightDMGreeterClass, idle),
1889 * LightDMGreeter::reset:
1890 * @greeter: A #LightDMGreeter
1892 * The ::reset signal gets emitted when the user is returning to a greeter
1893 * that was previously marked idle.
1895 * This signal only matters if the greeter has marked itself as
1896 * resettable using lightdm_greeter_set_resettable().
1899 g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
1900 G_TYPE_FROM_CLASS (klass),
1902 G_STRUCT_OFFSET (LightDMGreeterClass, reset),
1909 request_init (Request *request)
1914 request_finalize (GObject *object)
1916 Request *request = REQUEST (object);
1918 g_free (request->dir);
1919 if (request->cancellable)
1920 g_object_unref (request->cancellable);
1922 G_OBJECT_CLASS (request_parent_class)->finalize (object);
1926 request_class_init (RequestClass *klass)
1928 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1929 object_class->finalize = request_finalize;
1933 request_get_user_data (GAsyncResult *result)
1935 return REQUEST (result)->user_data;
1939 request_get_source_object (GAsyncResult *res)
1945 request_iface_init (GAsyncResultIface *iface)
1947 iface->get_user_data = request_get_user_data;
1948 iface->get_source_object = request_get_source_object;