libnm: port NMRemoteSettings to NMObject
authorDan Winship <danw@gnome.org>
Sun, 20 Jul 2014 16:55:59 +0000 (12:55 -0400)
committerDan Winship <danw@gnome.org>
Thu, 7 Aug 2014 19:43:43 +0000 (15:43 -0400)
NMRemoteSettings duplicates a bunch of NMObject's functionality that
it doesn't need to. In libnm-glib, it wouldn't have been possible to
port NMRemoteSettings to NMObject without breaking ABI, but now in
libnm we can do that.

As a side effect of this, NMRemoteSettings gains a "connections"
property, and "connection-added" and "connection-removed" signals
(with the former replacing the old "new-connection" signal). This also
removes the "connections-loaded" signal, since the connections will
now always be loaded (via the initialization of the "connections"
property) during init()/init_async().

Also, this removes NMRemoteConnection's "removed" signal, since it's
redundant with the new NMRemoteSettings::connection-removed (and
having the signal on NMRemoteSettings instead is more consistent with
other objects).

clients/cli/connections.c
clients/tui/nmt-edit-connection-list.c
clients/tui/nmtui-edit.c
clients/tui/nmtui.c
examples/C/glib/list-connections-libnm.c
libnm/nm-remote-connection.c
libnm/nm-remote-connection.h
libnm/nm-remote-settings.c
libnm/nm-remote-settings.h
libnm/tests/test-remote-settings-client.c

index 4d5101f..e4de756 100644 (file)
@@ -228,16 +228,9 @@ static NmcOutputField nmc_fields_con_active_details_groups[] = {
 #define CON_SHOW_DETAIL_GROUP_PROFILE "profile"
 #define CON_SHOW_DETAIL_GROUP_ACTIVE  "active"
 
-typedef struct {
-       NmCli *nmc;
-       int argc;
-       char **argv;
-} ArgsInfo;
-
 /* glib main loop variable - defined in nmcli.c */
 extern GMainLoop *loop;
 
-static ArgsInfo args_info;
 static guint progress_id = 0;  /* ID of event source for displaying progress */
 
 /* for readline TAB completion in editor */
@@ -8607,21 +8600,6 @@ opt_error:
        return nmc->return_value;
 }
 
-/* callback called when connections are obtained from the settings service */
-static void
-get_connections_cb (NMRemoteSettings *settings, gpointer user_data)
-{
-       ArgsInfo *args = (ArgsInfo *) user_data;
-
-       /* Get the connection list */
-       args->nmc->system_connections = nm_remote_settings_list_connections (settings);
-
-       parse_cmd (args->nmc, args->argc, args->argv);
-
-       if (!args->nmc->should_wait)
-               quit ();
-}
-
 /* Entry point function for connections-related commands: 'nmcli connection' */
 NMCResultCode
 do_connections (NmCli *nmc, int argc, char **argv)
@@ -8651,10 +8629,6 @@ do_connections (NmCli *nmc, int argc, char **argv)
 
                nmc->should_wait = TRUE;
 
-               args_info.nmc = nmc;
-               args_info.argc = argc;
-               args_info.argv = argv;
-
                /* get system settings */
                if (!(nmc->system_settings = nm_remote_settings_new (NULL, &error))) {
                        g_string_printf (nmc->return_text, _("Error: Could not get system settings: %s."), error->message);
@@ -8674,13 +8648,13 @@ do_connections (NmCli *nmc, int argc, char **argv)
                        return nmc->return_value;
                }
 
-               /* connect to signal "connections-read" - emitted when connections are fetched and ready */
-               g_signal_connect (nmc->system_settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ,
-                                 G_CALLBACK (get_connections_cb), &args_info);
+               /* Get the connection list */
+               nmc->system_connections = nm_remote_settings_list_connections (nmc->system_settings);
 
-               /* The rest will be done in get_connection_cb() callback.
-                * We need to wait for signals that connections are read.
-                */
+               parse_cmd (nmc, argc, argv);
+
+               if (!nmc->should_wait)
+                       quit ();
                return NMC_RESULT_SUCCESS;
        }
 }
index 2c2c084..d11b21d 100644 (file)
@@ -204,8 +204,6 @@ nmt_edit_connection_list_rebuild (NmtEditConnectionList *list)
 
                g_signal_connect (conn, NM_REMOTE_CONNECTION_UPDATED,
                                  G_CALLBACK (rebuild_on_connection_updated), list);
-               g_signal_connect (conn, NM_REMOTE_CONNECTION_REMOVED,
-                                 G_CALLBACK (rebuild_on_connection_updated), list);
                g_object_ref (iter->data);
        }
        priv->connections = g_slist_sort (priv->connections, sort_by_timestamp);
@@ -279,9 +277,9 @@ nmt_edit_connection_list_rebuild (NmtEditConnectionList *list)
 }
 
 static void
-rebuild_on_new_connection (NMRemoteSettings   *settings,
-                           NMRemoteConnection *connection,
-                           gpointer            list)
+rebuild_on_connections_changed (GObject    *object,
+                                GParamSpec *pspec,
+                                gpointer    list)
 {
        nmt_edit_connection_list_rebuild (list);
 }
@@ -295,8 +293,8 @@ nmt_edit_connection_list_constructed (GObject *object)
        if (priv->extra)
                nmt_newt_button_box_add_widget_end (priv->buttons, priv->extra);
 
-       g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_NEW_CONNECTION,
-                         G_CALLBACK (rebuild_on_new_connection), list);
+       g_signal_connect (nm_settings, "notify::" NM_REMOTE_SETTINGS_CONNECTIONS,
+                         G_CALLBACK (rebuild_on_connections_changed), list);
 
        nmt_edit_connection_list_rebuild (list);
 
index a564ff3..1757ff4 100644 (file)
@@ -426,6 +426,7 @@ nmt_edit_connection (NMConnection *connection)
 typedef struct {
        NmtSyncOp op;
        gboolean got_callback, got_signal;
+       NMRemoteConnection *connection;
 } ConnectionDeleteData;
 
 static void
@@ -446,14 +447,17 @@ connection_deleted_callback (NMRemoteConnection *connection,
 }
 
 static void
-connection_removed_signal (NMRemoteConnection *connection,
+connection_removed_signal (NMRemoteSettings   *settings,
+                           NMRemoteConnection *connection,
                            gpointer            user_data)
 {
        ConnectionDeleteData *data = user_data;
 
-       data->got_signal = TRUE;
-       if (data->got_callback && data->got_signal)
-               nmt_sync_op_complete_boolean (&data->op, TRUE, NULL);
+       if (connection == data->connection) {
+               data->got_signal = TRUE;
+               if (data->got_callback && data->got_signal)
+                       nmt_sync_op_complete_boolean (&data->op, TRUE, NULL);
+       }
 }
 
 void
@@ -473,8 +477,8 @@ nmt_remove_connection (NMRemoteConnection *connection)
        data.got_callback = data.got_signal = FALSE;
        nmt_sync_op_init (&data.op);
 
-       g_object_ref (connection);
-       g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED,
+       data.connection = connection;
+       g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_CONNECTION_REMOVED,
                          G_CALLBACK (connection_removed_signal), &data);
        nm_remote_connection_delete (connection, connection_deleted_callback, &data);
 
@@ -484,8 +488,7 @@ nmt_remove_connection (NMRemoteConnection *connection)
                g_error_free (error);
        }
 
-       g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_removed_signal), &data);
-       g_object_unref (connection);
+       g_signal_handlers_disconnect_by_func (nm_settings, G_CALLBACK (connection_removed_signal), &data);
 }
 
 NmtNewtForm *
index 0fea767..ee63ccf 100644 (file)
@@ -140,15 +140,6 @@ nmtui_quit (void)
        g_main_loop_quit (loop);
 }
 
-static void
-connections_read (NMRemoteSettings *settings,
-                  gpointer          user_data)
-{
-       gboolean *got_connections = user_data;
-
-       *got_connections = TRUE;
-}
-
 static void
 usage (void)
 {
@@ -217,7 +208,6 @@ GOptionEntry entries[] = {
 int
 main (int argc, char **argv)
 {
-       gboolean got_connections = FALSE;
        GOptionContext *opts;
        GError *error = NULL;
        NmtuiStartupData startup_data;
@@ -260,11 +250,6 @@ main (int argc, char **argv)
                g_error_free (error);
                exit (1);
        }
-       g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ,
-                         G_CALLBACK (connections_read), &got_connections);
-       /* coverity[loop_condition] */
-       while (!got_connections)
-               g_main_context_iteration (NULL, TRUE);
 
        if (sleep_on_startup)
                sleep (5);
index 1b2c8f1..1827835 100644 (file)
 #include <glib.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <signal.h>
 
 #include <NetworkManager.h>
 
-
-/* Global variables */
-GMainLoop *loop = NULL; /* Main loop variable - needed for waiting for signal */
-int result = EXIT_SUCCESS;
-
-static void
-signal_handler (int signo)
-{
-       if (signo == SIGINT || signo == SIGTERM) {
-               g_message ("Caught signal %d, shutting down...", signo);
-               g_main_loop_quit (loop);
-       }
-}
-
-static void
-setup_signals (void)
-{
-       struct sigaction action;
-       sigset_t mask;
-
-       sigemptyset (&mask);
-       action.sa_handler = signal_handler;
-       action.sa_mask = mask;
-       action.sa_flags = 0;
-       sigaction (SIGTERM,  &action, NULL);
-       sigaction (SIGINT,  &action, NULL);
-}
-
 /* Print details of connection */
 static void
 show_connection (gpointer data, gpointer user_data)
@@ -89,42 +60,24 @@ show_connection (gpointer data, gpointer user_data)
        }
 }
 
-/* This callback is called when connections from the settings service are ready.
- * Now the connections can be listed.
- */
-static void
-get_connections_cb (NMRemoteSettings *settings, gpointer user_data)
-{
-       GSList *connections;
-
-       connections = nm_remote_settings_list_connections (settings);
-
-       printf ("Connections:\n===================\n");
-
-       g_slist_foreach (connections, show_connection, NULL);
-
-       g_slist_free (connections);
-       g_object_unref (settings);
-
-       /* We are done, exit main loop */
-       g_main_loop_quit (loop);
-}
-
-/* Get system settings and then connect to connections-read signal */
-static gboolean
-list_connections (gpointer data)
+int
+main (int argc, char *argv[])
 {
        NMRemoteSettings *settings;
        gboolean settings_running;
        GError *error = NULL;
+       GSList *connections;
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+       /* Initialize GType system */
+       g_type_init ();
+#endif
 
        /* Get system settings */
        if (!(settings = nm_remote_settings_new (NULL, &error))) {
                g_message ("Error: Could not get system settings: %s.", error->message);
                g_error_free (error);
-               result = EXIT_FAILURE;
-               g_main_loop_quit (loop);
-               return FALSE;
+               return EXIT_FAILURE;
        }
 
        /* Find out whether setting service is running */
@@ -132,42 +85,18 @@ list_connections (gpointer data)
 
        if (!settings_running) {
                g_message ("Error: Can't obtain connections: settings service is not running.");
-               result = EXIT_FAILURE;
-               g_main_loop_quit (loop);
-               return FALSE;
+               return EXIT_FAILURE;
        }
 
-       /* Connect to signal "connections-read" - emitted when connections are fetched and ready */
-       g_signal_connect (settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ,
-                         G_CALLBACK (get_connections_cb), NULL);
-
-       return FALSE;
-}
-
-int main (int argc, char *argv[])
-{
-       DBusGConnection *bus;
-
-#if !GLIB_CHECK_VERSION (2, 35, 0)
-       /* Initialize GType system */
-       g_type_init ();
-#endif
-
-       /* Get system bus */
-       bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+       /* Now the connections can be listed. */
+       connections = nm_remote_settings_list_connections (settings);
 
-       /* Run list_connections from main loop, because we need to wait for "connections-read"
-        * signal to have connections ready. The execution will be finished in get_connections_cb()
-        * callback on the signal.
-        */
-       g_idle_add (list_connections, bus);
+       printf ("Connections:\n===================\n");
 
-       loop = g_main_loop_new (NULL, FALSE);  /* Create main loop */
-       setup_signals ();                      /* Setup UNIX signals */
-       g_main_loop_run (loop);                /* Run main loop */
+       g_slist_foreach (connections, show_connection, NULL);
 
-       g_main_loop_unref (loop);
-       dbus_g_connection_unref (bus);
+       g_slist_free (connections);
+       g_object_unref (settings);
 
-       return result;
+       return EXIT_SUCCESS;
 }
index 2bf5b61..0aa6e9d 100644 (file)
@@ -57,7 +57,6 @@ enum {
 
 enum {
        UPDATED,
-       REMOVED,
 
        LAST_SIGNAL
 };
@@ -453,8 +452,6 @@ replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
                           error ? error->code : -1,
                           (error && error->message) ? error->message : "(unknown)");
                g_clear_error (&error);
-
-               g_signal_emit (self, signals[REMOVED], 0);
        }
 }
 
@@ -477,11 +474,7 @@ updated_get_settings_cb (DBusGProxy *proxy,
 
                g_error_free (error);
 
-               /* Connection is no longer visible to this user.  Let the settings
-                * service handle this via 'visible'.  The settings service will emit
-                * the "removed" signal for us since it handles the lifetime of this
-                * object.
-                */
+               /* Connection is no longer visible to this user. */
                hash = g_hash_table_new (g_str_hash, g_str_equal);
                nm_connection_replace_settings (NM_CONNECTION (self), hash, NULL);
                g_hash_table_destroy (hash);
@@ -514,12 +507,6 @@ updated_cb (DBusGProxy *proxy, gpointer user_data)
        }
 }
 
-static void
-removed_cb (DBusGProxy *proxy, gpointer user_data)
-{
-       g_signal_emit (G_OBJECT (user_data), signals[REMOVED], 0);
-}
-
 static void
 properties_changed_cb (DBusGProxy *proxy,
                        GHashTable *properties,
@@ -558,9 +545,6 @@ init_common (NMRemoteConnection *self)
        dbus_g_proxy_add_signal (priv->proxy, "Updated", G_TYPE_INVALID);
        dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), self, NULL);
 
-       dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID);
-       dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), self, NULL);
-
        g_signal_connect (priv->proxy, "destroy", G_CALLBACK (proxy_destroy_cb), self);
 
        /* Monitor properties */
@@ -909,22 +893,6 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
                              NULL, NULL,
                              g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
-
-       /**
-        * NMRemoteConnection::removed:
-        * @connection: a #NMConnection
-        *
-        * This signal is emitted when a connection is either deleted or becomes
-        * invisible to the current user.
-        */
-       signals[REMOVED] =
-               g_signal_new (NM_REMOTE_CONNECTION_REMOVED,
-                             G_TYPE_FROM_CLASS (remote_class),
-                             G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (NMRemoteConnectionClass, removed),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
 }
 
 static void
index b50f2fa..3d851f7 100644 (file)
@@ -61,7 +61,6 @@ GQuark nm_remote_connection_error_quark (void);
 
 /* Signals */
 #define NM_REMOTE_CONNECTION_UPDATED         "updated"
-#define NM_REMOTE_CONNECTION_REMOVED         "removed"
 
 typedef struct {
        NMConnection parent;
@@ -74,8 +73,6 @@ typedef struct {
        void (*updated) (NMRemoteConnection *connection,
                         GHashTable *new_settings);
 
-       void (*removed) (NMRemoteConnection *connection);
-
        /*< private >*/
        gpointer padding[8];
 } NMRemoteConnectionClass;
index 84bd6c1..3418eeb 100644 (file)
@@ -30,6 +30,7 @@
 #include "nm-dbus-helpers-private.h"
 #include "nm-glib-compat.h"
 #include "nm-object-private.h"
+#include "nm-types.h"
 
 /**
  * SECTION:nm-remote-settings
  * ]|
  */
 
-static void nm_remote_settings_initable_iface_init (GInitableIface *iface);
-static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_settings_initable_iface_init);
-                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_settings_async_initable_iface_init);
-                         )
+G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, NM_TYPE_OBJECT)
 
 #define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
 
 typedef struct {
-       DBusGConnection *bus;
-       gboolean private_bus;
-
        DBusGProxy *proxy;
-       GHashTable *connections;
-       GHashTable *pending;  /* Connections we don't have settings for yet */
-       gboolean nm_running;
-       guint32 init_left;
+       GPtrArray *all_connections;
+       GPtrArray *visible_connections;
 
        /* AddConnectionInfo objects that are waiting for the connection to become initialized */
        GSList *add_list;
 
-       DBusGProxy *props_proxy;
        char *hostname;
        gboolean can_modify;
-
-       DBusGProxy *dbus_proxy;
-
-       DBusGProxyCall *listcon_call;
 } NMRemoteSettingsPrivate;
 
 enum {
        PROP_0,
-       PROP_BUS,
        PROP_NM_RUNNING,
+       PROP_CONNECTIONS,
        PROP_HOSTNAME,
        PROP_CAN_MODIFY,
 
@@ -162,8 +147,8 @@ enum {
 
 /* Signals */
 enum {
-       NEW_CONNECTION,
-       CONNECTIONS_READ,
+       CONNECTION_ADDED,
+       CONNECTION_REMOVED,
 
        LAST_SIGNAL
 };
@@ -194,11 +179,11 @@ typedef struct {
        NMRemoteSettings *self;
        NMRemoteSettingsAddConnectionFunc callback;
        gpointer callback_data;
-       NMRemoteConnection *connection;
+       char *path;
 } AddConnectionInfo;
 
 static AddConnectionInfo *
-add_connection_info_find (NMRemoteSettings *self, NMRemoteConnection *connection)
+add_connection_info_find (NMRemoteSettings *self, const char *path)
 {
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
        GSList *iter;
@@ -206,7 +191,7 @@ add_connection_info_find (NMRemoteSettings *self, NMRemoteConnection *connection
        for (iter = priv->add_list; iter; iter = g_slist_next (iter)) {
                AddConnectionInfo *info = iter->data;
 
-               if (info->connection == connection)
+               if (!g_strcmp0 (info->path, path))
                        return info;
        }
 
@@ -220,20 +205,47 @@ add_connection_info_dispose (NMRemoteSettings *self, AddConnectionInfo *info)
 
        priv->add_list = g_slist_remove (priv->add_list, info);
 
+       g_free (info->path);
        g_free (info);
 }
 
 static void
 add_connection_info_complete (NMRemoteSettings *self,
                               AddConnectionInfo *info,
+                              NMRemoteConnection *connection,
                               GError *error)
 {
        g_return_if_fail (info != NULL);
 
-       info->callback (info->self, error ? NULL : info->connection, error, info->callback_data);
+       info->callback (info->self, connection, error, info->callback_data);
        add_connection_info_dispose (self, info);
 }
 
+typedef const char * (*ConnectionStringGetter) (NMConnection *);
+
+static NMRemoteConnection *
+get_connection_by_string (NMRemoteSettings *settings,
+                          const char *string,
+                          ConnectionStringGetter get_comparison_string)
+{
+       NMRemoteSettingsPrivate *priv;
+       NMConnection *candidate;
+       int i;
+
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
+               return NULL;
+
+       priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+       for (i = 0; i < priv->visible_connections->len; i++) {
+               candidate = priv->visible_connections->pdata[i];
+               if (!g_strcmp0 (string, get_comparison_string (candidate)))
+                       return NM_REMOTE_CONNECTION (candidate);
+       }
+
+       return NULL;
+}
+
 /**
  * nm_remote_settings_get_connection_by_id:
  * @settings: the %NMRemoteSettings
@@ -247,26 +259,10 @@ add_connection_info_complete (NMRemoteSettings *self,
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char *id)
 {
-       NMRemoteSettingsPrivate *priv;
-
        g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
        g_return_val_if_fail (id != NULL, NULL);
 
-       priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
-       if (priv->nm_running) {
-               GHashTableIter iter;
-               NMConnection *candidate;
-
-               g_hash_table_iter_init (&iter, priv->connections);
-               while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) {
-
-                       if (!strcmp (id, nm_connection_get_id (candidate)))
-                               return NM_REMOTE_CONNECTION (candidate);
-               }
-       }
-
-       return NULL;
+       return get_connection_by_string (settings, id, nm_connection_get_id);
 }
 
 /**
@@ -282,14 +278,10 @@ nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path)
 {
-       NMRemoteSettingsPrivate *priv;
-
        g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
        g_return_val_if_fail (path != NULL, NULL);
 
-       priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
-       return priv->nm_running ? g_hash_table_lookup (priv->connections, path) : NULL;
+       return get_connection_by_string (settings, path, nm_connection_get_path);
 }
 
 /**
@@ -305,259 +297,101 @@ nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const cha
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid)
 {
-       NMRemoteSettingsPrivate *priv;
-       GHashTableIter iter;
-       NMRemoteConnection *candidate;
-
        g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
        g_return_val_if_fail (uuid != NULL, NULL);
 
-       priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
-       if (priv->nm_running) {
-               g_hash_table_iter_init (&iter, priv->connections);
-               while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
-                       if (g_strcmp0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate))) == 0)
-                               return candidate;
-               }
-       }
-
-       return NULL;
+       return get_connection_by_string (settings, uuid, nm_connection_get_uuid);
 }
 
 static void
-connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
+connection_visible_changed (GObject *object,
+                            GParamSpec *pspec,
+                            gpointer user_data)
 {
+       NMRemoteConnection *connection = NM_REMOTE_CONNECTION (object);
        NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       AddConnectionInfo *addinfo;
-       GError *add_error;
-       const char *path;
 
-       /* Might have been removed while it was waiting to be initialized */
-       addinfo = add_connection_info_find (self, remote);
-       if (addinfo) {
-               add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
-                                                NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
-                                                "Connection removed before it was initialized");
-               add_connection_info_complete (self, addinfo, add_error);
-               g_error_free (add_error);
-       }
-
-       path = nm_connection_get_path (NM_CONNECTION (remote));
-       g_hash_table_remove (priv->connections, path);
-       g_hash_table_remove (priv->pending, path);
+       if (nm_remote_connection_get_visible (connection))
+               g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection);
+       else
+               g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
 }
 
-static void connection_visible_changed_cb (GObject *object, GParamSpec *spec, gpointer user_data);
-
-/* Takes a reference to the connection when adding to 'to' */
 static void
-move_connection (NMRemoteSettings *self,
-                 NMRemoteConnection *remote,
-                 GHashTable *from,
-                 GHashTable *to)
+cleanup_connection (NMRemoteSettings *self,
+                    NMRemoteConnection *remote)
 {
-       const char *path = nm_connection_get_path (NM_CONNECTION (remote));
-
-       g_hash_table_insert (to, g_strdup (path), g_object_ref (remote));
-       if (from)
-               g_hash_table_remove (from, path);
-
-       /* Setup connection signals since removing from 'from' clears them, but
-        * also the first time the connection is added to a hash if 'from' is NULL.
-        */
-       if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
-                                   0, 0, NULL, connection_removed_cb, NULL)) {
-               g_signal_connect (remote,
-                                 NM_REMOTE_CONNECTION_REMOVED,
-                                 G_CALLBACK (connection_removed_cb),
-                                 self);
-       }
-
-       if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
-                                   0, 0, NULL, connection_visible_changed_cb, NULL)) {
-               g_signal_connect (remote,
-                                 "notify::" NM_REMOTE_CONNECTION_VISIBLE,
-                                 G_CALLBACK (connection_visible_changed_cb),
-                                 self);
-       }
+       g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (connection_visible_changed), self);
 }
 
 static void
-connection_visible_changed_cb (GObject *object,
-                               GParamSpec *pspec,
-                               gpointer user_data)
+connection_removed (NMRemoteSettings *self,
+                    NMRemoteConnection *remote)
 {
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       NMRemoteConnection *remote = NM_REMOTE_CONNECTION (object);
-       const char *path;
-
-       path = nm_connection_get_path (NM_CONNECTION (remote));
-       g_assert (path);
+       gboolean still_exists = FALSE;
+       int i;
 
-       /* When a connection becomes invisible, we put it back in the pending
-        * hash until it becomes visible again.  When it does, we move it back to
-        * the normal connections hash.
-        */
-       if (nm_remote_connection_get_visible (remote)) {
-               /* Connection visible to this user again */
-               if (g_hash_table_lookup (priv->pending, path)) {
-                       /* Move connection from pending to visible hash; emit for clients */
-                       move_connection (self, remote, priv->pending, priv->connections);
-                       g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
-               }
-       } else {
-               /* Connection now invisible to this user */
-               if (g_hash_table_lookup (priv->connections, path)) {
-                       /* Move connection to pending hash and wait for it to become visible again */
-                       move_connection (self, remote, priv->connections, priv->pending);
-
-                       /* Signal to clients that the connection is gone; but we have to
-                        * block our connection removed handler so we don't destroy
-                        * the connection when the signal is emitted.
-                        */
-                       g_signal_handlers_block_by_func (remote, connection_removed_cb, self);
-                       g_signal_emit_by_name (remote, NM_REMOTE_CONNECTION_REMOVED);
-                       g_signal_handlers_unblock_by_func (remote, connection_removed_cb, self);
+       /* Check if the connection was actually removed or if it just turned invisible. */
+       if (priv->all_connections) {
+               for (i = 0; i < priv->all_connections->len; i++) {
+                       if (remote == priv->all_connections->pdata[i]) {
+                               still_exists = TRUE;
+                               break;
+                       }
                }
        }
+
+       if (!still_exists)
+               cleanup_connection (self, remote);
+
+       /* Allow the signal to propagate if and only if @remote was in visible_connections */
+       if (!g_ptr_array_remove (priv->visible_connections, remote))
+               g_signal_stop_emission (self, signals[CONNECTION_REMOVED], 0);
 }
 
 static void
-connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+connection_added (NMRemoteSettings *self,
+                  NMRemoteConnection *remote)
 {
-       NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source);
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
        AddConnectionInfo *addinfo;
        const char *path;
-       GError *error = NULL, *local;
-
-       path = nm_connection_get_path (NM_CONNECTION (remote));
-       addinfo = add_connection_info_find (self, remote);
-
-       if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) {
-               /* Connection is initialized and visible; expose it to clients */
-               move_connection (self, remote, priv->pending, priv->connections);
-
-               /* If there's a pending AddConnection request, complete that here before
-                * signaling new-connection.
-                */
-               if (addinfo)
-                       add_connection_info_complete (self, addinfo, NULL);
-
-               /* Finally, let users know of the new connection now that it has all
-                * its settings and is valid.
-                */
-               g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
-       } else {
-               if (addinfo) {
-                       local = g_error_new (NM_REMOTE_SETTINGS_ERROR,
-                                            NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
-                                            "Connection not visible or not available: %s",
-                                            error ? error->message : "(unknown)");
-                       add_connection_info_complete (self, addinfo, local);
-                       g_error_free (local);
-               }
 
-               /* PermissionDenied means the connection isn't visible to this user, so
-                * keep it in priv->pending to be notified later of visibility changes.
-                * Otherwise forget it.
-                */
-               if (!dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
-                       g_hash_table_remove (priv->pending, path);
-
-               g_error_free (error);
+       if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+                                   G_CALLBACK (connection_visible_changed), NULL)) {
+               g_signal_connect (remote,
+                                 "notify::" NM_REMOTE_CONNECTION_VISIBLE,
+                                 G_CALLBACK (connection_visible_changed),
+                                 self);
        }
 
-       /* Let listeners know that all connections have been found */
-       priv->init_left--;
-       if (priv->init_left == 0)
-               g_signal_emit (self, signals[CONNECTIONS_READ], 0);
-}
-
-static NMRemoteConnection *
-new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
-{
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       NMRemoteConnection *connection = NULL;
-
-       /* Make double-sure we don't already have it */
-       connection = g_hash_table_lookup (priv->pending, path);
-       if (connection)
-               return connection;
-       connection = g_hash_table_lookup (priv->connections, path);
-       if (connection)
-               return connection;
-
-       /* Create a new connection object for it */
-       connection = g_object_new (NM_TYPE_REMOTE_CONNECTION,
-                                  NM_REMOTE_CONNECTION_BUS, priv->bus,
-                                  NM_CONNECTION_PATH, path,
-                                  NULL);
-       g_async_initable_init_async (G_ASYNC_INITABLE (connection),
-                                    G_PRIORITY_DEFAULT, NULL,
-                                    connection_inited, self);
-
-       /* Add the connection to the pending table to wait for it to retrieve
-        * it's settings asynchronously over D-Bus.  The connection isn't
-        * really valid until it has all its settings, so hide it until it does.
-        */
-       move_connection (self, connection, NULL, priv->pending);
-       g_object_unref (connection); /* move_connection() takes a ref */
+       if (nm_remote_connection_get_visible (remote))
+               g_ptr_array_add (priv->visible_connections, remote);
+       else
+               g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0);
 
-       return connection;
+       path = nm_connection_get_path (NM_CONNECTION (remote));
+       addinfo = add_connection_info_find (self, path);
+       if (addinfo)
+               add_connection_info_complete (self, addinfo, remote, NULL);
 }
 
 static void
-fetch_connections_done (DBusGProxy *proxy,
-                        DBusGProxyCall *call,
-                        gpointer user_data)
+object_creation_failed (NMObject *object, GError *error, char *failed_path)
 {
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       GPtrArray *connections;
-       GError *error = NULL;
-       int i;
-
-       g_warn_if_fail (priv->listcon_call == call);
-       priv->listcon_call = NULL;
-
-       if (!dbus_g_proxy_end_call (proxy, call, &error,
-                                   DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &connections,
-                                   G_TYPE_INVALID)) {
-               if (   !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
-                   && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER)
-                   && priv->nm_running) {
-                       g_warning ("%s: error fetching connections: (%d) %s.",
-                                  __func__,
-                                  error->code,
-                                  error->message ? error->message : "(unknown)");
-               }
-               g_clear_error (&error);
-
-               /* We tried to read connections and failed */
-               g_signal_emit (self, signals[CONNECTIONS_READ], 0);
-               return;
-       }
-
-       /* Let listeners know we are done getting connections */
-       if (connections->len == 0)
-               g_signal_emit (self, signals[CONNECTIONS_READ], 0);
-       else {
-               priv->init_left = connections->len;
-               for (i = 0; i < connections->len; i++) {
-                       char *path = g_ptr_array_index (connections, i);
+       NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
+       AddConnectionInfo *addinfo;
+       GError *add_error;
 
-                       new_connection_cb (proxy, path, user_data);
-                       g_free (path);
-               }
+       addinfo = add_connection_info_find (self, failed_path);
+       if (addinfo) {
+               add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
+                                                NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
+                                                "Connection removed before it was initialized");
+               add_connection_info_complete (self, addinfo, NULL, add_error);
+               g_error_free (add_error);
        }
-
-       g_ptr_array_free (connections, TRUE);
 }
 
 /**
@@ -576,17 +410,16 @@ nm_remote_settings_list_connections (NMRemoteSettings *settings)
 {
        NMRemoteSettingsPrivate *priv;
        GSList *list = NULL;
-       GHashTableIter iter;
-       gpointer value;
+       int i;
 
        g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (priv->nm_running) {
-               g_hash_table_iter_init (&iter, priv->connections);
-               while (g_hash_table_iter_next (&iter, NULL, &value))
-                       list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
+       if (_nm_object_get_nm_running (NM_OBJECT (settings))) {
+               for (i = 0; i < priv->visible_connections->len; i++)
+                       list = g_slist_prepend (list, priv->visible_connections->pdata[i]);
+               list = g_slist_reverse (list);
        }
 
        return list;
@@ -600,12 +433,10 @@ add_connection_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data
        char *path = NULL;
 
        if (dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID)) {
-               info->connection = new_connection_cb (proxy, path, info->self);
-               g_assert (info->connection);
+               info->path = path;
                /* Wait until this connection is fully initialized before calling the callback */
-               g_free (path);
        } else
-               add_connection_info_complete (info->self, info, error);
+               add_connection_info_complete (info->self, info, NULL, error);
 
        g_clear_error (&error);
 }
@@ -646,7 +477,7 @@ nm_remote_settings_add_connection (NMRemoteSettings *settings,
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (!priv->nm_running)
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
                return FALSE;
 
        info = g_malloc0 (sizeof (AddConnectionInfo));
@@ -699,7 +530,7 @@ nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings,
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (!priv->nm_running)
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
                return FALSE;
 
        info = g_malloc0 (sizeof (AddConnectionInfo));
@@ -759,7 +590,7 @@ nm_remote_settings_load_connections (NMRemoteSettings *settings,
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (!priv->nm_running) {
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings))) {
                g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
                                     NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
                                     "NetworkManager is not running.");
@@ -806,7 +637,7 @@ nm_remote_settings_reload_connections (NMRemoteSettings *settings,
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (!priv->nm_running) {
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings))) {
                g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
                                     NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
                                     "NetworkManager is not running.");
@@ -821,29 +652,6 @@ nm_remote_settings_reload_connections (NMRemoteSettings *settings,
        return success;
 }
 
-static void
-clear_one_hash (GHashTable *table)
-{
-       GHashTableIter iter;
-       gpointer value;
-       GSList *list = NULL, *list_iter;
-
-       /* Build up the list of connections; we can't emit "removed" during hash
-        * table iteration because emission of the "removed" signal may trigger code
-        * that explicitly removes the connection from the hash table somewhere
-        * else.
-        */
-       g_hash_table_iter_init (&iter, table);
-       while (g_hash_table_iter_next (&iter, NULL, &value))
-               list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
-
-       for (list_iter = list; list_iter; list_iter = g_slist_next (list_iter))
-               g_signal_emit_by_name (NM_REMOTE_CONNECTION (list_iter->data), NM_REMOTE_CONNECTION_REMOVED);
-       g_slist_free (list);
-
-       g_hash_table_remove_all (table);
-}
-
 typedef struct {
        NMRemoteSettings *settings;
        NMRemoteSettingsSaveHostnameFunc callback;
@@ -893,7 +701,7 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings,
 
        priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-       if (!priv->nm_running)
+       if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
                return FALSE;
 
        info = g_malloc0 (sizeof (SaveHostnameInfo));
@@ -911,91 +719,64 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings,
 }
 
 static void
-properties_changed_cb (DBusGProxy *proxy,
-                       GHashTable *properties,
-                       gpointer user_data)
+updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
 {
        NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       GHashTableIter iter;
-       gpointer key, tmp;
-
-       g_hash_table_iter_init (&iter, properties);
-       while (g_hash_table_iter_next (&iter, &key, &tmp)) {
-               GValue *value = tmp;
-
-               if (!strcmp ((const char *) key, "Hostname")) {
-                       g_free (priv->hostname);
-                       priv->hostname = g_value_dup_string (value);
-                       g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME);
-               }
+       GError *error = NULL;
 
-               if (!strcmp ((const char *) key, "CanModify")) {
-                       priv->can_modify = g_value_get_boolean (value);
-                       g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY);
-               }
+       if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
+               g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message);
+               g_error_free (error);
        }
-}
-
-static void
-nm_appeared_got_properties (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
-{
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       GHashTable *props = NULL;
 
-       if (dbus_g_proxy_end_call (proxy, call, NULL,
-                                  DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-                                  G_TYPE_INVALID)) {
-               properties_changed_cb (priv->props_proxy, props, self);
-               g_hash_table_destroy (props);
-       }
+       g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING);
 }
 
 static void
-name_owner_changed (DBusGProxy *proxy,
-                    const char *name,
-                    const char *old_owner,
-                    const char *new_owner,
+nm_running_changed (GObject *object,
+                    GParamSpec *pspec,
                     gpointer user_data)
 {
-       NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+       NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-       const char *sname = NM_DBUS_SERVICE;
 
-       if (!strcmp (name, sname)) {
-               if (new_owner && strlen (new_owner) > 0) {
-                       priv->nm_running = TRUE;
+       g_object_freeze_notify (object);
 
-                       priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
-                                                                     fetch_connections_done, self, NULL,
-                                                                     G_TYPE_INVALID);
+       if (!_nm_object_get_nm_running (NM_OBJECT (self))) {
+               if (priv->all_connections) {
+                       GPtrArray *connections;
+                       int i;
 
-                       dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-                                                nm_appeared_got_properties, self, NULL,
-                                                G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
-                                                G_TYPE_INVALID);
-               } else {
-                       priv->nm_running = FALSE;
+                       connections = priv->all_connections;
+                       priv->all_connections = NULL;
 
-                       clear_one_hash (priv->pending);
-                       clear_one_hash (priv->connections);
+                       for (i = 0; i < connections->len; i++) {
+                               g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connections->pdata[i]);
+                               g_object_unref (connections->pdata[i]);
+                       }
+                       g_ptr_array_unref (connections);
+               }
 
-                       /* Clear properties */
+               /* Clear properties */
+               if (priv->hostname) {
                        g_free (priv->hostname);
                        priv->hostname = NULL;
                        g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME);
+               }
 
+               if (priv->can_modify) {
                        priv->can_modify = FALSE;
                        g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY);
-
-                       if (priv->listcon_call) {
-                               dbus_g_proxy_cancel_call (priv->proxy, priv->listcon_call);
-                               priv->listcon_call = NULL;
-                       }
                }
+
+               _nm_object_suppress_property_updates (NM_OBJECT (self), TRUE);
                g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING);
+       } else {
+               _nm_object_suppress_property_updates (NM_OBJECT (self), FALSE);
+               _nm_object_reload_properties_async (NM_OBJECT (self), updated_properties, self);
        }
+
+       g_object_thaw_notify (object);
 }
 
 /****************************************************************/
@@ -1021,20 +802,6 @@ nm_remote_settings_new (GCancellable  *cancellable,
                               NULL);
 }
 
-static void
-remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data)
-{
-       GSimpleAsyncResult *simple = user_data;
-       GError *error = NULL;
-
-       if (!g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error))
-               g_simple_async_result_take_error (simple, error);
-       else
-               g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
-       g_simple_async_result_complete (simple);
-       g_object_unref (simple);
-}
-
 /**
  * nm_remote_settings_new_async:
  * @cancellable: a #GCancellable, or %NULL
@@ -1048,14 +815,11 @@ remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_dat
  **/
 void
 nm_remote_settings_new_async (GCancellable *cancellable,
-                              GAsyncReadyCallback callback, gpointer user_data)
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
-       GSimpleAsyncResult *simple;
-
-       simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async);
-
        g_async_initable_new_async (NM_TYPE_REMOTE_SETTINGS, G_PRIORITY_DEFAULT, cancellable,
-                                   remote_settings_inited, simple,
+                                   callback, user_data,
                                    NULL);
 }
 
@@ -1071,27 +835,14 @@ nm_remote_settings_new_async (GCancellable *cancellable,
 NMRemoteSettings *
 nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
 {
-       GSimpleAsyncResult *simple;
+       GObject *source;
+       NMRemoteSettings *settings;
 
-       g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL);
+       source = g_async_result_get_source_object (result);
+       settings = (NMRemoteSettings *) g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
+       g_object_unref (source);
 
-       simple = G_SIMPLE_ASYNC_RESULT (result);
-       if (g_simple_async_result_propagate_error (simple, error))
-               return NULL;
-       else
-               return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static void
-forget_connection (gpointer user_data)
-{
-       NMRemoteConnection *remote = NM_REMOTE_CONNECTION (user_data);
-
-       g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
-                                             0, 0, NULL, connection_removed_cb, NULL);
-       g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
-                                             0, 0, NULL, connection_visible_changed_cb, NULL);
-       g_object_unref (remote);
+       return settings;
 }
 
 static void
@@ -1099,235 +850,61 @@ nm_remote_settings_init (NMRemoteSettings *self)
 {
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
 
-       priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
-       priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
+       priv->visible_connections = g_ptr_array_new ();
 }
 
 static void
-init_common (NMRemoteSettings *self)
+init_dbus (NMObject *object)
 {
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-
-       if (priv->private_bus == FALSE) {
-               /* D-Bus proxy for clearing connections on NameOwnerChanged */
-               priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
-                                                             DBUS_SERVICE_DBUS,
-                                                             DBUS_PATH_DBUS,
-                                                             DBUS_INTERFACE_DBUS);
-               g_assert (priv->dbus_proxy);
-
-               dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
-                                                  G_TYPE_NONE,
-                                                  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-                                                  G_TYPE_INVALID);
-               dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
-                                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-                                        G_TYPE_INVALID);
-               dbus_g_proxy_connect_signal (priv->dbus_proxy,
-                                            "NameOwnerChanged",
-                                            G_CALLBACK (name_owner_changed),
-                                            self, NULL);
-       }
-
-       priv->proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
-                                                        NM_DBUS_PATH_SETTINGS,
-                                                        NM_DBUS_INTERFACE_SETTINGS);
-       g_assert (priv->proxy);
-       dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
-
-       dbus_g_proxy_add_signal (priv->proxy, "NewConnection",
-                                DBUS_TYPE_G_OBJECT_PATH,
-                                G_TYPE_INVALID);
-       dbus_g_proxy_connect_signal (priv->proxy, "NewConnection",
-                                    G_CALLBACK (new_connection_cb),
-                                    self,
-                                    NULL);
-
-       /* D-Bus properties proxy */
-       priv->props_proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
-                                                              NM_DBUS_PATH_SETTINGS,
-                                                              "org.freedesktop.DBus.Properties");
-       g_assert (priv->props_proxy);
-
-       /* Monitor properties */
-       dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
-                                          G_TYPE_NONE,
-                                          DBUS_TYPE_G_MAP_OF_VARIANT,
-                                          G_TYPE_INVALID);
-       dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged",
-                                DBUS_TYPE_G_MAP_OF_VARIANT,
-                                G_TYPE_INVALID);
-       dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged",
-                                    G_CALLBACK (properties_changed_cb),
-                                    self,
-                                    NULL);
+       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
+       const NMPropertiesInfo property_info[] = {
+               { NM_REMOTE_SETTINGS_CONNECTIONS,      &priv->all_connections, NULL, NM_TYPE_REMOTE_CONNECTION, "connection" },
+               { NM_REMOTE_SETTINGS_HOSTNAME,         &priv->hostname },
+               { NM_REMOTE_SETTINGS_CAN_MODIFY,       &priv->can_modify },
+               { NULL },
+       };
+
+       NM_OBJECT_CLASS (nm_remote_settings_parent_class)->init_dbus (object);
+
+       priv->proxy = _nm_object_new_proxy (object,
+                                           NM_DBUS_PATH_SETTINGS,
+                                           NM_DBUS_INTERFACE_SETTINGS);
+       _nm_object_register_properties (object,
+                                       priv->proxy,
+                                       property_info);
+
+       g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING,
+                         G_CALLBACK (nm_running_changed), NULL);
 }
 
-static gboolean
-init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
 {
-       NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable);
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-       GHashTable *props;
-
-       init_common (settings);
-
-       if (priv->private_bus == FALSE) {
-               if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
-                                       G_TYPE_STRING, NM_DBUS_SERVICE,
-                                       G_TYPE_INVALID,
-                                       G_TYPE_BOOLEAN, &priv->nm_running,
-                                       G_TYPE_INVALID)) {
-                       priv->nm_running = FALSE;
-                       return FALSE;
+       guint i;
+       const char *dbus_path;
+
+       /* Fill in the right D-Bus path if none was specified */
+       for (i = 0; i < n_construct_params; i++) {
+               if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) {
+                       dbus_path = g_value_get_string (construct_params[i].value);
+                       if (dbus_path == NULL) {
+                               g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS);
+                       } else {
+                               if (!g_variant_is_object_path (dbus_path)) {
+                                       g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead",
+                                                  dbus_path, NM_DBUS_PATH);
+                                       g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS);
+                               }
+                       }
+                       break;
                }
-
-               /* If NM isn't running we'll grab properties from name_owner_changed()
-                * when it starts.
-                */
-               if (!priv->nm_running)
-                       return TRUE;
-       } else
-               priv->nm_running = TRUE;
-
-       priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
-                                                     fetch_connections_done, NM_REMOTE_SETTINGS (initable), NULL,
-                                                     G_TYPE_INVALID);
-
-       /* Get properties */
-       if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
-                               G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
-                               G_TYPE_INVALID,
-                               DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-                               G_TYPE_INVALID))
-               return FALSE;
-       properties_changed_cb (priv->props_proxy, props, settings);
-       g_hash_table_destroy (props);
-
-       return TRUE;
-}
-
-typedef struct {
-       NMRemoteSettings *settings;
-       GSimpleAsyncResult *result;
-} NMRemoteSettingsInitData;
-
-static void
-init_async_complete (NMRemoteSettingsInitData *init_data)
-{
-       g_simple_async_result_complete (init_data->result);
-       g_object_unref (init_data->result);
-       g_slice_free (NMRemoteSettingsInitData, init_data);
-}
-
-static void
-init_read_connections (NMRemoteSettings *settings, gpointer user_data)
-{
-       NMRemoteSettingsInitData *init_data = user_data;
-
-       g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (init_read_connections), user_data);
-
-       init_async_complete (init_data);
-}
-
-static void
-init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
-                           gpointer user_data)
-{
-       NMRemoteSettingsInitData *init_data = user_data;
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
-       GHashTable *props;
-       GError *error = NULL;
-
-       if (dbus_g_proxy_end_call (proxy, call, &error,
-                                  DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-                                  G_TYPE_INVALID)) {
-               properties_changed_cb (priv->props_proxy, props, init_data->settings);
-               g_hash_table_destroy (props);
-               g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
-       } else
-               g_simple_async_result_take_error (init_data->result, error);
-
-       /* Read connections and wait for the result */
-       priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
-                                                     fetch_connections_done, init_data->settings, NULL,
-                                                     G_TYPE_INVALID);
-       g_signal_connect (init_data->settings, "connections-read",
-                         G_CALLBACK (init_read_connections), init_data);
-}
-
-static void
-init_get_properties (NMRemoteSettingsInitData *init_data)
-{
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
-
-       dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-                                init_async_got_properties, init_data, NULL,
-                                G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
-                                G_TYPE_INVALID);
-}
-
-static void
-init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
-                                gpointer user_data)
-{
-       NMRemoteSettingsInitData *init_data = user_data;
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
-       GError *error = NULL;
-
-       if (!dbus_g_proxy_end_call (proxy, call, &error,
-                                   G_TYPE_BOOLEAN, &priv->nm_running,
-                                   G_TYPE_INVALID)) {
-               g_simple_async_result_take_error (init_data->result, error);
-               init_async_complete (init_data);
-               return;
-       }
-
-       if (!priv->nm_running) {
-               g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
-               init_async_complete (init_data);
-               return;
        }
 
-       init_get_properties (init_data);
-}
-
-static void
-init_async (GAsyncInitable *initable, int io_priority,
-            GCancellable *cancellable, GAsyncReadyCallback callback,
-            gpointer user_data)
-{
-       NMRemoteSettingsInitData *init_data;
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (initable);
-
-       init_data = g_slice_new0 (NMRemoteSettingsInitData);
-       init_data->settings = NM_REMOTE_SETTINGS (initable);
-       init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
-                                                      user_data, init_async);
-
-       init_common (init_data->settings);
-
-       if (priv->private_bus)
-               init_get_properties (init_data);
-       else {
-               /* Check if NM is running */
-               dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner",
-                                        init_async_got_manager_running,
-                                        init_data, NULL,
-                                        G_TYPE_STRING, NM_DBUS_SERVICE,
-                                        G_TYPE_INVALID);
-       }
-}
-
-static gboolean
-init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
-{
-       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
-       if (g_simple_async_result_propagate_error (simple, error))
-               return FALSE;
-       else
-               return TRUE;
+       return G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type,
+                                                                             n_construct_params,
+                                                                             construct_params);
 }
 
 static void
@@ -1339,52 +916,22 @@ dispose (GObject *object)
        while (g_slist_length (priv->add_list))
                add_connection_info_dispose (self, (AddConnectionInfo *) priv->add_list->data);
 
-       if (priv->connections) {
-               g_hash_table_destroy (priv->connections);
-               priv->connections = NULL;
-       }
+       if (priv->all_connections) {
+               int i;
 
-       if (priv->pending) {
-               g_hash_table_destroy (priv->pending);
-               priv->pending = NULL;
+               for (i = 0; i < priv->all_connections->len; i++) {
+                       cleanup_connection (self, priv->all_connections->pdata[i]);
+                       g_object_unref (priv->all_connections->pdata[i]);
+               }
+               g_clear_pointer (&priv->all_connections, g_ptr_array_unref);
        }
-
-       g_free (priv->hostname);
-       priv->hostname = NULL;
-
-       g_clear_object (&priv->dbus_proxy);
+       g_clear_pointer (&priv->visible_connections, g_ptr_array_unref);
+       g_clear_pointer (&priv->hostname, g_free);
        g_clear_object (&priv->proxy);
-       g_clear_object (&priv->props_proxy);
-
-       if (priv->bus) {
-               dbus_g_connection_unref (priv->bus);
-               priv->bus = NULL;
-       }
 
        G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
 }
 
-static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
-{
-       NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
-
-       switch (prop_id) {
-       case PROP_BUS:
-               /* Construct only */
-               priv->bus = g_value_dup_boxed (value);
-               if (!priv->bus) {
-                       priv->bus = _nm_dbus_new_connection (NULL);
-                       priv->private_bus = _nm_dbus_is_connection_private (priv->bus);
-               }
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
-}
-
 static void
 get_property (GObject *object, guint prop_id,
               GValue *value, GParamSpec *pspec)
@@ -1392,11 +939,11 @@ get_property (GObject *object, guint prop_id,
        NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
 
        switch (prop_id) {
-       case PROP_BUS:
-               g_value_set_boxed (value, priv->bus);
-               break;
        case PROP_NM_RUNNING:
-               g_value_set_boolean (value, priv->nm_running);
+               g_value_set_boolean (value, _nm_object_get_nm_running (NM_OBJECT (object)));
+               break;
+       case PROP_CONNECTIONS:
+               g_value_set_boxed (value, priv->visible_connections);
                break;
        case PROP_HOSTNAME:
                g_value_set_string (value, priv->hostname);
@@ -1414,29 +961,22 @@ static void
 nm_remote_settings_class_init (NMRemoteSettingsClass *class)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (class);
+       NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class);
 
        g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
 
        /* Virtual methods */
-       object_class->set_property = set_property;
+       object_class->constructor = constructor;
        object_class->get_property = get_property;
        object_class->dispose = dispose;
 
-       /* Properties */
+       nm_object_class->init_dbus = init_dbus;
+       nm_object_class->object_creation_failed = object_creation_failed;
 
-       /**
-        * NMRemoteSettings:bus:
-        *
-        * The #DBusGConnection that the #NMRemoteSettings is connected to. Defaults
-        * to the system bus if not specified.
-        */
-       g_object_class_install_property
-               (object_class, PROP_BUS,
-                g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS, "", "",
-                                    DBUS_TYPE_G_CONNECTION,
-                                    G_PARAM_READWRITE |
-                                    G_PARAM_CONSTRUCT_ONLY |
-                                    G_PARAM_STATIC_STRINGS));
+       class->connection_added = connection_added;
+       class->connection_removed = connection_removed;
+
+       /* Properties */
 
        /**
         * NMRemoteSettings:nm-running:
@@ -1450,6 +990,23 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
                                       G_PARAM_READABLE |
                                       G_PARAM_STATIC_STRINGS));
 
+       /**
+        * NMRemoteSettings:connections:
+        *
+        * The list of configured connections that are available to the user. (Note
+        * that this differs from the underlying D-Bus property, which may also
+        * contain the object paths of connections that the user does not have
+        * permission to read the details of.)
+        *
+        * Type: GPtrArray
+        */
+       g_object_class_install_property
+               (object_class, PROP_CONNECTIONS,
+                g_param_spec_boxed (NM_REMOTE_SETTINGS_CONNECTIONS, "", "",
+                                    NM_TYPE_OBJECT_ARRAY,
+                                    G_PARAM_READABLE |
+                                    G_PARAM_STATIC_STRINGS));
+
        /**
         * NMRemoteSettings:hostname:
         *
@@ -1476,32 +1033,35 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
                                       G_PARAM_STATIC_STRINGS));
 
        /* Signals */
-       signals[NEW_CONNECTION] =
-               g_signal_new (NM_REMOTE_SETTINGS_NEW_CONNECTION,
+       /**
+        * NMRemoteSettings::connection-added:
+        * @settings: the settings object that received the signal
+        * @connection: the new connection
+        *
+        * Notifies that a #NMConnection has been added.
+        **/
+       signals[CONNECTION_ADDED] =
+               g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_ADDED,
                              G_OBJECT_CLASS_TYPE (object_class),
                              G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (NMRemoteSettingsClass, new_connection),
+                             G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_added),
                              NULL, NULL, NULL,
-                             G_TYPE_NONE, 1, G_TYPE_OBJECT);
+                             G_TYPE_NONE, 1,
+                             NM_TYPE_REMOTE_CONNECTION);
 
-       signals[CONNECTIONS_READ] =
-               g_signal_new (NM_REMOTE_SETTINGS_CONNECTIONS_READ,
+       /**
+        * NMRemoteSettings::connection-removed:
+        * @settings: the settings object that received the signal
+        * @connection: the removed connection
+        *
+        * Notifies that a #NMConnection has been removed.
+        **/
+       signals[CONNECTION_REMOVED] =
+               g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_REMOVED,
                              G_OBJECT_CLASS_TYPE (object_class),
                              G_SIGNAL_RUN_FIRST,
-                             G_STRUCT_OFFSET (NMRemoteSettingsClass, connections_read),
+                             G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_removed),
                              NULL, NULL, NULL,
-                             G_TYPE_NONE, 0);
-}
-
-static void
-nm_remote_settings_initable_iface_init (GInitableIface *iface)
-{
-       iface->init = init_sync;
-}
-
-static void
-nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface)
-{
-       iface->init_async = init_async;
-       iface->init_finish = init_finish;
+                             G_TYPE_NONE, 1,
+                             NM_TYPE_REMOTE_CONNECTION);
 }
index 1aa22f5..7ba7527 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include <gio/gio.h>
+#include <nm-object.h>
 #include <nm-connection.h>
 #include <nm-remote-connection.h>
 
@@ -62,13 +63,13 @@ typedef enum {
 GQuark nm_remote_settings_error_quark (void);
 
 
-#define NM_REMOTE_SETTINGS_BUS             "bus"
 #define NM_REMOTE_SETTINGS_NM_RUNNING      "nm-running"
+#define NM_REMOTE_SETTINGS_CONNECTIONS     "connections"
 #define NM_REMOTE_SETTINGS_HOSTNAME        "hostname"
 #define NM_REMOTE_SETTINGS_CAN_MODIFY      "can-modify"
 
-#define NM_REMOTE_SETTINGS_NEW_CONNECTION    "new-connection"
-#define NM_REMOTE_SETTINGS_CONNECTIONS_READ  "connections-read"
+#define NM_REMOTE_SETTINGS_CONNECTION_ADDED   "connection-added"
+#define NM_REMOTE_SETTINGS_CONNECTION_REMOVED "connection-removed"
 
 typedef struct _NMRemoteSettings NMRemoteSettings;
 typedef struct _NMRemoteSettingsClass NMRemoteSettingsClass;
@@ -90,17 +91,17 @@ typedef void (*NMRemoteSettingsSaveHostnameFunc) (NMRemoteSettings *settings,
 
 
 struct _NMRemoteSettings {
-       GObject parent;
+       NMObject parent;
 };
 
 struct _NMRemoteSettingsClass {
-       GObjectClass parent;
+       NMObjectClass parent;
 
        /* Signals */
-       void (*new_connection) (NMRemoteSettings *settings,
-                               NMRemoteConnection *connection);
-
-       void (*connections_read) (NMRemoteSettings *settings);
+       void (*connection_added)   (NMRemoteSettings *settings,
+                                   NMRemoteConnection *connection);
+       void (*connection_removed) (NMRemoteSettings *settings,
+                                   NMRemoteConnection *connection);
 
        /*< private >*/
        gpointer padding[8];
index 4333e68..3ba64a3 100644 (file)
@@ -119,9 +119,17 @@ set_visible_cb (DBusGProxy *proxy,
 }
 
 static void
-invis_removed_cb (NMRemoteConnection *connection, gboolean *done)
+visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done)
 {
-       *done = TRUE;
+       if (!nm_remote_connection_get_visible (NM_REMOTE_CONNECTION (object)))
+               *done = TRUE;
+}
+
+static void
+connection_removed_cb (NMRemoteSettings *s, NMRemoteConnection *connection, gboolean *done)
+{
+       if (connection == remote)
+               *done = TRUE;
 }
 
 static void
@@ -140,13 +148,15 @@ test_make_invisible (void)
        time_t start, now;
        GSList *list, *iter;
        DBusGProxy *proxy;
-       gboolean done = FALSE, has_settings = FALSE;
+       gboolean visible_changed = FALSE, connection_removed = FALSE;
+       gboolean has_settings = FALSE;
        char *path;
 
        g_assert (remote != NULL);
 
        /* Listen for the remove event when the connection becomes invisible */
-       g_signal_connect (remote, "removed", G_CALLBACK (invis_removed_cb), &done);
+       g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed);
+       g_signal_connect (settings, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed);
 
        path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
        proxy = dbus_g_proxy_new_for_name (bus,
@@ -164,11 +174,12 @@ test_make_invisible (void)
        do {
                now = time (NULL);
                g_main_context_iteration (NULL, FALSE);
-       } while ((done == FALSE) && (now - start < 5));
-       g_assert (done == TRUE);
+       } while ((!visible_changed || !connection_removed) && (now - start < 5));
+       g_assert (visible_changed == TRUE);
+       g_assert (connection_removed == TRUE);
 
-       g_assert (remote);
-       g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (invis_removed_cb), &done);
+       g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed);
+       g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (connection_removed_cb), &connection_removed);
 
        /* Ensure NMRemoteSettings no longer has the connection */
        list = nm_remote_settings_list_connections (settings);
@@ -213,7 +224,7 @@ test_make_visible (void)
        g_assert (remote != NULL);
 
        /* Wait for the new-connection signal when the connection is visible again */
-       g_signal_connect (settings, NM_REMOTE_SETTINGS_NEW_CONNECTION,
+       g_signal_connect (settings, NM_REMOTE_SETTINGS_CONNECTION_ADDED,
                          G_CALLBACK (vis_new_connection_cb), &new);
 
        path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
@@ -275,9 +286,10 @@ deleted_cb (DBusGProxy *proxy,
 }
 
 static void
-removed_cb (NMRemoteConnection *connection, gboolean *done)
+removed_cb (NMRemoteSettings *s, NMRemoteConnection *connection, gboolean *done)
 {
-       *done = TRUE;
+       if (connection == remote)
+               *done = TRUE;
 }
 
 static void
@@ -298,7 +310,7 @@ test_remove_connection (void)
        g_assert (connection);
        g_assert (remote == connection);
        path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection)));
-       g_signal_connect (connection, "removed", G_CALLBACK (removed_cb), &done);
+       g_signal_connect (settings, "connection-removed", G_CALLBACK (removed_cb), &done);
 
        proxy = dbus_g_proxy_new_for_name (bus,
                                           NM_DBUS_SERVICE,
@@ -373,7 +385,7 @@ test_nm_running (void)
        nm_test_service_cleanup (sinfo);
 
        settings2 = g_initable_new (NM_TYPE_REMOTE_SETTINGS, NULL, &error,
-                                   NM_REMOTE_SETTINGS_BUS, bus,
+                                   NM_OBJECT_DBUS_CONNECTION, bus,
                                    NULL);
        g_assert_no_error (error);
        g_assert (settings != NULL);
@@ -438,7 +450,7 @@ main (int argc, char **argv)
        sinfo = nm_test_service_init ();
 
        settings = g_initable_new (NM_TYPE_REMOTE_SETTINGS, NULL, &error,
-                                  NM_REMOTE_SETTINGS_BUS, bus,
+                                  NM_OBJECT_DBUS_CONNECTION, bus,
                                   NULL);
        g_assert_no_error (error);
        g_assert (settings != NULL);