]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - tests/src/test-runner.c
Fix warning about status timeout
[sojka/lightdm.git] / tests / src / test-runner.c
index ed39d114e8097b723a8de5c3c27099e713ba30cd..018007046f71256aaa1d644c3ca82e3d70fbe86c 100644 (file)
@@ -81,7 +81,6 @@ static const GDBusInterfaceVTable user_vtable =
     handle_user_call,
     handle_user_get_property,
 };
-static GDBusConnection *ck_connection = NULL;
 static GDBusNodeInfo *ck_session_info;
 typedef struct
 {
@@ -107,6 +106,22 @@ static const GDBusInterfaceVTable ck_session_vtable =
 
 typedef struct
 {
+    gchar *id;
+    gchar *path;
+    gboolean can_graphical;
+    gboolean can_multi_session;
+    gchar *active_session;
+} Login1Seat;
+
+static GList *login1_seats = NULL;
+
+static Login1Seat *add_login1_seat (GDBusConnection *connection, const gchar *id, gboolean emit_signal);
+static Login1Seat *find_login1_seat (const gchar *id);
+static void remove_login1_seat (GDBusConnection *connection, const gchar *id);
+
+typedef struct
+{
+    gchar *id;
     gchar *path;
     guint pid;
     gboolean locked;
@@ -122,21 +137,26 @@ typedef struct
 } StatusClient;
 static GList *status_clients = NULL;
 
-static void run_lightdm (void);
+static void ready (void);
 static void quit (int status);
+static gboolean status_timeout_cb (gpointer data);
 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 Login1Session *find_login1_session (const gchar *id);
 
 static gboolean
 kill_timeout_cb (gpointer data)
 {
     Process *process = data;
 
+    process->kill_timeout = 0;
+
     if (getenv ("DEBUG"))
         g_print ("Sending SIGKILL to process %d\n", process->pid);
     kill (process->pid, SIGKILL);
+
     return FALSE;
 }
 
@@ -319,6 +339,78 @@ get_script_line (const gchar *prefix)
     return NULL;
 }
 
+static gboolean
+stop_loop (gpointer user_data)
+{
+    g_main_loop_quit ((GMainLoop *)user_data);
+    return G_SOURCE_REMOVE;
+}
+
+static void
+switch_to_greeter_done_cb (GObject *bus, GAsyncResult *result, gpointer data)
+{
+    GVariant *r;
+    GError *error = NULL;
+
+    r = g_dbus_connection_call_finish (G_DBUS_CONNECTION (bus), result, &error);
+    if (error)
+        g_warning ("Failed to switch to greeter: %s\n", error->message);
+    g_clear_error (&error);
+
+    if (r)
+    {
+        check_status ("RUNNER SWITCH-TO-GREETER");
+        g_variant_unref (r);
+    }
+    else
+        check_status ("RUNNER SWITCH-TO-GREETER FAILED");
+}
+
+static void
+switch_to_user_done_cb (GObject *bus, GAsyncResult *result, gpointer data)
+{
+    GVariant *r;
+    GError *error = NULL;
+    gchar *username = data, *status_text;
+
+    r = g_dbus_connection_call_finish (G_DBUS_CONNECTION (bus), result, &error);
+    if (error)
+        g_warning ("Failed to switch to user: %s\n", error->message);
+    g_clear_error (&error);
+
+    if (r)
+    {
+        status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s", username);
+        g_variant_unref (r);
+    }
+    else
+        status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s FAILED", username);
+    check_status (status_text);
+
+    g_free (status_text);
+    g_free (username);
+}
+
+static void
+switch_to_guest_done_cb (GObject *bus, GAsyncResult *result, gpointer data)
+{
+    GVariant *r;
+    GError *error = NULL;
+
+    r = g_dbus_connection_call_finish (G_DBUS_CONNECTION (bus), result, &error);
+    if (error)
+        g_warning ("Failed to switch to guest: %s\n", error->message);
+    g_clear_error (&error);
+
+    if (r)
+    {
+        check_status ("RUNNER SWITCH-TO-GUEST");
+        g_variant_unref (r);
+    }
+    else
+        check_status ("RUNNER SWITCH-TO-GUEST FAILED");
+}
+
 static void
 handle_command (const gchar *command)
 {
@@ -396,9 +488,147 @@ handle_command (const gchar *command)
         g_hash_table_insert (params, param_name, param_value);
     }
 
-    if (strcmp (name, "WAIT") == 0)
+    if (strcmp (name, "START-DAEMON") == 0)
+    {
+        GString *command_line;
+        gchar **lightdm_argv;
+        pid_t lightdm_pid;
+        GError *error = NULL;
+
+        command_line = g_string_new ("lightdm");
+        if (getenv ("DEBUG"))
+            g_string_append (command_line, " --debug");
+        g_string_append_printf (command_line, " --cache-dir %s/cache", temp_dir);
+
+        test_runner_command = g_strdup_printf ("PATH=%s LD_PRELOAD=%s LD_LIBRARY_PATH=%s LIGHTDM_TEST_ROOT=%s DBUS_SESSION_BUS_ADDRESS=%s %s\n",
+                                               g_getenv ("PATH"), g_getenv ("LD_PRELOAD"), g_getenv ("LD_LIBRARY_PATH"), g_getenv ("LIGHTDM_TEST_ROOT"), g_getenv ("DBUS_SESSION_BUS_ADDRESS"),
+                                               command_line->str);
+
+        if (!g_shell_parse_argv (command_line->str, NULL, &lightdm_argv, &error))
+        {
+            g_warning ("Error parsing command line: %s", error->message);
+            quit (EXIT_FAILURE);
+        }
+        g_clear_error (&error);
+
+        if (!g_spawn_async (NULL, lightdm_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &lightdm_pid, &error))
+        {
+            g_warning ("Error launching LightDM: %s", error->message);
+            quit (EXIT_FAILURE);
+        }
+        g_clear_error (&error);
+        lightdm_process = watch_process (lightdm_pid);
+
+        check_status ("RUNNER DAEMON-START");
+    }
+    else if (strcmp (name, "WAIT") == 0)
     {
-        sleep (1);
+        const gchar *v;
+        int duration;
+
+        /* Stop status timeout */
+        if (status_timeout)
+            g_source_remove (status_timeout);
+        status_timeout = 0;
+
+        /* Use a main loop so that our DBus functions are still responsive */
+        GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+        v = g_hash_table_lookup (params, "DURATION");
+        duration = v ? atoi (v) : 1;
+        if (duration < 1)
+            duration = 1;
+        g_timeout_add_seconds (duration, stop_loop, loop);
+        g_main_loop_run (loop);
+        g_main_loop_unref (loop);
+
+        /* Restart status timeout */
+        status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
+    }
+    else if (strcmp (name, "ADD-SEAT") == 0)
+    {
+        const gchar *id, *v;
+        Login1Seat *seat;
+
+        id = g_hash_table_lookup (params, "ID");
+        seat = add_login1_seat (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL), id, TRUE);
+        v = g_hash_table_lookup (params, "CAN-GRAPHICAL");
+        if (v)
+            seat->can_graphical = strcmp (v, "TRUE") == 0;
+        v = g_hash_table_lookup (params, "CAN-MULTI-SESSION");
+        if (v)
+            seat->can_multi_session = strcmp (v, "TRUE") == 0;
+    }
+    else if (strcmp (name, "ADD-LOCAL-X-SEAT") == 0)
+    {
+        GVariant *result;
+        const gchar *v;
+
+        v = g_hash_table_lookup (params, "DISPLAY");
+        result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                              "org.freedesktop.DisplayManager",
+                                              "/org/freedesktop/DisplayManager",
+                                              "org.freedesktop.DisplayManager",
+                                              "AddLocalXSeat",
+                                              g_variant_new ("(i)", v ? atoi (v) : -1),
+                                              G_VARIANT_TYPE ("(o)"),
+                                              G_DBUS_CALL_FLAGS_NONE,
+                                              G_MAXINT,
+                                              NULL,
+                                              NULL);
+        g_variant_unref (result);
+    }
+    else if (strcmp (name, "UPDATE-SEAT") == 0)
+    {
+        Login1Seat *seat;
+        const gchar *id;
+
+        id = g_hash_table_lookup (params, "ID");
+        seat = find_login1_seat (id);
+        if (seat)
+        {
+            const gchar *v;
+            GVariantBuilder invalidated_properties;
+            GError *error = NULL;
+
+            g_variant_builder_init (&invalidated_properties, G_VARIANT_TYPE_ARRAY);
+
+            v = g_hash_table_lookup (params, "CAN-GRAPHICAL");
+            if (v)
+            {
+                seat->can_graphical = strcmp (v, "TRUE") == 0;
+                g_variant_builder_add (&invalidated_properties, "s", "CanGraphical");
+            }
+            v = g_hash_table_lookup (params, "CAN-MULTI-SESSION");
+            if (v)
+            {
+                seat->can_multi_session = strcmp (v, "TRUE") == 0;
+                g_variant_builder_add (&invalidated_properties, "s", "CanMultiSession");
+            }
+            v = g_hash_table_lookup (params, "ACTIVE-SESSION");
+            if (v)
+            {
+                g_free (seat->active_session);
+                seat->active_session = g_strdup (v);
+                g_variant_builder_add (&invalidated_properties, "s", "ActiveSession");
+            }
+
+            g_dbus_connection_emit_signal (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                           NULL,
+                                           seat->path,
+                                           "org.freedesktop.DBus.Properties",
+                                           "PropertiesChanged",
+                                           g_variant_new ("(sa{sv}as)", "org.freedesktop.login1.Seat", NULL, &invalidated_properties),
+                                           &error);
+            if (error)
+                g_warning ("Failed to emit PropertiesChanged: %s", error->message);
+            g_clear_error (&error);
+        }
+    }
+    else if (strcmp (name, "REMOVE-SEAT") == 0)
+    {
+        const gchar *id;
+        id = g_hash_table_lookup (params, "ID");
+        remove_login1_seat (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL), id);
     }
     else if (strcmp (name, "LIST-SEATS") == 0)
     {
@@ -416,7 +646,7 @@ handle_command (const gchar *command)
                                               g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Seats"),
                                               G_VARIANT_TYPE ("(v)"),
                                               G_DBUS_CALL_FLAGS_NONE,
-                                              1000,
+                                              G_MAXINT,
                                               NULL,
                                               NULL);
 
@@ -452,7 +682,7 @@ handle_command (const gchar *command)
                                               g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
                                               G_VARIANT_TYPE ("(v)"),
                                               G_DBUS_CALL_FLAGS_NONE,
-                                              1000,
+                                              G_MAXINT,
                                               NULL,
                                               NULL);
 
@@ -472,55 +702,101 @@ handle_command (const gchar *command)
         check_status (status->str);
         g_string_free (status, TRUE);
     }
+    else if (strcmp (name, "SEAT-CAN-SWITCH") == 0)
+    {
+        GVariant *result, *value;
+        gchar *status;
+
+        result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                              "org.freedesktop.DisplayManager",
+                                              "/org/freedesktop/DisplayManager/Seat0",
+                                              "org.freedesktop.DBus.Properties",
+                                              "Get",
+                                              g_variant_new ("(ss)", "org.freedesktop.DisplayManager.Seat", "CanSwitch"),
+                                              G_VARIANT_TYPE ("(v)"),
+                                              G_DBUS_CALL_FLAGS_NONE,
+                                              G_MAXINT,
+                                              NULL,
+                                              NULL);
+
+        g_variant_get (result, "(v)", &value);
+        status = g_strdup_printf ("RUNNER SEAT-CAN-SWITCH CAN-SWITCH=%s", g_variant_get_boolean (value) ? "TRUE" : "FALSE");
+        g_variant_unref (value);
+        g_variant_unref (result);
+        check_status (status);
+        g_free (status);
+    }
+    else if (strcmp (name, "SEAT-HAS-GUEST-ACCOUNT") == 0)
+    {
+        GVariant *result, *value;
+        gchar *status;
+
+        result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                              "org.freedesktop.DisplayManager",
+                                              "/org/freedesktop/DisplayManager/Seat0",
+                                              "org.freedesktop.DBus.Properties",
+                                              "Get",
+                                              g_variant_new ("(ss)", "org.freedesktop.DisplayManager.Seat", "HasGuestAccount"),
+                                              G_VARIANT_TYPE ("(v)"),
+                                              G_DBUS_CALL_FLAGS_NONE,
+                                              G_MAXINT,
+                                              NULL,
+                                              NULL);
+
+        g_variant_get (result, "(v)", &value);
+        status = g_strdup_printf ("RUNNER SEAT-HAS-GUEST-ACCOUNT HAS-GUEST-ACCOUNT=%s", g_variant_get_boolean (value) ? "TRUE" : "FALSE");
+        g_variant_unref (value);
+        g_variant_unref (result);
+        check_status (status);
+        g_free (status);
+    }
     else if (strcmp (name, "SWITCH-TO-GREETER") == 0)
     {
-        g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
-                                     "org.freedesktop.DisplayManager",
-                                     "/org/freedesktop/DisplayManager/Seat0",
-                                     "org.freedesktop.DisplayManager.Seat",
-                                     "SwitchToGreeter",
-                                     g_variant_new ("()"),
-                                     G_VARIANT_TYPE ("()"),
-                                     G_DBUS_CALL_FLAGS_NONE,
-                                     1000,
-                                     NULL,
-                                     NULL);
-        check_status ("RUNNER SWITCH-TO-GREETER");
+        g_dbus_connection_call (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                "org.freedesktop.DisplayManager",
+                                "/org/freedesktop/DisplayManager/Seat0",
+                                "org.freedesktop.DisplayManager.Seat",
+                                "SwitchToGreeter",
+                                g_variant_new ("()"),
+                                G_VARIANT_TYPE ("()"),
+                                G_DBUS_CALL_FLAGS_NONE,
+                                G_MAXINT,
+                                NULL,
+                                switch_to_greeter_done_cb,
+                                NULL);
     }
     else if (strcmp (name, "SWITCH-TO-USER") == 0)
     {
-        gchar *status_text, *username;
+        const gchar *username;
 
         username = g_hash_table_lookup (params, "USERNAME");
-        g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
-                                     "org.freedesktop.DisplayManager",
-                                     "/org/freedesktop/DisplayManager/Seat0",
-                                     "org.freedesktop.DisplayManager.Seat",
-                                     "SwitchToUser",
-                                     g_variant_new ("(ss)", username, ""),
-                                     G_VARIANT_TYPE ("()"),
-                                     G_DBUS_CALL_FLAGS_NONE,
-                                     1000,
-                                     NULL,
-                                     NULL);
-        status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s", username);
-        check_status (status_text);
-        g_free (status_text);
+        g_dbus_connection_call (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                "org.freedesktop.DisplayManager",
+                                "/org/freedesktop/DisplayManager/Seat0",
+                                "org.freedesktop.DisplayManager.Seat",
+                                "SwitchToUser",
+                                g_variant_new ("(ss)", username, ""),
+                                G_VARIANT_TYPE ("()"),
+                                G_DBUS_CALL_FLAGS_NONE,
+                                G_MAXINT,
+                                NULL,
+                                switch_to_user_done_cb,
+                                g_strdup (username));
     }
     else if (strcmp (name, "SWITCH-TO-GUEST") == 0)
     {
-        g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
-                                     "org.freedesktop.DisplayManager",
-                                     "/org/freedesktop/DisplayManager/Seat0",
-                                     "org.freedesktop.DisplayManager.Seat",
-                                     "SwitchToGuest",
-                                     g_variant_new ("(s)", ""),
-                                     G_VARIANT_TYPE ("()"),
-                                     G_DBUS_CALL_FLAGS_NONE,
-                                     1000,
-                                     NULL,
-                                     NULL);
-        check_status ("RUNNER SWITCH-TO-GUEST");
+        g_dbus_connection_call (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                "org.freedesktop.DisplayManager",
+                                "/org/freedesktop/DisplayManager/Seat0",
+                                "org.freedesktop.DisplayManager.Seat",
+                                "SwitchToGuest",
+                                g_variant_new ("(s)", ""),
+                                G_VARIANT_TYPE ("()"),
+                                G_DBUS_CALL_FLAGS_NONE,
+                                G_MAXINT,
+                                NULL,
+                                switch_to_guest_done_cb,
+                                NULL);
     }
     else if (strcmp (name, "STOP-DAEMON") == 0)
         stop_process (lightdm_process);
@@ -651,17 +927,18 @@ handle_command (const gchar *command)
                 user->xsession = g_strdup (g_hash_table_lookup (params, "SESSION"));
                 g_string_append_printf (status_text, " SESSION=%s", user->xsession);
             }
+
+            g_dbus_connection_emit_signal (accounts_connection,
+                                           NULL,
+                                           user->path,
+                                           "org.freedesktop.Accounts.User",
+                                           "Changed",
+                                           g_variant_new ("()"),
+                                           &error);
         }
         else
             g_warning ("Unknown user %s", username);
 
-        g_dbus_connection_emit_signal (accounts_connection,
-                                       NULL,
-                                       user->path,
-                                       "org.freedesktop.Accounts.User",
-                                       "Changed",
-                                       g_variant_new ("()"),
-                                       &error);
         if (error)
             g_warning ("Failed to emit Changed: %s", error->message);
         g_clear_error (&error);
@@ -685,10 +962,32 @@ handle_command (const gchar *command)
         check_status (status_text);
         g_free (status_text);
     }
+    else if (strcmp (name, "UNLOCK-SESSION") == 0)
+    {
+        gchar *status_text, *id;
+        Login1Session *session;
+        
+        id = g_hash_table_lookup (params, "SESSION");
+        session = find_login1_session (id);
+        if (session)
+        {
+            if (!session->locked)
+                g_warning ("Session %s is not locked", id);
+            session->locked = FALSE;
+        }
+        else
+            g_warning ("Unknown session %s", id);
+
+        status_text = g_strdup_printf ("RUNNER UNLOCK-SESSION SESSION=%s", id);
+        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-") ||
              g_str_has_prefix (name, "XSERVER-") ||
+             g_str_has_prefix (name, "XMIR-") ||
+             g_str_has_prefix (name, "XVNC-") ||
              strcmp (name, "UNITY-SYSTEM-COMPOSITOR") == 0)
     {
         GList *link;
@@ -744,10 +1043,12 @@ status_timeout_cb (gpointer data)
 {
     ScriptLine *line;
 
+    status_timeout = 0;
+
     line = get_script_line (NULL);
     fail ("(timeout)", line ? line->text : NULL);
 
-    return FALSE;
+    return G_SOURCE_REMOVE;
 }
 
 static void
@@ -787,7 +1088,8 @@ check_status (const gchar *status)
     line->done = TRUE;
 
     /* Restart timeout */
-    g_source_remove (status_timeout);
+    if (status_timeout)
+        g_source_remove (status_timeout);
     status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
 
     run_commands ();
@@ -958,7 +1260,7 @@ upower_name_acquired_cb (GDBusConnection *connection,
 
     service_count--;
     if (service_count == 0)
-        run_lightdm ();
+        ready ();
 }
 
 static void
@@ -976,7 +1278,7 @@ start_upower_daemon (void)
 }
 
 static CKSession *
-open_ck_session (GVariant *params)
+open_ck_session (GDBusConnection *connection, GVariant *params)
 {
     CKSession *session;
     GString *cookie;
@@ -1003,7 +1305,7 @@ open_ck_session (GVariant *params)
     session->cookie = cookie->str;
     g_string_free (cookie, FALSE);
     session->path = g_strdup_printf ("/org/freedesktop/ConsoleKit/Session%d", ck_session_index++);
-    session->id = g_dbus_connection_register_object (ck_connection,
+    session->id = g_dbus_connection_register_object (connection,
                                                      session->path,
                                                      ck_session_info->interfaces[0],
                                                      &ck_session_vtable,
@@ -1043,12 +1345,12 @@ handle_ck_call (GDBusConnection       *connection,
     {
         GVariantBuilder params;
         g_variant_builder_init (&params, G_VARIANT_TYPE ("a(sv)"));
-        CKSession *session = open_ck_session (g_variant_builder_end (&params));
+        CKSession *session = open_ck_session (connection, g_variant_builder_end (&params));
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
     }
     else if (strcmp (method_name, "OpenSessionWithParameters") == 0)
     {
-        CKSession *session = open_ck_session (g_variant_get_child_value (parameters, 0));
+        CKSession *session = open_ck_session (connection, g_variant_get_child_value (parameters, 0));
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
     }
     else if (strcmp (method_name, "GetSessionForCookie") == 0)
@@ -1061,7 +1363,7 @@ handle_ck_call (GDBusConnection       *connection,
         for (link = ck_sessions; link; link = link->next)
         {
             CKSession *session = link->data;
-            if (strcmp (session->cookie, cookie) != 0)
+            if (strcmp (session->cookie, cookie) == 0)
             {
                 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", session->path));
                 return;
@@ -1096,8 +1398,12 @@ handle_ck_session_call (GDBusConnection       *connection,
 {
     CKSession *session = user_data;
 
-    if (strcmp (method_name, "Lock") == 0)
-    { 
+    if (strcmp (method_name, "GetXDGRuntimeDir") == 0 && !g_key_file_get_boolean (config, "test-runner-config", "ck-no-xdg-runtime", NULL))
+    {
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "/run/console-kit"));
+    }
+    else if (strcmp (method_name, "Lock") == 0)
+    {
         if (!session->locked)
             check_status ("CONSOLE-KIT LOCK-SESSION");
         session->locked = TRUE;
@@ -1110,6 +1416,14 @@ handle_ck_session_call (GDBusConnection       *connection,
         session->locked = FALSE;
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
     }
+    else if (strcmp (method_name, "Activate") == 0)
+    {
+        gchar *status = g_strdup_printf ("CONSOLE-KIT ACTIVATE-SESSION SESSION=%s", session->cookie);
+        check_status (status);
+        g_free (status);
+
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+    }
     else
         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
 }
@@ -1157,25 +1471,38 @@ ck_name_acquired_cb (GDBusConnection *connection,
     {
         handle_ck_call,
     };
+    const gchar *ck_session_interface_old =
+        "<node>"
+        "  <interface name='org.freedesktop.ConsoleKit.Session'>"
+        "    <method name='Lock'/>"
+        "    <method name='Unlock'/>"
+        "    <method name='Activate'/>"
+        "  </interface>"
+        "</node>";
     const gchar *ck_session_interface =
         "<node>"
         "  <interface name='org.freedesktop.ConsoleKit.Session'>"
+        "    <method name='GetXDGRuntimeDir'>"
+        "      <arg name='dir' direction='out' type='s'/>"
+        "    </method>"
         "    <method name='Lock'/>"
         "    <method name='Unlock'/>"
+        "    <method name='Activate'/>"
         "  </interface>"
         "</node>";
     GDBusNodeInfo *ck_info;
     GError *error = NULL;
 
-    ck_connection = connection;
-
     ck_info = g_dbus_node_info_new_for_xml (ck_interface, &error);
     if (error)
         g_warning ("Failed to parse D-Bus interface: %s", error->message);
     g_clear_error (&error);
     if (!ck_info)
         return;
-    ck_session_info = g_dbus_node_info_new_for_xml (ck_session_interface, &error);
+    if (g_key_file_get_boolean (config, "test-runner-config", "ck-no-xdg-runtime", NULL))
+        ck_session_info = g_dbus_node_info_new_for_xml (ck_session_interface_old, &error);
+    else
+        ck_session_info = g_dbus_node_info_new_for_xml (ck_session_interface, &error);  
     if (error)
         g_warning ("Failed to parse D-Bus interface: %s", error->message);
     g_clear_error (&error);
@@ -1194,7 +1521,7 @@ ck_name_acquired_cb (GDBusConnection *connection,
 
     service_count--;
     if (service_count == 0)
-        run_lightdm ();
+        ready ();
 }
 
 static void
@@ -1204,13 +1531,173 @@ start_console_kit_daemon (void)
     g_bus_own_name (G_BUS_TYPE_SYSTEM,
                     "org.freedesktop.ConsoleKit",
                     G_BUS_NAME_OWNER_FLAGS_NONE,
-                    ck_name_acquired_cb,
                     NULL,
+                    ck_name_acquired_cb,
                     NULL,
                     NULL,
                     NULL);
 }
 
+static void
+handle_login1_seat_call (GDBusConnection       *connection,
+                         const gchar           *sender,
+                         const gchar           *object_path,
+                         const gchar           *interface_name,
+                         const gchar           *method_name,
+                         GVariant              *parameters,
+                         GDBusMethodInvocation *invocation,
+                         gpointer               user_data)
+{
+    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
+}
+
+static GVariant *
+handle_login1_seat_get_property (GDBusConnection       *connection,
+                                 const gchar           *sender,
+                                 const gchar           *object_path,
+                                 const gchar           *interface_name,
+                                 const gchar           *property_name,
+                                 GError               **error,
+                                 gpointer               user_data)
+{
+    Login1Seat *seat = user_data;
+
+    if (strcmp (property_name, "CanGraphical") == 0)
+        return g_variant_new_boolean (seat->can_graphical);
+    else if (strcmp (property_name, "CanMultiSession") == 0)
+        return g_variant_new_boolean (seat->can_multi_session);
+    else if (strcmp (property_name, "Id") == 0)
+        return g_variant_new_string (seat->id);
+    else if (strcmp (property_name, "ActiveSession") == 0)
+    {
+        if (seat->active_session)
+        {
+            gchar *path;
+            GVariant *ret;
+            
+            path = g_strdup_printf ("/org/freedesktop/login1/session/%s", seat->active_session);
+            ret = g_variant_new ("(so)", seat->active_session, path);
+            g_free (path);
+
+            return ret;
+        }
+        else 
+            return NULL;
+    }
+    else
+        return NULL;
+}
+
+static Login1Seat *
+add_login1_seat (GDBusConnection *connection, const gchar *id, gboolean emit_signal)
+{
+    Login1Seat *seat;
+    GError *error = NULL;
+    GDBusNodeInfo *login1_seat_info;
+
+    const gchar *login1_seat_interface =
+        "<node>"
+        "  <interface name='org.freedesktop.login1.Seat'>"
+        "    <property name='CanGraphical' type='b' access='read'/>"
+        "    <property name='CanMultiSession' type='b' access='read'/>"
+        "    <property name='ActiveSession' type='(so)' access='read'/>"
+        "    <property name='Id' type='s' access='read'/>"
+        "  </interface>"
+        "</node>";
+    static const GDBusInterfaceVTable login1_seat_vtable =
+    {
+        handle_login1_seat_call,
+        handle_login1_seat_get_property,
+    };
+
+    seat = g_malloc0 (sizeof (Login1Seat));
+    login1_seats = g_list_append (login1_seats, seat);
+    seat->id = g_strdup (id);
+    seat->path = g_strdup_printf ("/org/freedesktop/login1/seat/%s", seat->id);
+    seat->can_graphical = TRUE;
+    seat->can_multi_session = TRUE;
+    seat->active_session = NULL;
+
+    login1_seat_info = g_dbus_node_info_new_for_xml (login1_seat_interface, &error);
+    if (error)
+        g_warning ("Failed to parse login1 seat D-Bus interface: %s", error->message);
+    g_clear_error (&error);
+    if (!login1_seat_info)
+        return NULL;
+
+    g_dbus_connection_register_object (connection,
+                                       seat->path,
+                                       login1_seat_info->interfaces[0],
+                                       &login1_seat_vtable,
+                                       seat,
+                                       NULL,
+                                       &error);
+    if (error)
+        g_warning ("Failed to register login1 seat: %s", error->message);
+    g_clear_error (&error);
+    g_dbus_node_info_unref (login1_seat_info);
+
+    if (emit_signal)
+    {
+        g_dbus_connection_emit_signal (connection,
+                                       NULL,
+                                       "/org/freedesktop/login1",
+                                       "org.freedesktop.login1.Manager",
+                                       "SeatNew",
+                                       g_variant_new ("(so)", seat->id, seat->path),
+                                       &error);
+        if (error)
+            g_warning ("Failed to emit SeatNew: %s", error->message);
+        g_clear_error (&error);
+    }
+
+    return seat;
+}
+
+static Login1Seat *
+find_login1_seat (const gchar *id)
+{
+    Login1Seat *seat;
+    GList *link;
+
+    for (link = login1_seats; link; link = link->next)
+    {
+        seat = link->data;
+        if (strcmp (seat->id, id) == 0)
+            return seat;
+    }
+
+    return NULL;
+}
+
+static void
+remove_login1_seat (GDBusConnection *connection, const gchar *id)
+{
+    Login1Seat *seat;
+    GError *error = NULL;
+
+    seat = find_login1_seat (id);
+    if (!seat)
+        return;
+
+    g_dbus_connection_emit_signal (connection,
+                                   NULL,
+                                   "/org/freedesktop/login1",
+                                   "org.freedesktop.login1.Manager",
+                                   "SeatRemoved",
+                                   g_variant_new ("(so)", seat->id, seat->path),
+                                   &error);
+    if (error)
+        g_warning ("Failed to emit SeatNew: %s", error->message);
+    g_clear_error (&error);
+
+    login1_seats = g_list_remove (login1_seats, seat);
+    g_free (seat->id);
+    g_free (seat->path);
+    g_free (seat->active_session);
+    g_free (seat);
+}
+
 static void
 handle_login1_session_call (GDBusConnection       *connection,
                             const gchar           *sender,
@@ -1221,29 +1708,12 @@ handle_login1_session_call (GDBusConnection       *connection,
                             GDBusMethodInvocation *invocation,
                             gpointer               user_data)
 {
-    Login1Session *session = user_data;
-
-    if (strcmp (method_name, "Lock") == 0)
-    {
-        if (!session->locked)
-            check_status ("LOGIN1 LOCK-SESSION");
-        session->locked = TRUE;
-        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
-    }
-    else if (strcmp (method_name, "Unlock") == 0)
-    {
-        if (session->locked)
-            check_status ("LOGIN1 UNLOCK-SESSION");
-        session->locked = FALSE;
-        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
-    }
-    else
-        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
+    /*Login1Session *session = user_data;*/
+    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
 }
 
 static Login1Session *
-open_login1_session (GDBusConnection *connection,
-                     GVariant *params)
+create_login1_session (GDBusConnection *connection)
 {
     Login1Session *session;
     GError *error = NULL;
@@ -1252,8 +1722,6 @@ open_login1_session (GDBusConnection *connection,
     const gchar *login1_session_interface =
         "<node>"
         "  <interface name='org.freedesktop.login1.Session'>"
-        "    <method name='Lock'/>"
-        "    <method name='Unlock'/>"
         "  </interface>"
         "</node>";
     static const GDBusInterfaceVTable login1_session_vtable =
@@ -1264,16 +1732,12 @@ open_login1_session (GDBusConnection *connection,
     session = g_malloc0 (sizeof (Login1Session));
     login1_sessions = g_list_append (login1_sessions, session);
 
-    session->path = g_strdup_printf("/org/freedesktop/login1/Session/c%d",
-                                    login1_session_index++);
+    session->id = g_strdup_printf ("c%d", login1_session_index++);
+    session->path = g_strdup_printf ("/org/freedesktop/login1/Session/%s", session->id);
 
-
-
-    login1_session_info = g_dbus_node_info_new_for_xml (login1_session_interface,
-                                                        &error);
+    login1_session_info = g_dbus_node_info_new_for_xml (login1_session_interface, &error);
     if (error)
-        g_warning ("Failed to parse login1 session D-Bus interface: %s",
-                   error->message);
+        g_warning ("Failed to parse login1 session D-Bus interface: %s", error->message);
     g_clear_error (&error);
     if (!login1_session_info)
         return NULL;
@@ -1293,6 +1757,20 @@ open_login1_session (GDBusConnection *connection,
     return session;
 }
 
+static Login1Session *
+find_login1_session (const gchar *id)
+{
+    GList *link;
+
+    for (link = login1_sessions; link; link = link->next)
+    {
+        Login1Session *session = link->data;
+        if (strcmp (session->id, id) == 0)
+            return session;
+    }
+
+    return NULL;
+}
 
 static void
 handle_login1_call (GDBusConnection       *connection,
@@ -1304,34 +1782,89 @@ handle_login1_call (GDBusConnection       *connection,
                     GDBusMethodInvocation *invocation,
                     gpointer               user_data)
 {
-
-    if (strcmp (method_name, "GetSessionByPID") == 0)
+    if (strcmp (method_name, "ListSeats") == 0)
     {
-        /* Look for a session with our PID, and create one if we don't have one
-           already. */
+        GVariantBuilder seats;
         GList *link;
-        guint pid;
-        Login1Session *ret = NULL;
 
-        g_variant_get (parameters, "(u)", &pid);
+        g_variant_builder_init (&seats, G_VARIANT_TYPE ("a(so)"));
+        for (link = login1_seats; link; link = link->next)
+        {
+            Login1Seat *seat = link->data;
+            g_variant_builder_add (&seats, "(so)", seat->id, seat->path);
+        }
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", &seats));
+    }
+    else if (strcmp (method_name, "CreateSession") == 0)
+    {
+        /* Note: this is not the full CreateSession as used by logind, we just
+           need one so our fake PAM stack can communicate with this service */
+        Login1Session *session = create_login1_session (connection);
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(so)", session->id, session->path));
 
-        for (link = login1_sessions; link; link = link->next)
+    }
+    else if (strcmp (method_name, "LockSession") == 0)
+    {
+        const gchar *id;
+        Login1Session *session;
+
+        g_variant_get (parameters, "(&s)", &id);
+        session = find_login1_session (id);
+        if (!session)
         {
-            Login1Session *session;
-            session = link->data;
-            if (session->pid == pid)
-            {
-                ret = session;
-                break;
-            }
+            g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such session: %s", id);
+            return;
+        }
+
+        if (!session->locked)
+        {
+            gchar *status = g_strdup_printf ("LOGIN1 LOCK-SESSION SESSION=%s", id);
+            check_status (status);
+            g_free (status);
         }
-        /* Not found */
-        if (!ret)
-            ret = open_login1_session (connection, parameters);
+        session->locked = TRUE;
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+    }
+    else if (strcmp (method_name, "UnlockSession") == 0)
+    {
+        const gchar *id;
+        Login1Session *session;
 
-        g_dbus_method_invocation_return_value (invocation,
-                                               g_variant_new("(o)", ret->path));
+        g_variant_get (parameters, "(&s)", &id);
+        session = find_login1_session (id);
+        if (!session)
+        {
+            g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such session: %s", id);
+            return;
+        }
 
+        if (session->locked)
+        {
+            gchar *status = g_strdup_printf ("LOGIN1 UNLOCK-SESSION SESSION=%s", id);
+            check_status (status);
+            g_free (status);
+        }
+        session->locked = FALSE;
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+    }
+    else if (strcmp (method_name, "ActivateSession") == 0)
+    {
+        const gchar *id;
+        Login1Session *session;
+
+        g_variant_get (parameters, "(&s)", &id);
+        session = find_login1_session (id);
+        if (!session)
+        {
+            g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such session: %s", id);
+            return;
+        }
+
+        gchar *status = g_strdup_printf ("LOGIN1 ACTIVATE-SESSION SESSION=%s", id);
+        check_status (status);
+        g_free (status);
+
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
     }
     else if (strcmp (method_name, "CanReboot") == 0)
     {
@@ -1393,9 +1926,21 @@ login1_name_acquired_cb (GDBusConnection *connection,
     const gchar *login1_interface =
         "<node>"
         "  <interface name='org.freedesktop.login1.Manager'>"
-        "    <method name='GetSessionByPID'>"
-        "      <arg name='pid' type='u' direction='in'/>"
-        "      <arg name='session' type='o' direction='out'/>"
+        "    <method name='ListSeats'>"
+        "      <arg name='seats' type='a(so)' direction='out'/>"
+        "    </method>"
+        "    <method name='CreateSession'>"
+        "      <arg name='id' type='s' direction='out'/>"
+        "      <arg name='path' type='o' direction='out'/>"
+        "    </method>"
+        "    <method name='LockSession'>"
+        "      <arg name='id' type='s' direction='in'/>"
+        "    </method>"
+        "    <method name='UnlockSession'>"
+        "      <arg name='id' type='s' direction='in'/>"
+        "    </method>"
+        "    <method name='ActivateSession'>"
+        "      <arg name='id' type='s' direction='in'/>"
         "    </method>"
         "    <method name='CanReboot'>"
         "      <arg name='result' direction='out' type='s'/>"
@@ -1421,6 +1966,12 @@ login1_name_acquired_cb (GDBusConnection *connection,
         "    <method name='Hibernate'>"
         "      <arg name='interactive' direction='in' type='b'/>"
         "    </method>"
+        "    <signal name='SeatNew'>"
+        "      <arg name='seat' type='so'/>"
+        "    </signal>"
+        "    <signal name='SeatRemoved'>"
+        "      <arg name='seat' type='so'/>"
+        "    </signal>"
         "  </interface>"
         "</node>";
     static const GDBusInterfaceVTable login1_vtable =
@@ -1428,6 +1979,7 @@ login1_name_acquired_cb (GDBusConnection *connection,
         handle_login1_call,
     };
     GDBusNodeInfo *login1_info;
+    Login1Seat *seat0;
     GError *error = NULL;
 
     login1_info = g_dbus_node_info_new_for_xml (login1_interface, &error);
@@ -1447,9 +1999,16 @@ login1_name_acquired_cb (GDBusConnection *connection,
     g_clear_error (&error);
     g_dbus_node_info_unref (login1_info);
 
+    /* We always have seat0 */
+    seat0 = add_login1_seat (connection, "seat0", FALSE);
+    if (g_key_file_has_key (config, "test-runner-config", "seat0-can-graphical", NULL))
+        seat0->can_graphical = g_key_file_get_boolean (config, "test-runner-config", "seat0-can-graphical", NULL);
+    if (g_key_file_has_key (config, "test-runner-config", "seat0-can-multi-session", NULL))
+        seat0->can_multi_session = g_key_file_get_boolean (config, "test-runner-config", "seat0-can-multi-session", NULL);
+
     service_count--;
     if (service_count == 0)
-        run_lightdm ();
+        ready ();
 }
 
 static void
@@ -1459,8 +2018,8 @@ start_login1_daemon (void)
     g_bus_own_name (G_BUS_TYPE_SYSTEM,
                     "org.freedesktop.login1",
                     G_BUS_NAME_OWNER_FLAGS_NONE,
-                    login1_name_acquired_cb,
                     NULL,
+                    login1_name_acquired_cb,
                     NULL,
                     NULL,
                     NULL);
@@ -1477,7 +2036,7 @@ get_accounts_user_by_uid (guint uid)
         if (u->uid == uid)
             return u;
     }
-  
+
     return NULL;
 }
 
@@ -1665,7 +2224,7 @@ handle_accounts_call (GDBusConnection       *connection,
         for (link = accounts_users; link; link = link->next)
         {
             AccountsUser *user = link->data;
-            if (!user->hidden)
+            if (!user->hidden && user->uid >= 1000)
                 g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
         }
 
@@ -1715,6 +2274,15 @@ handle_user_call (GDBusConnection       *connection,
         user->xsession = g_strdup (xsession);
 
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+
+        /* And notify others that it took */
+        g_dbus_connection_emit_signal (accounts_connection,
+                                       NULL,
+                                       user->path,
+                                       "org.freedesktop.Accounts.User",
+                                       "Changed",
+                                       g_variant_new ("()"),
+                                       NULL);
     }
     else
         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
@@ -1737,12 +2305,18 @@ handle_user_get_property (GDBusConnection       *connection,
         return g_variant_new_string (user->real_name);
     else if (strcmp (property_name, "HomeDirectory") == 0)
         return g_variant_new_string (user->home_directory);
+    else if (strcmp (property_name, "SystemAccount") == 0)
+        return g_variant_new_boolean (user->uid < 1000);
     else if (strcmp (property_name, "BackgroundFile") == 0)
         return g_variant_new_string (user->background ? user->background : "");
     else if (strcmp (property_name, "Language") == 0)
         return g_variant_new_string (user->language ? user->language : "");
     else if (strcmp (property_name, "IconFile") == 0)
         return g_variant_new_string (user->image ? user->image : "");
+    else if (strcmp (property_name, "Shell") == 0)
+        return g_variant_new_string ("/bin/sh");
+    else if (strcmp (property_name, "Uid") == 0)
+        return g_variant_new_uint64 (user->uid);
     else if (strcmp (property_name, "XSession") == 0)
         return g_variant_new_string (user->xsession ? user->xsession : "");
     else if (strcmp (property_name, "XKeyboardLayouts") == 0)
@@ -1794,9 +2368,12 @@ accounts_name_acquired_cb (GDBusConnection *connection,
         "    <property name='UserName' type='s' access='read'/>"
         "    <property name='RealName' type='s' access='read'/>"
         "    <property name='HomeDirectory' type='s' access='read'/>"
+        "    <property name='SystemAccount' type='b' access='read'/>"
         "    <property name='BackgroundFile' type='s' access='read'/>"
         "    <property name='Language' type='s' access='read'/>"
         "    <property name='IconFile' type='s' access='read'/>"
+        "    <property name='Shell' type='s' access='read'/>"
+        "    <property name='Uid' type='t' access='read'/>"
         "    <property name='XSession' type='s' access='read'/>"
         "    <property name='XKeyboardLayouts' type='as' access='read'/>"
         "    <property name='XHasMessages' type='b' access='read'/>"
@@ -1833,7 +2410,7 @@ accounts_name_acquired_cb (GDBusConnection *connection,
 
     service_count--;
     if (service_count == 0)
-        run_lightdm ();
+        ready ();
 }
 
 static void
@@ -1851,50 +2428,87 @@ start_accounts_service_daemon (void)
 }
 
 static void
-run_lightdm (void)
+ready (void)
 {
-    GString *command_line;
-    gchar **lightdm_argv;
-    pid_t lightdm_pid;
-    GError *error = NULL;
-
     run_commands ();
+}
 
-    status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
+static gboolean
+signal_cb (gpointer user_data)
+{
+    g_print ("Caught signal, quitting\n");
+    quit (EXIT_FAILURE);
+    return FALSE;
+}
 
-    command_line = g_string_new ("lightdm");
-    if (getenv ("DEBUG"))
-        g_string_append (command_line, " --debug");
-    g_string_append_printf (command_line, " --cache-dir %s/cache", temp_dir);
+static void
+properties_changed_cb (GDBusConnection *connection,
+                       const gchar *sender_name,
+                       const gchar *object_path,
+                       const gchar *interface_name,
+                       const gchar *signal_name,
+                       GVariant *parameters,
+                       gpointer user_data)
+{
+    const gchar *interface, *name;
+    GString *status;
+    GVariant *value;
+    GVariantIter *changed_properties, *invalidated_properties;
+    int i;
 
-    test_runner_command = g_strdup_printf ("PATH=%s LD_PRELOAD=%s LD_LIBRARY_PATH=%s LIGHTDM_TEST_ROOT=%s DBUS_SESSION_BUS_ADDRESS=%s %s\n",
-                                           g_getenv ("PATH"), g_getenv ("LD_PRELOAD"), g_getenv ("LD_LIBRARY_PATH"), g_getenv ("LIGHTDM_TEST_ROOT"), g_getenv ("DBUS_SESSION_BUS_ADDRESS"),
-                                           command_line->str);
+    g_variant_get (parameters, "(&sa{sv}as)", &interface, &changed_properties, &invalidated_properties);
 
-    if (!g_shell_parse_argv (command_line->str, NULL, &lightdm_argv, &error))
+    status = g_string_new ("RUNNER DBUS-PROPERTIES-CHANGED");
+    g_string_append_printf (status, " PATH=%s", object_path);
+    g_string_append_printf (status, " INTERFACE=%s", interface);
+    for (i = 0; g_variant_iter_loop (changed_properties, "{&sv}", &name, &value); i++)
     {
-        g_warning ("Error parsing command line: %s", error->message);
-        quit (EXIT_FAILURE);
-    }
-    g_clear_error (&error);
+        if (i == 0)
+            g_string_append (status, " CHANGED=");
+        else
+            g_string_append (status, ",");
+        g_string_append (status, name);
+        if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao")))
+        {
+            GVariantIter iter;
+            const gchar *path;
 
-    if (!g_spawn_async (NULL, lightdm_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &lightdm_pid, &error))
+            g_variant_iter_init (&iter, value);
+            while (g_variant_iter_loop (&iter, "&o", &path))
+                g_string_append_printf (status, ":%s", path);
+        }
+    }
+    for (i = 0; g_variant_iter_loop (invalidated_properties, "&s", &name); i++)
     {
-        g_warning ("Error launching LightDM: %s", error->message);
-        quit (EXIT_FAILURE);
+        if (i == 0)
+            g_string_append (status, " INVALIDATED=");
+        else
+            g_string_append (status, ",");
+        g_string_append (status, name);
     }
-    g_clear_error (&error);
-    lightdm_process = watch_process (lightdm_pid);
 
-    check_status ("RUNNER DAEMON-START");
+    check_status (status->str);
+    g_string_free (status, TRUE);
 }
 
-static gboolean
-signal_cb (gpointer user_data)
+static void
+dbus_signal_cb (GDBusConnection *connection,
+                const gchar *sender_name,
+                const gchar *object_path,
+                const gchar *interface_name,
+                const gchar *signal_name,
+                GVariant *parameters,
+                gpointer user_data)
 {
-    g_print ("Caught signal, quitting\n");
-    quit (EXIT_FAILURE);
-    return FALSE;
+    GString *status;
+
+    status = g_string_new ("RUNNER DBUS-SIGNAL");
+    g_string_append_printf (status, " PATH=%s", object_path);
+    g_string_append_printf (status, " INTERFACE=%s", interface_name);
+    g_string_append_printf (status, " NAME=%s", signal_name);
+
+    check_status (status->str);
+    g_string_free (status, TRUE);
 }
 
 int
@@ -1944,6 +2558,10 @@ main (int argc, char **argv)
     /* Don't contact our X server */
     g_unsetenv ("DISPLAY");
 
+    /* Don't let XDG vars from system affect tests */
+    g_unsetenv ("XDG_CONFIG_DIRS");
+    g_unsetenv ("XDG_DATA_DIRS");
+
     /* Override system calls */
     ld_preload = g_build_filename (BUILDDIR, "tests", "src", ".libs", "libsystem.so", NULL);
     g_setenv ("LD_PRELOAD", ld_preload, TRUE);
@@ -1979,7 +2597,7 @@ main (int argc, char **argv)
         if (!g_file_test (temp_dir, G_FILE_TEST_EXISTS))
             break;
         i++;
-    }  
+    }
     g_mkdir_with_parents (temp_dir, 0755);
     g_setenv ("LIGHTDM_TEST_ROOT", temp_dir, TRUE);
 
@@ -2023,11 +2641,13 @@ main (int argc, char **argv)
 
     /* Set up a skeleton file system */
     g_mkdir_with_parents (g_strdup_printf ("%s/etc", temp_dir), 0755);
+    g_mkdir_with_parents (g_strdup_printf ("%s/run", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/usr/share", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/sessions", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/remote-sessions", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/greeters", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/tmp", temp_dir), 0755);
+    g_mkdir_with_parents (g_strdup_printf ("%s/var/lib/lightdm-data", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/var/run", temp_dir), 0755);
     g_mkdir_with_parents (g_strdup_printf ("%s/var/log", temp_dir), 0755);
 
@@ -2036,6 +2656,8 @@ main (int argc, char **argv)
     if (!g_key_file_has_key (config, "test-runner-config", "have-config", NULL) || g_key_file_get_boolean (config, "test-runner-config", "have-config", NULL))
         if (system (g_strdup_printf ("cp %s %s/etc/lightdm/lightdm.conf", config_path, temp_dir)))
             perror ("Failed to copy configuration");
+    if (system (g_strdup_printf ("cp %s/tests/data/keys.conf %s/etc/lightdm/", SRCDIR, temp_dir)))
+        perror ("Failed to copy key configuration");
 
     additional_system_config = g_key_file_get_string (config, "test-runner-config", "additional-system-config", NULL);
     if (additional_system_config)
@@ -2056,15 +2678,46 @@ main (int argc, char **argv)
     {
         gchar **files;
 
-        g_mkdir_with_parents (g_strdup_printf ("%s/etc/lightdm/lightdm.conf.d", temp_dir), 0755);
+        g_mkdir_with_parents (g_strdup_printf ("%s/etc/xdg/lightdm/lightdm.conf.d", temp_dir), 0755);
 
         files = g_strsplit (additional_config, " ", -1);
         for (i = 0; files[i]; i++)
-            if (system (g_strdup_printf ("cp %s/tests/scripts/%s %s/etc/lightdm/lightdm.conf.d", SRCDIR, files[i], temp_dir)))
+            if (system (g_strdup_printf ("cp %s/tests/scripts/%s %s/etc/xdg/lightdm/lightdm.conf.d", SRCDIR, files[i], temp_dir)))
                 perror ("Failed to copy configuration");
         g_strfreev (files);
     }
 
+    if (g_key_file_has_key (config, "test-runner-config", "shared-data-dirs", NULL))
+    {
+        gchar *dir_string;
+        gchar **dirs;
+        gint i;
+
+        dir_string = g_key_file_get_string (config, "test-runner-config", "shared-data-dirs", NULL);
+        dirs = g_strsplit (dir_string, " ", -1);
+        g_free (dir_string);
+
+        for (i = 0; dirs[i]; i++)
+        {
+            gchar **fields = g_strsplit (dirs[i], ":", -1);
+            if (g_strv_length (fields) == 4)
+            {
+                gchar *path = g_strdup_printf ("%s/var/lib/lightdm-data/%s", temp_dir, fields[0]);
+                int uid = g_ascii_strtoll (fields[1], NULL, 10);
+                int gid = g_ascii_strtoll (fields[2], NULL, 10);
+                int mode = g_ascii_strtoll (fields[3], NULL, 8);
+                g_mkdir (path, mode);
+                g_chmod (path, mode); /* mkdir filters by umask, so make sure we have what we want */
+                if (chown (path, uid, gid) < 0)
+                  g_warning ("chown (%s) failed: %s", path, strerror (errno));
+                g_free (path);
+            }
+            g_strfreev (fields);
+        }
+
+        g_strfreev (dirs);
+    }
+
     /* Always copy the script */
     if (system (g_strdup_printf ("cp %s %s/script", config_path, temp_dir)))
         perror ("Failed to copy configuration");
@@ -2261,6 +2914,31 @@ main (int argc, char **argv)
     if (!g_key_file_get_boolean (config, "test-runner-config", "disable-accounts-service", NULL))
         start_accounts_service_daemon ();
 
+    /* Listen for daemon bus events */
+    if (g_key_file_get_boolean (config, "test-runner-config", "log-dbus", NULL))
+    {
+        g_dbus_connection_signal_subscribe (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                            "org.freedesktop.DisplayManager",
+                                            "org.freedesktop.DBus.Properties",
+                                            "PropertiesChanged",
+                                            NULL,
+                                            NULL,
+                                            G_DBUS_SIGNAL_FLAGS_NONE,
+                                            properties_changed_cb,
+                                            NULL,
+                                            NULL);
+        g_dbus_connection_signal_subscribe (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                            "org.freedesktop.DisplayManager",
+                                            "org.freedesktop.DisplayManager",
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            G_DBUS_SIGNAL_FLAGS_NONE,
+                                            dbus_signal_cb,
+                                            NULL,
+                                            NULL);
+    }
+
     g_main_loop_run (loop);
 
     return EXIT_FAILURE;