about summary refs log tree commit diff
path: root/libnm-glib/nm-remote-settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-glib/nm-remote-settings.c')
-rw-r--r--libnm-glib/nm-remote-settings.c430
1 files changed, 297 insertions, 133 deletions
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
index 7658623f..8f213f9e 100644
--- a/libnm-glib/nm-remote-settings.c
+++ b/libnm-glib/nm-remote-settings.c
@@ -18,25 +18,32 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2008 Novell, Inc.
- * Copyright (C) 2009 - 2011 Red Hat, Inc.
+ * Copyright (C) 2009 - 2012 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <NetworkManager.h>
 #include <nm-connection.h>
 
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-remote-settings.h"
-#include "nm-settings-bindings.h"
 #include "nm-remote-connection-private.h"
+#include "nm-glib-compat.h"
 
-G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT)
+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);
+                         )
 
 #define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
 
 typedef struct {
 	DBusGConnection *bus;
+	gboolean inited;
 
 	DBusGProxy *proxy;
 	GHashTable *connections;
@@ -96,24 +103,27 @@ nm_remote_settings_error_quark (void)
 	return quark;
 }
 
-/* This should really be standard. */
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+/**********************************************************************/
 
-GType
-nm_remote_settings_error_get_type (void)
+static void
+_nm_remote_settings_ensure_inited (NMRemoteSettings *self)
 {
-	static GType etype = 0;
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	GError *error;
 
-	if (etype == 0) {
-		static const GEnumValue values[] = {
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_UNKNOWN, "UnknownError"),
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, "ConnectionRemoved"),
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, "ConnectionUnavailable"),
-			{ 0, 0, 0 }
-		};
-		etype = g_enum_register_static ("NMRemoteSettingsError", values);
+	if (!priv->inited) {
+		if (!g_initable_init (G_INITABLE (self), NULL, &error)) {
+			/* Don't warn when the call times out because the settings service can't
+			 * be activated or whatever.
+			 */
+			if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
+				g_warning ("%s: (NMRemoteSettings) error initializing: %s\n",
+					       __func__, error->message);
+			}
+			g_error_free (error);
+		}
+		priv->inited = TRUE;
 	}
-	return etype;
 }
 
 /**********************************************************************/
@@ -175,11 +185,17 @@ add_connection_info_complete (NMRemoteSettings *self,
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path)
 {
+	NMRemoteSettingsPrivate *priv;
+
 	g_return_val_if_fail (settings != NULL, NULL);
 	g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return g_hash_table_lookup (NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections, path);
+	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+	_nm_remote_settings_ensure_inited (settings);
+
+	return priv->service_running ? g_hash_table_lookup (priv->connections, path) : NULL;
 }
 
 /**
@@ -195,6 +211,7 @@ 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;
 
@@ -202,10 +219,16 @@ nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const cha
 	g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
 	g_return_val_if_fail (uuid != NULL, NULL);
 
-	g_hash_table_iter_init (&iter, NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->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;
+	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+	_nm_remote_settings_ensure_inited (settings);
+
+	if (priv->service_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;
@@ -278,37 +301,20 @@ connection_visible_cb (NMRemoteConnection *remote,
 }
 
 static void
-connection_init_result_cb (NMRemoteConnection *remote,
-                           GParamSpec *pspec,
-                           gpointer user_data)
+connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
 {
+	NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source);
 	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-	guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
 	AddConnectionInfo *addinfo;
 	const char *path;
-	GError *add_error = NULL;
+	GError *error = NULL;
 	gboolean remove_from_pending = TRUE;
 
-	/* Disconnect from the init-result signal just to be safe */
-	g_signal_handlers_disconnect_matched (remote,
-	                                      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-	                                      0,
-	                                      0,
-	                                      NULL,
-	                                      G_CALLBACK (connection_init_result_cb),
-	                                      self);
-
 	path = nm_connection_get_path (NM_CONNECTION (remote));
-
-	g_object_get (G_OBJECT (remote),
-	              NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
-	              NULL);
-
 	addinfo = add_connection_info_find (self, remote);
 
-	switch (init_result) {
-	case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
+	if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) {
 		/* ref it when adding to ->connections, since removing it from ->pending
 		 * will unref it.
 		 */
@@ -324,22 +330,20 @@ connection_init_result_cb (NMRemoteConnection *remote,
 		 * its settings and is valid.
 		 */
 		g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
-		break;
-	case NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE:
-		remove_from_pending = FALSE;
-		/* fall through */
-	case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
-		/* Complete pending AddConnection callbacks */
+	} else {
+		if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied")) {
+			/* Connection doesn't exist, or isn't visible to this user */
+			remove_from_pending = FALSE;
+		}
+		g_error_free (error);
+
 		if (addinfo) {
-			add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
-			                                 NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
-			                                 "Connection not visible or not available");
-			add_connection_info_complete (self, addinfo, add_error);
-			g_error_free (add_error);
+			error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
+			                             NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
+			                             "Connection not visible or not available");
+			add_connection_info_complete (self, addinfo, error);
+			g_error_free (error);
 		}
-		break;
-	default:
-		break;
 	}
 
 	if (remove_from_pending)
@@ -377,9 +381,9 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 		                  G_CALLBACK (connection_visible_cb),
 		                  self);
 
-		g_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT,
-		                  G_CALLBACK (connection_init_result_cb),
-		                  self);
+		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
@@ -392,15 +396,18 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 
 static void
 fetch_connections_done (DBusGProxy *proxy,
-                        GPtrArray *connections,
-                        GError *error,
+                        DBusGProxyCall *call,
                         gpointer user_data)
 {
 	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	GPtrArray *connections;
+	GError *error = NULL;
 	int i;
 
-	if (error) {
+	if (!dbus_g_proxy_end_call (proxy, call, &error, 
+	                            DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &connections,
+	                            G_TYPE_INVALID)) {
 		/* Ignore settings service spawn errors */
 		if (   !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
 		    && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER)) {
@@ -440,9 +447,9 @@ fetch_connections (gpointer user_data)
 
 	priv->fetch_id = 0;
 
-	org_freedesktop_NetworkManager_Settings_list_connections_async (priv->proxy,
-	                                                                fetch_connections_done,
-	                                                                self);
+	dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
+	                         fetch_connections_done, self, NULL,
+	                         G_TYPE_INVALID);
 	return FALSE;
 }
 
@@ -470,9 +477,13 @@ nm_remote_settings_list_connections (NMRemoteSettings *settings)
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-	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));
+	_nm_remote_settings_ensure_inited (settings);
+
+	if (priv->service_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));
+	}
 
 	return list;
 }
@@ -525,7 +536,9 @@ nm_remote_settings_add_connection (NMRemoteSettings *settings,
 	g_return_val_if_fail (callback != NULL, FALSE);
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-	
+
+	_nm_remote_settings_ensure_inited (settings);
+
 	info = g_malloc0 (sizeof (AddConnectionInfo));
 	info->self = settings;
 	info->callback = callback;
@@ -629,6 +642,8 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings,
 	
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
+	_nm_remote_settings_ensure_inited (settings);
+
 	info = g_malloc0 (sizeof (SaveHostnameInfo));
 	info->settings = settings;
 	info->callback = callback;
@@ -696,35 +711,6 @@ properties_changed_cb (DBusGProxy *proxy,
 	}
 }
 
-static void
-get_all_cb  (DBusGProxy *proxy,
-             DBusGProxyCall *call,
-             gpointer user_data)
-{
-	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-	GHashTable *props = NULL;
-	GError *error = NULL;
-
-	if (!dbus_g_proxy_end_call (proxy, call, &error,
-	                            DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-	                            G_TYPE_INVALID)) {
-		/* Don't warn when the call times out because the settings service can't
-		 * be activated or whatever.
-		 */
-		if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) {
-			g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.",
-			           __func__,
-			           error ? error->code : -1,
-			           (error && error->message) ? error->message : "(unknown)");
-		}
-		g_clear_error (&error);
-		return;
-	}
-
-	properties_changed_cb (NULL, props, self);
-	g_hash_table_destroy (props);
-}
-
 /****************************************************************/
 
 /**
@@ -733,16 +719,84 @@ get_all_cb  (DBusGProxy *proxy,
  *
  * Creates a new object representing the remote settings service.
  *
+ * Note that this will do blocking D-Bus calls to initialize the
+ * settings object. You can use nm_remote_settings_new_async() if you
+ * want to avoid that.
+ *
  * Returns: the new remote settings object on success, or %NULL on failure
  **/
 NMRemoteSettings *
 nm_remote_settings_new (DBusGConnection *bus)
 {
-	return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS,
-	                                          NM_REMOTE_SETTINGS_BUS, bus,
-	                                          NULL);
+	return g_object_new (NM_TYPE_REMOTE_SETTINGS, NM_REMOTE_SETTINGS_BUS, bus, NULL);
+}
+
+static void
+remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_init_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:
+ * @bus: (allow-none): a valid and connected D-Bus connection
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the settings object is created
+ * @user_data: data for @callback
+ *
+ * Creates a new object representing the remote settings service and
+ * begins asynchronously initializing it. @callback will be called
+ * when it is done; use nm_remote_settings_new_finish() to get the
+ * result.
+ **/
+void
+nm_remote_settings_new_async (DBusGConnection *bus, GCancellable *cancellable,
+                              GAsyncReadyCallback callback, gpointer user_data)
+{
+	NMRemoteSettings *self;
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async);
+
+	self = g_object_new (NM_TYPE_REMOTE_SETTINGS,
+	                     NM_REMOTE_SETTINGS_BUS, bus,
+	                     NULL);
+	g_async_initable_init_async (G_ASYNC_INITABLE (self), G_PRIORITY_DEFAULT,
+	                             cancellable, remote_settings_inited, simple);
+}
+
+/**
+ * nm_remote_settings_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_remote_settings_new_async() call.
+ *
+ * Returns: a new #NMRemoteSettings object, or %NULL on error
+ **/
+NMRemoteSettings *
+nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL);
+
+	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
 nm_remote_settings_init (NMRemoteSettings *self)
 {
@@ -752,18 +806,10 @@ nm_remote_settings_init (NMRemoteSettings *self)
 	priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 }
 
-static GObject *
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMRemoteSettingsPrivate *priv;
-	GError *error = NULL;
-
-	object = G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, n_construct_params, construct_params);
-	if (!object)
-		return NULL;
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
 
@@ -774,7 +820,7 @@ constructor (GType type,
 	                                              "org.freedesktop.DBus");
 	g_assert (priv->dbus_proxy);
 
-	dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
+	dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
 	                                   G_TYPE_NONE,
 	                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 	                                   G_TYPE_INVALID);
@@ -786,19 +832,6 @@ constructor (GType type,
 	                             G_CALLBACK (name_owner_changed),
 	                             object, NULL);
 
-	if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", &error,
-	                        G_TYPE_STRING, NM_DBUS_SERVICE,
-	                        G_TYPE_INVALID,
-	                        G_TYPE_BOOLEAN, &priv->service_running,
-	                        G_TYPE_INVALID)) {
-		g_warning ("%s (NMRemoteSettings) error getting remote settings service status: (%d) %s\n",
-		           __func__,
-		           error ? error->code : -1,
-		           error && error->message ? error->message : "(unknown)");
-		g_error_free (error);
-		priv->service_running = FALSE;
-	}
-
 	priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
 	                                         NM_DBUS_SERVICE,
 	                                         NM_DBUS_PATH_SETTINGS,
@@ -836,16 +869,136 @@ constructor (GType type,
 	                             G_CALLBACK (properties_changed_cb),
 	                             object,
 	                             NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+	GHashTable *props;
+
+	if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
+	                        G_TYPE_STRING, NM_DBUS_SERVICE,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_BOOLEAN, &priv->service_running,
+	                        G_TYPE_INVALID)) {
+		priv->service_running = FALSE;
+		return FALSE;
+	}
 
 	/* Get properties */
+	if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
+	                        G_TYPE_STRING, NM_DBUS_IFACE_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);
+
+	/* FIXME: need a synchronous fetch_connections too */
+
+	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);
+
+	if (priv->init_left) {
+		/* Still creating initial connections; wait for that to complete */
+		g_signal_connect (init_data->settings, "connections-read",
+		                  G_CALLBACK (init_read_connections), init_data);
+		return;
+	}
+
+	init_async_complete (init_data);
+}
+
+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->service_running,
+	                            G_TYPE_INVALID)) {
+		g_simple_async_result_take_error (init_data->result, error);
+		init_async_complete (init_data);
+		return;
+	}
+
+	if (!priv->service_running) {
+		g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+		init_async_complete (init_data);
+		return;
+	}
+
 	dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-	                         get_all_cb,
-	                         object,
-	                         NULL,
+	                         init_async_got_properties, init_data, NULL,
 	                         G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
-	                         G_TYPE_INVALID);	
+	                         G_TYPE_INVALID);
+}
 
-	return object;
+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);
+
+	/* 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 void
@@ -935,7 +1088,7 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
 	g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
 
 	/* Virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
@@ -993,3 +1146,14 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
 	                              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;
+}