]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - common/user-list.c
Load all users only when really needed
[sojka/lightdm.git] / common / user-list.c
index 7e7faa68e510d6cb754070d4e7baae0646e97124..d5d95e208e32ee7f904afcdfd590f74843a76a85 100644 (file)
 
 enum
 {
-    LIST_PROP_0,
-    LIST_PROP_NUM_USERS,
+    LIST_PROP_NUM_USERS = 1,
     LIST_PROP_USERS,
 };
 
 enum
 {
-    USER_PROP_0,
-    USER_PROP_NAME,
+    USER_PROP_NAME = 1,
     USER_PROP_REAL_NAME,
     USER_PROP_DISPLAY_NAME,
     USER_PROP_HOME_DIRECTORY,
@@ -61,6 +59,7 @@ static guint list_signals[LAST_LIST_SIGNAL] = { 0 };
 enum
 {
     CHANGED,
+    GET_LOGGED_IN,
     LAST_USER_SIGNAL
 };
 static guint user_signals[LAST_USER_SIGNAL] = { 0 };
@@ -93,12 +92,12 @@ typedef struct
 
 typedef struct
 {
-    /* User list this user is part of */
-    CommonUserList *user_list;
-
     /* TRUE if have loaded the DMRC file */
     gboolean loaded_dmrc;
 
+    /* Bus we are listening for accounts service on */
+    GDBusConnection *bus;
+
     /* Accounts service path */
     gchar *path;
 
@@ -186,9 +185,7 @@ common_user_list_get_instance (void)
 void
 common_user_list_cleanup (void)
 {
-    if (singleton)
-        g_object_unref (singleton);
-    singleton = NULL;
+    g_clear_object (&singleton);
 }
 
 static CommonUser *
@@ -254,10 +251,34 @@ update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_
     return TRUE;
 }
 
+static void load_sessions (CommonUserList *user_list);
+
+static gboolean
+get_logged_in_cb (CommonUser *user, CommonUserList *user_list)
+{
+    CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+    const gchar *username;
+    GList *link;
+
+    // Lazily decide to load/listen to sessions
+    if (priv->session_added_signal == 0)
+        load_sessions (user_list);
+
+    username = GET_USER_PRIVATE (user)->name;
+    for (link = priv->sessions; link; link = link->next)
+    {
+        CommonSession *session = link->data;
+        if (strcmp (session->username, username) == 0)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
 static void
-user_changed_cb (CommonUser *user)
+user_changed_cb (CommonUser *user, CommonUserList *user_list)
 {
-    g_signal_emit (GET_USER_PRIVATE (user)->user_list, list_signals[USER_CHANGED], 0, user);
+    g_signal_emit (user_list, list_signals[USER_CHANGED], 0, user);
 }
 
 static CommonUser *
@@ -268,6 +289,8 @@ make_passwd_user (CommonUserList *user_list, struct passwd *entry)
     char **tokens;
     gchar *real_name, *image;
 
+    g_signal_connect (user, "get-logged-in", G_CALLBACK (get_logged_in_cb), user_list);  
+
     tokens = g_strsplit (entry->pw_gecos, ",", -1);
     if (tokens[0] != NULL && tokens[0][0] != '\0')
         real_name = g_strdup (tokens[0]);
@@ -287,7 +310,6 @@ make_passwd_user (CommonUserList *user_list, struct passwd *entry)
         }
     }
 
-    priv->user_list = user_list;
     priv->name = g_strdup (entry->pw_name);
     priv->real_name = real_name;
     priv->home_directory = g_strdup (entry->pw_dir);
@@ -407,7 +429,7 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal)
     {
         CommonUser *info = link->data;
         g_debug ("User %s added", common_user_get_name (info));
-        g_signal_connect (info, "changed", G_CALLBACK (user_changed_cb), NULL);
+        g_signal_connect (info, USER_SIGNAL_CHANGED, G_CALLBACK (user_changed_cb), user_list);
         if (emit_add_signal)
             g_signal_emit (user_list, list_signals[USER_ADDED], 0, info);
     }
@@ -463,9 +485,12 @@ accounts_user_changed_cb (GDBusConnection *connection,
                           gpointer data)
 {
     CommonUser *user = data;
-    CommonUserPrivate *priv = GET_USER_PRIVATE (user);  
+    /*CommonUserPrivate *priv = GET_USER_PRIVATE (user);*/
 
-    g_debug ("User %s changed", priv->path);
+    /* Log message disabled as AccountsService can have arbitrary plugins that
+     * might cause us to log when properties change we don't use. LP: #1376357
+     */
+    /*g_debug ("User %s changed", priv->path);*/
     if (load_accounts_user (user))
         g_signal_emit (user, user_signals[CHANGED], 0);
 }
@@ -482,17 +507,17 @@ load_accounts_user (CommonUser *user)
 
     /* Get the properties for this user */
     if (!priv->changed_signal)
-        priv->changed_signal = g_dbus_connection_signal_subscribe (GET_LIST_PRIVATE (priv->user_list)->bus,
+        priv->changed_signal = g_dbus_connection_signal_subscribe (priv->bus,
                                                                    "org.freedesktop.Accounts",
-                                                                   "org.freedesktop.DBus.Properties",
-                                                                   "PropertiesChanged",
-                                                                   priv->path,
                                                                    "org.freedesktop.Accounts.User",
+                                                                   "Changed",
+                                                                   priv->path,
+                                                                   NULL,
                                                                    G_DBUS_SIGNAL_FLAGS_NONE,
                                                                    accounts_user_changed_cb,
                                                                    user,
                                                                    NULL);
-    result = g_dbus_connection_call_sync (GET_LIST_PRIVATE (priv->user_list)->bus,
+    result = g_dbus_connection_call_sync (priv->bus,
                                           "org.freedesktop.Accounts",
                                           priv->path,
                                           "org.freedesktop.DBus.Properties",
@@ -599,9 +624,10 @@ add_accounts_user (CommonUserList *user_list, const gchar *path, gboolean emit_s
     priv = GET_USER_PRIVATE (user);
 
     g_debug ("User %s added", path);
-    priv->user_list = user_list;
+    priv->bus = g_object_ref (list_priv->bus);
     priv->path = g_strdup (path);
-    g_signal_connect (user, "changed", G_CALLBACK (user_changed_cb), NULL);
+    g_signal_connect (user, USER_SIGNAL_CHANGED, G_CALLBACK (user_changed_cb), user_list);
+    g_signal_connect (user, "get-logged-in", G_CALLBACK (get_logged_in_cb), user_list);  
     if (load_accounts_user (user))
     {
         list_priv->users = g_list_insert_sorted (list_priv->users, user, compare_user);
@@ -919,8 +945,6 @@ load_users (CommonUserList *user_list)
         g_dbus_connection_signal_unsubscribe (priv->bus, priv->user_removed_signal);
         priv->user_removed_signal = 0;
 
-        load_passwd_file (user_list, FALSE);
-
         /* Watch for changes to user list */
 
         passwd_file = g_file_new_for_path (PASSWD_FILE);
@@ -982,6 +1006,7 @@ common_user_list_get_user_by_name (CommonUserList *user_list, const gchar *usern
     g_return_val_if_fail (COMMON_IS_USER_LIST (user_list), NULL);
     g_return_val_if_fail (username != NULL, NULL);
 
+    /* Load users from AccountsService, do nothing when it does not run */
     load_users (user_list);
 
     CommonUser *user = get_user_by_name (user_list, username);
@@ -1008,19 +1033,19 @@ common_user_list_init (CommonUserList *user_list)
 }
 
 static void
-common_user_list_set_property (GObject    *object,
-                                guint       prop_id,
-                                const GValue *value,
-                                GParamSpec *pspec)
+common_user_list_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
 {
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 }
 
 static void
 common_user_list_get_property (GObject    *object,
-                                guint       prop_id,
-                                GValue     *value,
-                                GParamSpec *pspec)
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
 {
     CommonUserList *self;
 
@@ -1056,8 +1081,7 @@ common_user_list_finalize (GObject *object)
     if (priv->session_removed_signal)
         g_dbus_connection_signal_unsubscribe (priv->bus, priv->session_removed_signal);
     g_object_unref (priv->bus);
-    if (priv->passwd_monitor)
-        g_object_unref (priv->passwd_monitor);
+    g_clear_object (&priv->passwd_monitor);
 
     G_OBJECT_CLASS (common_user_list_parent_class)->finalize (object);
 }
@@ -1088,7 +1112,7 @@ common_user_list_class_init (CommonUserListClass *klass)
      * The ::user-added signal gets emitted when a user account is created.
      **/
     list_signals[USER_ADDED] =
-        g_signal_new ("user-added",
+        g_signal_new (USER_LIST_SIGNAL_USER_ADDED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (CommonUserListClass, user_added),
@@ -1104,7 +1128,7 @@ common_user_list_class_init (CommonUserListClass *klass)
      * The ::user-changed signal gets emitted when a user account is modified.
      **/
     list_signals[USER_CHANGED] =
-        g_signal_new ("user-changed",
+        g_signal_new (USER_LIST_SIGNAL_USER_CHANGED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (CommonUserListClass, user_changed),
@@ -1120,7 +1144,7 @@ common_user_list_class_init (CommonUserListClass *klass)
      * The ::user-removed signal gets emitted when a user account is removed.
      **/
     list_signals[USER_REMOVED] =
-        g_signal_new ("user-removed",
+        g_signal_new (USER_LIST_SIGNAL_USER_REMOVED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (CommonUserListClass, user_removed),
@@ -1135,12 +1159,11 @@ call_method (CommonUser *user, const gchar *method, GVariant *args,
 {
     GVariant *answer;
     GError *error = NULL;
-    CommonUserPrivate *user_priv = GET_USER_PRIVATE (user);
-    CommonUserListPrivate *list_priv = GET_LIST_PRIVATE (user_priv->user_list);
+    CommonUserPrivate *priv = GET_USER_PRIVATE (user);
 
-    answer = g_dbus_connection_call_sync (list_priv->bus,
+    answer = g_dbus_connection_call_sync (priv->bus,
                                           "org.freedesktop.Accounts",
-                                          user_priv->path,
+                                          priv->path,
                                           "org.freedesktop.Accounts.User",
                                           method,
                                           args,
@@ -1438,27 +1461,13 @@ common_user_set_session (CommonUser *user, const gchar *session)
 gboolean
 common_user_get_logged_in (CommonUser *user)
 {
-    CommonUserPrivate *priv;
-    CommonUserListPrivate *list_priv;
-    GList *link;
+    gboolean result;
 
     g_return_val_if_fail (COMMON_IS_USER (user), FALSE);
 
-    priv = GET_USER_PRIVATE (user);
-    list_priv = GET_LIST_PRIVATE (priv->user_list);
+    g_signal_emit (user, user_signals[GET_LOGGED_IN], 0, &result);
 
-    // Lazily decide to load/listen to sessions
-    if (list_priv->session_added_signal == 0)
-        load_sessions (priv->user_list);
-
-    for (link = list_priv->sessions; link; link = link->next)
-    {
-        CommonSession *session = link->data;
-        if (strcmp (session->username, priv->name) == 0)
-            return TRUE;
-    }
-
-    return FALSE;
+    return result;
 }
 
 /**
@@ -1604,7 +1613,8 @@ common_user_finalize (GObject *object)
 
     g_free (priv->path);
     if (priv->changed_signal)
-        g_dbus_connection_signal_unsubscribe (GET_LIST_PRIVATE (priv->user_list)->bus, priv->changed_signal);
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->changed_signal);
+    g_clear_object (&priv->bus);
     g_free (priv->name);
     g_free (priv->real_name);
     g_free (priv->home_directory);
@@ -1744,13 +1754,23 @@ common_user_class_init (CommonUserClass *klass)
      * The ::changed signal gets emitted this user account is modified.
      **/
     user_signals[CHANGED] =
-        g_signal_new ("changed",
+        g_signal_new (USER_SIGNAL_CHANGED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (CommonUserClass, changed),
                       NULL, NULL,
                       NULL,
                       G_TYPE_NONE, 0);
+
+    user_signals[GET_LOGGED_IN] =
+        g_signal_new ("get-logged-in",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0,
+                      g_signal_accumulator_first_wins,
+                      NULL,
+                      NULL,
+                      G_TYPE_BOOLEAN, 0);
 }
 
 static void