]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Merge with trunk
authorRobert Ancell <robert.ancell@canonical.com>
Thu, 6 Jun 2013 21:51:01 +0000 (09:51 +1200)
committerRobert Ancell <robert.ancell@canonical.com>
Thu, 6 Jun 2013 21:51:01 +0000 (09:51 +1200)
tests/Makefile.am
tests/src/test-gobject-greeter.c
tests/src/test-python-greeter
tests/src/test-qt-greeter.cpp
tests/src/test-qt-greeter.h
tests/src/test-runner.c
tests/test-users-gobject [new file with mode: 0755]
tests/test-users-python [new file with mode: 0755]
tests/test-users-qt4 [new file with mode: 0755]
tests/test-users-qt5 [new file with mode: 0755]

index f429b8ad8136ec3d428791ea8b812da7cc0110ed..2cc23bd68586c654f0bb31b8ef3f3f4948f4da16 100644 (file)
@@ -49,6 +49,8 @@ TESTS = \
        test-system-xauthority \
        test-user-renamed \
        test-user-renamed-invalid \
+       test-users-gobject \
+       test-users-python \
        test-keyboard-layout \
        test-no-keyboard-layout \
        test-language \
@@ -182,6 +184,7 @@ TESTS += \
        test-login-qt4-guest-fail-setup-script \
        test-login-qt4-guest-logout \
        test-login-qt4-remote-session \
+       test-users-qt4 \
        test-qt4-power \
        test-qt4-power-no-console-kit \
        test-qt4-power-no-login1 \
@@ -215,6 +218,7 @@ TESTS += \
        test-login-qt5-guest-fail-setup-script \
        test-login-qt5-guest-logout \
        test-login-qt5-remote-session \
+       test-users-qt5 \
        test-qt5-power \
        test-qt5-power-no-console-kit \
        test-qt5-power-no-login1 \
@@ -339,6 +343,7 @@ EXTRA_DIST = \
        scripts/switch-to-user-logout.conf \
        scripts/switch-to-user-no-password.conf \
        scripts/system-xauthority.conf \
+       scripts/users.conf \
        scripts/util-path.conf \
        scripts/user-renamed.conf \
        scripts/user-renamed-invalid.conf \
index f95282bb81098ac705f346123dbd2506359f87e0..3a3a3850dec81c6485c4ed9e935793030e021a20 100644 (file)
@@ -120,6 +120,37 @@ request_cb (const gchar *request)
     }
     g_free (r);
 
+    r = g_strdup_printf ("%s LOG-USER-LIST-LENGTH", greeter_id);
+    if (strcmp (request, r) == 0)
+        status_notify ("%s LOG-USER-LIST-LENGTH N=%d", greeter_id, lightdm_user_list_get_length (lightdm_user_list_get_instance ()));
+    g_free (r);
+
+    r = g_strdup_printf ("%s LOG-USER USERNAME=", greeter_id);
+    if (g_str_has_prefix (request, r))
+    {
+        LightDMUser *user;
+        const gchar *username;
+
+        username = request + strlen (r);
+        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
+        status_notify ("%s LOG-USER USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+    }
+    g_free (r);
+
+    r = g_strdup_printf ("%s LOG-USER-LIST", greeter_id);
+    if (strcmp (request, r) == 0)
+    {
+        GList *users, *link;
+
+        users = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
+        for (link = users; link; link = link->next)
+        {
+            LightDMUser *user = link->data;
+            status_notify ("%s LOG-USER USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+        }
+    }
+    g_free (r);
+
     r = g_strdup_printf ("%s LOG-LAYOUT USERNAME=", greeter_id);
     if (g_str_has_prefix (request, r))
     {
@@ -238,6 +269,18 @@ request_cb (const gchar *request)
     g_free (r);
 }
 
+static void
+user_added_cb (LightDMUserList *user_list, LightDMUser *user)
+{
+    status_notify ("%s USER-ADDED USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+}
+
+static void
+user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
+{
+    status_notify ("%s USER-REMOVED USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+}
+
 int
 main (int argc, char **argv)
 {
@@ -290,6 +333,12 @@ main (int argc, char **argv)
     g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
     g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
 
+    if (g_key_file_get_boolean (config, "test-greeter-config", "log-user-changes", NULL))
+    {
+        g_signal_connect (lightdm_user_list_get_instance (), "user-added", G_CALLBACK (user_added_cb), NULL);
+        g_signal_connect (lightdm_user_list_get_instance (), "user-removed", G_CALLBACK (user_removed_cb), NULL);
+    }
+
     status_notify ("%s CONNECT-TO-DAEMON", greeter_id);
     if (!lightdm_greeter_connect_sync (greeter, NULL))
     {
index b5b02eee6d0777f00a43605a8b929d946a7ef00e..d4fb818a12ed815068c5995e5eca95d70a510e70 100755 (executable)
@@ -79,6 +79,22 @@ def request_cb (channel, condition):
         if not greeter.start_session_sync (request[len(r):]):
             status_notify ('%s SESSION-FAILED' % greeter_id)
 
+    r = '%s LOG-USER-LIST-LENGTH' % greeter_id
+    if request == r:
+        status_notify ('%s LOG-USER-LIST-LENGTH N=%d' % (greeter_id, LightDM.UserList.get_instance ().get_length ()))
+
+    r = '%s LOG-USER USERNAME=' % greeter_id
+    if request.startswith (r):
+        username = request[len(r):]
+        user = LightDM.UserList.get_instance ().get_user_by_name (username)
+        status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))
+
+    r = '%s LOG-USER-LIST' % greeter_id
+    if request == r:
+        users = LightDM.UserList.get_instance ().get_users ();
+        for user in users:
+            status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))
+
     r = '%s LOG-LAYOUT' % greeter_id
     if request == r:
         layout = LightDM.get_layout ().get_name ()
@@ -96,8 +112,8 @@ def request_cb (channel, condition):
     r = '%s LOG-LANGUAGE USERNAME=' % greeter_id
     if request.startswith (r):
         username = request[len(r):]
-        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username)
-        language = lightdm_user_get_language (user)
+        user = LightDM.UserList.get_instance ().get_user_by_name (username)
+        language = user.get_language ()
         if language is None:
             language = ''
         status_notify ('%s LOG-LANGUAGE USERNAME=%s LANGUAGE=%s' % (greeter_id, username, language))
@@ -171,6 +187,9 @@ GLib.io_add_watch (status_socket.fileno (), GLib.IO_IN | GLib.IO_HUP, request_cb
 
 status_notify ('%s START' % greeter_id)
 
+config = GLib.KeyFile ()
+config.load_from_file (os.getenv ('LIGHTDM_TEST_ROOT') + '/script', GLib.KeyFileFlags.NONE)
+
 # NOTE: There don't seem to be any good X bindings so we have to mock up our own...
 (host, display_number) = display.split (':')
 if host == '':
@@ -221,6 +240,19 @@ greeter.connect ('show-prompt', show_prompt_cb)
 greeter.connect ('authentication-complete', authentication_complete_cb)
 greeter.connect ('autologin-timer-expired', autologin_timer_expired_cb)
 
+def user_added_cb (user_list, user):
+    status_notify ('%s USER-ADDED USERNAME=%s' % (greeter_id, user.get_name ()))
+def user_removed_cb (user_list, user):
+    status_notify ('%s USER-REMOVED USERNAME=%s' % (greeter_id, user.get_name ()))
+log_user_changes = False
+try:
+    log_user_changes = config.get_boolean ('test-greeter-config', 'log-user-changes')
+except:
+    pass
+if log_user_changes:
+    LightDM.UserList.get_instance ().connect ('user-added', user_added_cb)
+    LightDM.UserList.get_instance ().connect ('user-removed', user_removed_cb)
+
 status_notify ('%s CONNECT-TO-DAEMON' % greeter_id)
 if not greeter.connect_sync ():
     status_notify ('%s FAIL-CONNECT-DAEMON' % greeter_id)
index b6a591deab168744db429e7699ccbc3fac79b0c3..99c0110799c35bbf0b092cda0b7f61cd4d7050d9 100644 (file)
@@ -6,6 +6,7 @@
 #include <xcb/xcb.h>
 #include <QLightDM/Greeter>
 #include <QLightDM/Power>
+#include <QLightDM/UsersModel>
 #include <QtCore/QSettings>
 #include <QtCore/QDebug>
 #include <QtCore/QCoreApplication>
@@ -18,6 +19,7 @@ static QCoreApplication *app = NULL;
 static QSettings *config = NULL;
 static QLightDM::PowerInterface *power = NULL;
 static TestGreeter *greeter = NULL;
+static QLightDM::UsersModel *users_model = NULL;
 
 TestGreeter::TestGreeter ()
 {
@@ -52,6 +54,24 @@ void TestGreeter::autologinTimerExpired ()
     status_notify ("%s AUTOLOGIN-TIMER-EXPIRED", greeter_id);
 }
 
+void TestGreeter::userRowsInserted (const QModelIndex & parent, int start, int end)
+{
+    for (int i = start; i <= end; i++)
+    {
+        QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+        status_notify ("%s USER-ADDED USERNAME=%s", greeter_id, qPrintable (name));
+    }
+}
+
+void TestGreeter::userRowsRemoved (const QModelIndex & parent, int start, int end)
+{
+    for (int i = start; i <= end; i++)
+    {
+        QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+        status_notify ("%s USER-REMOVED USERNAME=%s", greeter_id, qPrintable (name));
+    }
+}
+
 static void
 signal_cb (int signum)
 {
@@ -126,6 +146,35 @@ request_cb (const gchar *request)
     }
     g_free (r);
 
+    r = g_strdup_printf ("%s LOG-USER-LIST-LENGTH", greeter_id);
+    if (strcmp (request, r) == 0)
+        status_notify ("%s LOG-USER-LIST-LENGTH N=%d", greeter_id, users_model->rowCount (QModelIndex ()));
+    g_free (r);
+
+    r = g_strdup_printf ("%s LOG-USER USERNAME=", greeter_id);
+    if (g_str_has_prefix (request, r))
+    {
+        const gchar *username = request + strlen (r);
+        for (int i = 0; i < users_model->rowCount (QModelIndex ()); i++)
+        {
+            QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+            if (name == username)
+                status_notify ("%s LOG-USER USERNAME=%s", greeter_id, qPrintable (name));
+        }
+    }
+    g_free (r);
+
+    r = g_strdup_printf ("%s LOG-USER-LIST", greeter_id);
+    if (strcmp (request, r) == 0)
+    {
+        for (int i = 0; i < users_model->rowCount (QModelIndex ()); i++)
+        {
+            QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+            status_notify ("%s LOG-USER USERNAME=%s", greeter_id, qPrintable (name));
+        }
+    }
+    g_free (r);
+
     r = g_strdup_printf ("%s GET-CAN-SUSPEND", greeter_id);
     if (strcmp (request, r) == 0)
     {
@@ -232,7 +281,14 @@ main(int argc, char *argv[])
     power = new QLightDM::PowerInterface();
 
     greeter = new TestGreeter();
-  
+
+    users_model = new QLightDM::UsersModel();
+    if (config->value ("test-greeter-config/log-user-changes", "false") == "true")
+    {
+        QObject::connect (users_model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), greeter, SLOT(userRowsInserted(const QModelIndex&, int, int)));
+        QObject::connect (users_model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), greeter, SLOT(userRowsRemoved(const QModelIndex&, int, int)));
+    }
+
     status_notify ("%s CONNECT-TO-DAEMON", greeter_id);
     if (!greeter->connectSync())
     {
index 99370996044f19a0f9f686e1704a3df722f83b23..10a10db062189eef470bd01ff16af0d6d37f685b 100644 (file)
@@ -1,4 +1,5 @@
 #include <QLightDM/Greeter>
+#include <QLightDM/UsersModel>
 
 class TestGreeter : public QLightDM::Greeter
 {
@@ -12,4 +13,6 @@ private Q_SLOTS:
     void showPrompt(QString text, QLightDM::Greeter::PromptType type);
     void authenticationComplete();
     void autologinTimerExpired();
+    void userRowsInserted(const QModelIndex & parent, int start, int end);
+    void userRowsRemoved(const QModelIndex & parent, int start, int end);
 };
index d64f5f685ab140dcb705f9b81d61e53fc2c8609b..fb43233b91ced5a490d00b8f77545612d5ccd5e2 100644 (file)
@@ -55,6 +55,7 @@ typedef struct
     gchar *language;
     gchar *xsession;
     gchar **layouts;
+    gboolean hidden;
 } AccountsUser;
 static GList *accounts_users = NULL;
 static void handle_user_call (GDBusConnection       *connection,
@@ -119,6 +120,9 @@ static GList *status_clients = NULL;
 static void run_lightdm (void);
 static void quit (int status);
 static void check_status (const gchar *status);
+static AccountsUser *get_accounts_user_by_uid (guint uid);
+static AccountsUser *get_accounts_user_by_name (const gchar *username);
+static void accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal);
 
 static gboolean
 kill_timeout_cb (gpointer data)
@@ -494,6 +498,38 @@ handle_command (const gchar *command)
             g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
         }
     }
+    else if (strcmp (name, "ADD-USER") == 0)
+    {
+        gchar *status_text, *username;
+        AccountsUser *user;
+
+        username = g_hash_table_lookup (params, "USERNAME");
+        user = get_accounts_user_by_name (username);
+        if (user)
+            accounts_user_set_hidden (user, FALSE, TRUE);
+        else
+            g_warning ("Unknown user %s", username);
+
+        status_text = g_strdup_printf ("RUNNER ADD-USER USERNAME=%s", username);
+        check_status (status_text);
+        g_free (status_text);
+    }
+    else if (strcmp (name, "DELETE-USER") == 0)
+    {
+        gchar *status_text, *username;
+        AccountsUser *user;
+
+        username = g_hash_table_lookup (params, "USERNAME");
+        user = get_accounts_user_by_name (username);
+        if (user)
+            accounts_user_set_hidden (user, TRUE, TRUE);
+        else
+            g_warning ("Unknown user %s", username);
+
+        status_text = g_strdup_printf ("RUNNER DELETE-USER USERNAME=%s", username);
+        check_status (status_text);
+        g_free (status_text);
+    }
     /* Forward to external processes */
     else if (g_str_has_prefix (name, "SESSION-") ||
              g_str_has_prefix (name, "GREETER-") ||
@@ -1235,12 +1271,101 @@ start_login1_daemon ()
                     NULL);
 }
 
+static AccountsUser *
+get_accounts_user_by_uid (guint uid)
+{
+    GList *link;
+
+    for (link = accounts_users; link; link = link->next)
+    {
+        AccountsUser *u = link->data;
+        if (u->uid == uid)
+            return u;
+    }
+  
+    return NULL;
+}
+
+static AccountsUser *
+get_accounts_user_by_name (const gchar *username)
+{
+    GList *link;
+
+    for (link = accounts_users; link; link = link->next)
+    {
+        AccountsUser *u = link->data;
+        if (strcmp (u->user_name, username) == 0)
+            return u;
+    }
+
+    return NULL;
+}
+
+static void
+accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal)
+{
+    GError *error = NULL;
+
+    user->hidden = hidden;
+
+    if (user->hidden && user->id != 0)
+    {
+        g_dbus_connection_unregister_object (accounts_connection, user->id);
+        g_dbus_connection_emit_signal (accounts_connection,
+                                       NULL,
+                                       "/org/freedesktop/Accounts",
+                                       "org.freedesktop.Accounts",
+                                       "UserDeleted",
+                                       g_variant_new ("(o)", user->path),
+                                       &error);
+        if (error)
+            g_warning ("Failed to emit UserDeleted: %s", error->message);
+        g_clear_error (&error);
+
+        user->id = 0;
+    }
+    if (!user->hidden && user->id == 0)
+    {
+        user->id = g_dbus_connection_register_object (accounts_connection,
+                                                      user->path,
+                                                      user_info->interfaces[0],
+                                                      &user_vtable,
+                                                      user,
+                                                      NULL,
+                                                      &error);
+        if (error)
+            g_warning ("Failed to register user: %s", error->message);
+        g_clear_error (&error);
+
+        g_dbus_connection_emit_signal (accounts_connection,
+                                       NULL,
+                                       "/org/freedesktop/Accounts",
+                                       "org.freedesktop.Accounts",
+                                       "UserAdded",
+                                       g_variant_new ("(o)", user->path),
+                                       &error);
+        if (error)
+            g_warning ("Failed to emit UserAdded: %s", error->message);
+        g_clear_error (&error);
+    }
+}
+
 static void
 load_passwd_file ()
 {
     gchar *path, *data, **lines;
+    gchar **user_filter = NULL;
     int i;
 
+    if (g_key_file_has_key (config, "test-runner-config", "accounts-service-user-filter", NULL))
+    {
+        gchar *filter;
+
+        filter = g_key_file_get_string (config, "test-runner-config", "accounts-service-user-filter", NULL);
+        user_filter = g_strsplit (filter, " ", -1);
+        g_free (filter);
+    }
+
     path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
     g_file_get_contents (path, &data, NULL, NULL);
     g_free (path);
@@ -1258,21 +1383,16 @@ load_passwd_file ()
 
         fields = g_strsplit (lines[i], ":", -1);
         if (fields == NULL || g_strv_length (fields) < 7)
+        {
+            g_strfreev (fields);
             continue;
+        }
 
         user_name = fields[0];
         uid = atoi (fields[2]);
         real_name = fields[4];
 
-        for (link = accounts_users; link; link = link->next)
-        {
-            AccountsUser *u = link->data;
-            if (u->uid == uid)
-            {
-                user = u;
-                break;
-            }
-        }
+        user = get_accounts_user_by_uid (uid);
         if (!user)
         {
             gchar *path;
@@ -1281,6 +1401,18 @@ load_passwd_file ()
             user = g_malloc0 (sizeof (AccountsUser));
             accounts_users = g_list_append (accounts_users, user);
 
+            /* Only allow users in whitelist */
+            user->hidden = FALSE;
+            if (user_filter)
+            {
+                int j;
+
+                user->hidden = TRUE;
+                for (j = 0; user_filter[j] != NULL; j++)
+                    if (strcmp (user_name, user_filter[j]) == 0)
+                        user->hidden = FALSE;
+            }
+
             dmrc_file = g_key_file_new ();
             path = g_build_filename (temp_dir, "home", user_name, ".dmrc", NULL);
             g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
@@ -1301,16 +1433,7 @@ load_passwd_file ()
             user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
             user->layouts = g_key_file_get_string_list (dmrc_file, "X-Accounts", "Layouts", NULL, NULL);
             user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid);
-            user->id = g_dbus_connection_register_object (accounts_connection,
-                                                          user->path,
-                                                          user_info->interfaces[0],
-                                                          &user_vtable,
-                                                          user,
-                                                          NULL,
-                                                          &error);
-            if (error)
-                g_warning ("Failed to register user: %s", error->message);
-            g_clear_error (&error);
+            accounts_user_set_hidden (user, user->hidden, FALSE);
 
             g_key_file_free (dmrc_file);
         }
@@ -1342,7 +1465,8 @@ handle_accounts_call (GDBusConnection       *connection,
         for (link = accounts_users; link; link = link->next)
         {
             AccountsUser *user = link->data;
-            g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
+            if (!user->hidden)
+                g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
         }
 
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ao)", &builder));
@@ -1356,16 +1480,8 @@ handle_accounts_call (GDBusConnection       *connection,
         g_variant_get (parameters, "(&s)", &user_name);
 
         load_passwd_file ();
-        for (link = accounts_users; link; link = link->next)
-        {
-            AccountsUser *u = link->data;
-            if (strcmp (u->user_name, user_name) == 0)
-            {
-                user = u;
-                break;
-            }
-        }
-        if (user)
+        user = get_accounts_user_by_name (user_name);
+        if (user && !user->hidden)
             g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", user->path));
         else
             g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such user: %s", user_name);
@@ -1452,6 +1568,12 @@ accounts_name_acquired_cb (GDBusConnection *connection,
         "      <arg name='name' direction='in' type='s'/>"
         "      <arg name='user' direction='out' type='o'/>"
         "    </method>"
+        "    <signal name='UserAdded'>"
+        "      <arg name='user' type='o'/>"
+        "    </signal>"
+        "    <signal name='UserDeleted'>"
+        "      <arg name='user' type='o'/>"
+        "    </signal>"
         "  </interface>"
         "</node>";
     static const GDBusInterfaceVTable accounts_vtable =
diff --git a/tests/test-users-gobject b/tests/test-users-gobject
new file mode 100755 (executable)
index 0000000..aee83cb
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-gobject-greeter
diff --git a/tests/test-users-python b/tests/test-users-python
new file mode 100755 (executable)
index 0000000..88edefc
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-python-greeter
diff --git a/tests/test-users-qt4 b/tests/test-users-qt4
new file mode 100755 (executable)
index 0000000..4899ffc
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-qt4-greeter
diff --git a/tests/test-users-qt5 b/tests/test-users-qt5
new file mode 100755 (executable)
index 0000000..3638fc0
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-qt5-greeter