]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - liblightdm-gobject/greeter.c
Set GError values on greeter method failures
[sojka/lightdm.git] / liblightdm-gobject / greeter.c
index 9c8b347484689da6d9bc567a49ca2995a0463645..7db92c021c6226a73f6f2299c8bb44d5b677d774 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "lightdm/greeter.h"
 
+G_DEFINE_QUARK (lightdm_greeter_error, lightdm_greeter_error)
+
 enum {
     PROP_0,
     PROP_DEFAULT_SESSION_HINT,
@@ -129,6 +131,7 @@ typedef struct
     GAsyncReadyCallback callback;
     gpointer user_data;
     gboolean complete;
+    gboolean connected;
     guint32 return_code;
     gchar *dir;
 } Request;
@@ -141,6 +144,58 @@ static void request_iface_init (GAsyncResultIface *iface);
 #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
 G_DEFINE_TYPE_WITH_CODE (Request, request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, request_iface_init));
 
+GType
+lightdm_greeter_error_get_type (void)
+{
+    static GType enum_type = 0;
+
+    if (G_UNLIKELY(enum_type == 0)) {
+        static const GEnumValue values[] = {
+            { LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "LIGHTDM_GREETER_ERROR_CONNECTION_FAILED", "connection-failed" },
+            { LIGHTDM_GREETER_ERROR_SESSION_FAILED, "LIGHTDM_GREETER_ERROR_SESSION_FAILED", "session-failed" },
+            { 0, NULL, NULL }
+        };
+        enum_type = g_enum_register_static (g_intern_static_string ("LightDMGreeterError"), values);
+    }
+
+    return enum_type;
+}
+
+GType
+lightdm_prompt_type_get_type (void)
+{
+    static GType enum_type = 0;
+  
+    if (G_UNLIKELY(enum_type == 0)) {
+        static const GEnumValue values[] = {
+            { LIGHTDM_PROMPT_TYPE_QUESTION, "LIGHTDM_PROMPT_TYPE_QUESTION", "question" },
+            { LIGHTDM_PROMPT_TYPE_SECRET, "LIGHTDM_PROMPT_TYPE_SECRET", "secret" },
+            { 0, NULL, NULL }
+        };
+        enum_type = g_enum_register_static (g_intern_static_string ("LightDMPromptType"), values);
+    }
+
+    return enum_type;
+}
+
+GType
+lightdm_message_type_get_type (void)
+{
+    static GType enum_type = 0;
+  
+    if (G_UNLIKELY(enum_type == 0)) {
+        static const GEnumValue values[] = {
+            { LIGHTDM_MESSAGE_TYPE_INFO, "LIGHTDM_MESSAGE_TYPE_INFO", "info" },
+            { LIGHTDM_MESSAGE_TYPE_ERROR, "LIGHTDM_MESSAGE_TYPE_ERROR", "error" },
+            { 0, NULL, NULL }
+        };
+        enum_type = g_enum_register_static (g_intern_static_string ("LightDMMessageType"), values);
+    }
+
+    return enum_type;
+}
+
+
 /**
  * lightdm_greeter_new:
  *
@@ -243,7 +298,8 @@ write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *off
     write_int (buffer, buffer_length, length, offset);
     if (*offset + length >= buffer_length)
         return;
-    memcpy (buffer + *offset, value, length);
+    if (value)
+        memcpy (buffer + *offset, value, length);
     *offset += length;
 }
 
@@ -314,7 +370,8 @@ static gboolean
 send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
 {
     LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
-    GIOStatus status;
+    gchar *data;
+    gsize data_length;
     GError *error = NULL;
     guint32 stated_length;
 
@@ -333,15 +390,28 @@ send_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
         return FALSE;
     }
 
-    status = g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, &error);
-    if (error)
-        g_warning ("Error writing to daemon: %s", error->message);
-    g_clear_error (&error);
-    if (status != G_IO_STATUS_NORMAL)
-        return FALSE;
+    data = (gchar *) message;
+    data_length = message_length;
+    while (data_length > 0)
+    {
+        GIOStatus status;
+        gsize n_written;
+
+        status = g_io_channel_write_chars (priv->to_server_channel, data, data_length, &n_written, &error);
+        if (error)
+            g_warning ("Error writing to daemon: %s", error->message);
+        g_clear_error (&error);
+        if (status != G_IO_STATUS_NORMAL)
+            return FALSE;
+        data_length -= n_written;
+        data += n_written;
+    }
 
     g_debug ("Wrote %zi bytes to daemon", message_length);
-    g_io_channel_flush (priv->to_server_channel, NULL);
+    g_io_channel_flush (priv->to_server_channel, &error);
+    if (error)
+        g_warning ("Failed to flush data to daemon: %s", error->message);
+    g_clear_error (&error);
 
     return TRUE;
 }
@@ -360,7 +430,7 @@ handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length
     while (*offset < message_length)
     {
         gchar *name, *value;
-      
+
         name = read_string (message, message_length, offset);
         value = read_string (message, message_length, offset);
         g_hash_table_insert (priv->hints, name, value);
@@ -384,6 +454,7 @@ handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length
     request = g_list_nth_data (priv->connect_requests, 0);
     if (request)
     {
+        request->connected = TRUE;
         request_complete (request, G_OBJECT (greeter));
         priv->connect_requests = g_list_remove (priv->connect_requests, request);
         g_object_unref (request);
@@ -723,7 +794,7 @@ send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
 }
 
 /**
- * lightdm_greeter_connect:
+ * lightdm_greeter_connect_to_daemon:
  * @greeter: The greeter to connect
  * @cancellable: (allow-none): A #GCancellable or %NULL.
  * @callback: (allow-none): A #GAsyncReadyCallback to call when completed or %NULL.
@@ -731,12 +802,12 @@ send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
  *
  * Asynchronously connects the greeter to the display manager.
  *
- * When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_finish() to get the result of the operation.
+ * 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.
  *
- * See lightdm_greeter_connect_sync() for the synchronous version.
+ * See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
  **/
 void
-lightdm_greeter_connect (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+lightdm_greeter_connect_to_daemon (LightDMGreeter *greeter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
     LightDMGreeterPrivate *priv;
     Request *request;
@@ -751,23 +822,33 @@ lightdm_greeter_connect (LightDMGreeter *greeter, GCancellable *cancellable, GAs
 }
 
 /**
- * lightdm_greeter_connect_finish:
+ * lightdm_greeter_connect_to_daemon_finish:
+ * @greeter: The greeter the the request was done with
  * @result: A #GAsyncResult.
  * @error: return location for a #GError, or %NULL
  *
- * Finishes an operation started with lightdm_greeter_connect().
+ * Finishes an operation started with lightdm_greeter_connect_to_daemon().
  *
  * Return value: #TRUE if successfully connected
  **/
 gboolean
-lightdm_greeter_connect_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
+lightdm_greeter_connect_to_daemon_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
 {
-    g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
-    return REQUEST (result)->complete;
+    Request *request = REQUEST (result);
+
+    g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
+
+    if (request->connected)
+        return TRUE;
+    else
+    {
+        g_set_error_literal (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_CONNECTION_FAILED, "Failed to connect to daemon");
+        return FALSE;
+    }
 }
 
 /**
- * lightdm_greeter_connect_sync:
+ * lightdm_greeter_connect_to_daemon_sync:
  * @greeter: The greeter to connect
  * @error: return location for a #GError, or %NULL
  *
@@ -776,7 +857,7 @@ lightdm_greeter_connect_finish (LightDMGreeter *greeter, GAsyncResult *result, G
  * Return value: #TRUE if successfully connected
  **/
 gboolean
-lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
+lightdm_greeter_connect_to_daemon_sync (LightDMGreeter *greeter, GError **error)
 {
     LightDMGreeterPrivate *priv;
     Request *request;
@@ -801,9 +882,24 @@ lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
         g_free (message);
     } while (!request->complete);
 
-    g_object_unref (request);
+    return lightdm_greeter_connect_to_daemon_finish (greeter, G_ASYNC_RESULT (request), error);
+}
 
-    return request->complete;
+/**
+ * lightdm_greeter_connect_sync:
+ * @greeter: The greeter to connect
+ * @error: return location for a #GError, or %NULL
+ *
+ * Connects the greeter to the display manager.  Will block until connected.
+ *
+ * Return value: #TRUE if successfully connected
+ *
+ * Deprecated: 1.11.1: Use lightdm_greeter_connect_to_daemon_sync() instead
+ **/
+gboolean
+lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
+{
+    return lightdm_greeter_connect_to_daemon_sync (greeter, error);
 }
 
 /**
@@ -813,7 +909,7 @@ lightdm_greeter_connect_sync (LightDMGreeter *greeter, GError **error)
  *
  * Get a hint.
  *
- * Return value: The value for this hint or #NULL if not set.
+ * Return value: (nullable): The value for this hint or #NULL if not set.
  **/
 const gchar *
 lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name)
@@ -845,7 +941,7 @@ lightdm_greeter_get_default_session_hint (LightDMGreeter *greeter)
  * accounts should be taken from #LightDMUserList and displayed in the greeter
  * for the user to choose from.  Note that this list can be empty and it is
  * recommended you show a method for the user to enter a username manually.
- * 
+ *
  * If this option is shown the greeter should only allow these users to be
  * chosen for login unless the manual login hint is set.
  *
@@ -938,7 +1034,7 @@ lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
 
     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
     value = lightdm_greeter_get_hint (greeter, "has-guest-account");
-  
+
     return g_strcmp0 (value, "true") == 0;
 }
 
@@ -948,7 +1044,7 @@ lightdm_greeter_get_has_guest_account_hint (LightDMGreeter *greeter)
  *
  * Get the user to select by default.
  *
- * Return value: A username
+ * Return value: (nullable): A username or %NULL if no particular user should be selected.
  */
 const gchar *
 lightdm_greeter_get_select_user_hint (LightDMGreeter *greeter)
@@ -972,7 +1068,7 @@ lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
 
     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
     value = lightdm_greeter_get_hint (greeter, "select-guest");
-  
+
     return g_strcmp0 (value, "true") == 0;
 }
 
@@ -980,9 +1076,9 @@ lightdm_greeter_get_select_guest_hint (LightDMGreeter *greeter)
  * lightdm_greeter_get_autologin_user_hint:
  * @greeter: A #LightDMGreeter
  *
- * Get the user account to automatically logg into when the timer expires.
+ * Get the user account to automatically log into when the timer expires.
  *
- * Return value: The user account to automatically log into.
+ * Return value: (nullable): The user account to automatically log into or %NULL if none configured.
  */
 const gchar *
 lightdm_greeter_get_autologin_user_hint (LightDMGreeter *greeter)
@@ -1006,7 +1102,7 @@ lightdm_greeter_get_autologin_guest_hint (LightDMGreeter *greeter)
 
     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
     value = lightdm_greeter_get_hint (greeter, "autologin-guest");
-  
+
     return g_strcmp0 (value, "true") == 0;
 }
 
@@ -1076,7 +1172,7 @@ lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
 
     priv->cancelling_authentication = FALSE;
     priv->authenticate_sequence_number++;
-    priv->in_authentication = TRUE;  
+    priv->in_authentication = TRUE;
     priv->is_authenticated = FALSE;
     if (username != priv->authentication_user)
     {
@@ -1287,7 +1383,7 @@ lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter)
  *
  * Get the user that is being authenticated.
  *
- * Return value: The username of the authentication user being authenticated or #NULL if no authentication in progress.
+ * Return value: (nullable): The username of the authentication user being authenticated or #NULL if no authentication in progress.
  */
 const gchar *
 lightdm_greeter_get_authentication_user (LightDMGreeter *greeter)
@@ -1363,8 +1459,17 @@ lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session, GC
 gboolean
 lightdm_greeter_start_session_finish (LightDMGreeter *greeter, GAsyncResult *result, GError **error)
 {
+    Request *request = REQUEST (result);
+
     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
-    return REQUEST (result)->return_code == 0;
+
+    if (request->return_code == 0)
+        return TRUE;
+    else
+    {
+        g_set_error (error, LIGHTDM_GREETER_ERROR, LIGHTDM_GREETER_ERROR_SESSION_FAILED, "Session returned error code %d", request->return_code);
+        return FALSE;
+    }
 }
 
 /**
@@ -1382,7 +1487,6 @@ lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *sessio
 {
     LightDMGreeterPrivate *priv;
     Request *request;
-    guint32 return_code;
 
     g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE);
 
@@ -1407,10 +1511,7 @@ lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *sessio
         g_free (message);
     } while (!request->complete);
 
-    return_code = request->return_code;
-    g_object_unref (request);
-
-    return return_code == 0;
+    return lightdm_greeter_start_session_finish (greeter, G_ASYNC_RESULT (request), error);
 }
 
 /**
@@ -1452,6 +1553,7 @@ lightdm_greeter_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *us
  * @result: A #GAsyncResult.
  * @greeter: A #LightDMGreeter
  *
+ * Function to call from lightdm_greeter_ensure_shared_data_dir callback.
  *
  * Return value: The path to the shared directory, free with g_free.
  **/
@@ -1527,8 +1629,13 @@ lightdm_greeter_init (LightDMGreeter *greeter)
     fd = g_getenv ("LIGHTDM_TO_SERVER_FD");
     if (fd)
     {
+        GError *error = NULL;
+
         priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
-        g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
+        g_io_channel_set_encoding (priv->to_server_channel, NULL, &error);
+        if (error)
+            g_warning ("Failed to set encoding on to server channel to binary: %s\n", error->message);
+        g_clear_error (&error);
     }
     else
         g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
@@ -1536,8 +1643,13 @@ lightdm_greeter_init (LightDMGreeter *greeter)
     fd = g_getenv ("LIGHTDM_FROM_SERVER_FD");
     if (fd)
     {
+        GError *error = NULL;
+
         priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
-        g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
+        g_io_channel_set_encoding (priv->from_server_channel, NULL, &error);
+        if (error)
+            g_warning ("Failed to set encoding on from server channel to binary: %s\n", error->message);
+        g_clear_error (&error);
         g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
     }
     else
@@ -1645,7 +1757,7 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
                                                           "default-session-hint",
                                                           "Default session hint",
                                                           NULL,
-                                                          G_PARAM_READWRITE));
+                                                          G_PARAM_READABLE));
 
     g_object_class_install_property (object_class,
                                      PROP_HIDE_USERS_HINT,
@@ -1763,13 +1875,13 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * lightdm_greeter_cancel_authentication() to abort the authentication.
      **/
     signals[SHOW_PROMPT] =
-        g_signal_new ("show-prompt",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, show_prompt),
                       NULL, NULL,
                       NULL,
-                      G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
+                      G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_prompt_type_get_type ());
 
     /**
      * LightDMGreeter::show-message:
@@ -1781,13 +1893,13 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * should show a message to the user.
      **/
     signals[SHOW_MESSAGE] =
-        g_signal_new ("show-message",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, show_message),
                       NULL, NULL,
                       NULL,
-                      G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
+                      G_TYPE_NONE, 2, G_TYPE_STRING, lightdm_message_type_get_type ());
 
     /**
      * LightDMGreeter::authentication-complete:
@@ -1800,7 +1912,7 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * was successful.
      **/
     signals[AUTHENTICATION_COMPLETE] =
-        g_signal_new ("authentication-complete",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, authentication_complete),
@@ -1816,7 +1928,7 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * The application should then call lightdm_greeter_login().
      **/
     signals[AUTOLOGIN_TIMER_EXPIRED] =
-        g_signal_new ("autologin-timer-expired",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, autologin_timer_expired),
@@ -1835,7 +1947,7 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * resettable using lightdm_greeter_set_resettable().
      **/
     signals[IDLE] =
-        g_signal_new ("idle",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_IDLE,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, idle),
@@ -1854,7 +1966,7 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass)
      * resettable using lightdm_greeter_set_resettable().
      **/
     signals[RESET] =
-        g_signal_new ("reset",
+        g_signal_new (LIGHTDM_GREETER_SIGNAL_RESET,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (LightDMGreeterClass, reset),
@@ -1874,8 +1986,7 @@ request_finalize (GObject *object)
     Request *request = REQUEST (object);
 
     g_free (request->dir);
-    if (request->cancellable)
-        g_object_unref (request->cancellable);
+    g_clear_object (&request->cancellable);
 
     G_OBJECT_CLASS (request_parent_class)->finalize (object);
 }
@@ -1899,16 +2010,9 @@ request_get_source_object (GAsyncResult *res)
     return NULL;
 }
 
-static gboolean
-request_is_tagged (GAsyncResult *res, gpointer source_tag)
-{
-    return FALSE;
-}
-
 static void
 request_iface_init (GAsyncResultIface *iface)
 {
     iface->get_user_data = request_get_user_data;
     iface->get_source_object = request_get_source_object;
-    iface->is_tagged = request_is_tagged;
 }