diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 318a463bb6..7bf4fefb74 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -43,7 +43,7 @@ libdeprecated_HEADERS = libnm_glib.h lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la libnm_glib_la_CFLAGS = \ - $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ $(DBUS_CFLAGS) \ $(GUDEV_CFLAGS) @@ -117,7 +117,7 @@ libnm_glib_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ $(top_builddir)/marshallers/libmarshallers.la \ $(builddir)/libdeprecated-nm-glib.la \ - $(GLIB_LIBS) \ + $(GIO_LIBS) \ $(DBUS_LIBS) \ $(GUDEV_LIBS) @@ -129,16 +129,16 @@ libnm_glib_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \ noinst_PROGRAMS = libnm-glib-test libnm_glib_test_SOURCES = libnm-glib-test.c -libnm_glib_test_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS) -libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS) +libnm_glib_test_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS) +libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS) libnm_glib_vpn_la_SOURCES = \ nm-vpn-plugin.c \ nm-vpn-plugin-ui-interface.c \ nm-vpn-plugin-utils.c -libnm_glib_vpn_la_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS) -libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS) +libnm_glib_vpn_la_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS) +libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS) libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \ -version-info "2:0:1" @@ -147,7 +147,7 @@ libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \ ##################################################### libnm_glib_test_la_CFLAGS = \ - $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ $(DBUS_CFLAGS) \ $(GUDEV_CFLAGS) \ -DLIBNM_GLIB_TEST @@ -159,7 +159,7 @@ libnm_glib_test_la_SOURCES = \ libnm_glib_test_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ $(top_builddir)/marshallers/libmarshallers.la \ - $(GLIB_LIBS) \ + $(GIO_LIBS) \ $(DBUS_LIBS) \ $(GUDEV_LIBS) diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c index 9a2536520d..53993b0728 100644 --- a/libnm-glib/nm-access-point.c +++ b/libnm-glib/nm-access-point.c @@ -533,30 +533,21 @@ register_properties (NMAccessPoint *ap) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; NMAccessPointPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_access_point_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_access_point_parent_class)->constructed (object); priv = NM_ACCESS_POINT_GET_PRIVATE (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_ACCESS_POINT); register_properties (NM_ACCESS_POINT (object)); - - return G_OBJECT (object); } @@ -568,7 +559,7 @@ nm_access_point_class_init (NMAccessPointClass *ap_class) g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c index 0c922b7b40..9c5be58fee 100644 --- a/libnm-glib/nm-active-connection.c +++ b/libnm-glib/nm-active-connection.c @@ -445,30 +445,21 @@ register_properties (NMActiveConnection *connection) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; NMActiveConnectionPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object); priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_ACTIVE_CONNECTION); register_properties (NM_ACTIVE_CONNECTION (object)); - - return G_OBJECT (object); } @@ -480,7 +471,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class) g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index b1576b70ba..8fb76e6abf 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -39,7 +39,15 @@ void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); -G_DEFINE_TYPE (NMClient, nm_client, NM_TYPE_OBJECT) +static void nm_client_initable_iface_init (GInitableIface *iface); +static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface); +static GInitableIface *nm_client_parent_initable_iface; +static GAsyncInitableIface *nm_client_parent_async_initable_iface; + +G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init); + ) #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate)) @@ -372,19 +380,21 @@ update_permissions (NMClient *self, GHashTable *permissions) g_list_free (keys); } -static void -get_permissions_sync (NMClient *self) +static gboolean +get_permissions_sync (NMClient *self, GError **error) { gboolean success; GHashTable *permissions = NULL; success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy, - "GetPermissions", 3000, NULL, + "GetPermissions", 3000, error, G_TYPE_INVALID, DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID); update_permissions (self, success ? permissions : NULL); if (permissions) g_hash_table_destroy (permissions); + + return success; } static void @@ -1191,6 +1201,7 @@ nm_client_new (void) { DBusGConnection *connection; GError *err = NULL; + NMClient *client; #ifdef LIBNM_GLIB_TEST connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err); @@ -1203,34 +1214,28 @@ nm_client_new (void) return NULL; } - return (NMClient *) g_object_new (NM_TYPE_CLIENT, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, - NULL); + client = g_object_new (NM_TYPE_CLIENT, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, + NULL); + _nm_object_ensure_inited (NM_OBJECT (client)); + return client; } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; DBusGConnection *connection; NMClientPrivate *priv; - GError *err = NULL; - object = (NMObject *) G_OBJECT_CLASS (nm_client_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_client_parent_class)->constructed (object); priv = NM_CLIENT_GET_PRIVATE (object); - connection = nm_object_get_connection (object); + connection = nm_object_get_connection (NM_OBJECT (object)); priv->client_proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE); register_properties (NM_CLIENT (object)); @@ -1242,7 +1247,6 @@ constructor (GType type, G_CALLBACK (client_recheck_permissions), object, NULL); - get_permissions_sync (NM_CLIENT (object)); priv->bus_proxy = dbus_g_proxy_new_for_name (connection, DBUS_SERVICE_DBUS, @@ -1257,38 +1261,136 @@ constructor (GType type, G_CALLBACK (proxy_name_owner_changed), object, NULL); - if (!dbus_g_proxy_call (priv->bus_proxy, - "NameHasOwner", &err, - G_TYPE_STRING, NM_DBUS_SERVICE, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &priv->manager_running, - G_TYPE_INVALID)) { - g_warning ("Error on NameHasOwner DBUS call: %s", err->message); - g_error_free (err); - } - - if (priv->manager_running) { - update_wireless_status (NM_CLIENT (object), FALSE); - update_wwan_status (NM_CLIENT (object), FALSE); - update_wimax_status (NM_CLIENT (object), FALSE); - nm_client_get_state (NM_CLIENT (object)); - } - - g_signal_connect (G_OBJECT (object), "notify::" NM_CLIENT_WIRELESS_ENABLED, + g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED, G_CALLBACK (wireless_enabled_cb), NULL); g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS, G_CALLBACK (active_connections_changed_cb), NULL); +} - /* Get initial devices from NM. It is important to do it early. Else, - * a 'lazy' call won't find removed device. - * Solves this case: DeviceRemoved signal is received, we get devices - * from NM, but the removed object path is not there any more, and - * NMClient doesn't have the device either. - */ - nm_client_get_devices (NM_CLIENT (object)); +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMClient *client = NM_CLIENT (initable); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); - return G_OBJECT (object); + if (!nm_client_parent_initable_iface->init (initable, cancellable, error)) + return FALSE; + + if (!dbus_g_proxy_call (priv->bus_proxy, + "NameHasOwner", error, + G_TYPE_STRING, NM_DBUS_SERVICE, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &priv->manager_running, + G_TYPE_INVALID)) + return FALSE; + + if (priv->manager_running && !get_permissions_sync (client, error)) + return FALSE; + + return TRUE; +} + +typedef struct { + NMClient *client; + GSimpleAsyncResult *result; + gboolean properties_pending; + gboolean permissions_pending; +} NMClientInitData; + +static void +init_async_complete (NMClientInitData *init_data) +{ + if (init_data->properties_pending || init_data->permissions_pending) + return; + + g_simple_async_result_complete (init_data->result); + g_object_unref (init_data->result); + g_slice_free (NMClientInitData, init_data); +} + +static void +init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMClientInitData *init_data = user_data; + GHashTable *permissions; + GError *error = NULL; + + dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_STRING, &permissions, + G_TYPE_INVALID); + update_permissions (init_data->client, error ? NULL : permissions); + g_clear_error (&error); + + init_data->permissions_pending = FALSE; + init_async_complete (init_data); +} + +static void +init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMClientInitData *init_data = user_data; + GError *error = NULL; + + if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) + g_simple_async_result_take_error (init_data->result, error); + + init_data->properties_pending = FALSE; + init_async_complete (init_data); +} + +static void +init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + NMClientInitData *init_data = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client); + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_BOOLEAN, &priv->manager_running, + G_TYPE_INVALID)) { + g_simple_async_result_take_error (init_data->result, error); + init_async_complete (init_data); + return; + } + + if (!priv->manager_running) { + g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); + init_async_complete (init_data); + return; + } + + nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client), + G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */ + init_async_got_properties, init_data); + init_data->properties_pending = TRUE; + + dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions", + init_async_got_permissions, init_data, NULL, + G_TYPE_INVALID); + init_data->permissions_pending = TRUE; +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMClientInitData *init_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable); + + init_data = g_slice_new0 (NMClientInitData); + init_data->client = NM_CLIENT (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->bus_proxy, "NameHasOwner", + init_async_got_manager_running, + init_data, NULL, + G_TYPE_STRING, NM_DBUS_SERVICE, + G_TYPE_INVALID); } static void @@ -1427,7 +1529,7 @@ nm_client_class_init (NMClientClass *client_class) g_type_class_add_private (client_class, sizeof (NMClientPrivate)); /* 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; @@ -1631,3 +1733,18 @@ nm_client_class_init (NMClientClass *client_class) G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); } +static void +nm_client_initable_iface_init (GInitableIface *iface) +{ + nm_client_parent_initable_iface = g_type_interface_peek_parent (iface); + + iface->init = init_sync; +} + +static void +nm_client_async_initable_iface_init (GAsyncInitableIface *iface) +{ + nm_client_parent_async_initable_iface = g_type_interface_peek_parent (iface); + + iface->init_async = init_async; +} diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c index 4c9f95511c..581d1d03b3 100644 --- a/libnm-glib/nm-device-bt.c +++ b/libnm-glib/nm-device-bt.c @@ -216,28 +216,19 @@ register_properties (NMDeviceBt *device) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - object = G_OBJECT_CLASS (nm_device_bt_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (object) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), - NM_DBUS_SERVICE, - nm_object_get_path (NM_OBJECT (object)), - NM_DBUS_INTERFACE_DEVICE_BLUETOOTH); + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), + NM_DBUS_SERVICE, + nm_object_get_path (NM_OBJECT (object)), + NM_DBUS_INTERFACE_DEVICE_BLUETOOTH); - register_properties (NM_DEVICE_BT (object)); - } - - return object; + register_properties (NM_DEVICE_BT (object)); } static void @@ -300,7 +291,7 @@ nm_device_bt_class_init (NMDeviceBtClass *bt_class) g_type_class_add_private (bt_class, sizeof (NMDeviceBtPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c index c043113e7b..1dd45f3bd6 100644 --- a/libnm-glib/nm-device-ethernet.c +++ b/libnm-glib/nm-device-ethernet.c @@ -75,13 +75,17 @@ enum { GObject * nm_device_ethernet_new (DBusGConnection *connection, const char *path) { + GObject *device; + g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); - return g_object_new (NM_TYPE_DEVICE_ETHERNET, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + device = g_object_new (NM_TYPE_DEVICE_ETHERNET, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return device; } /** @@ -224,19 +228,12 @@ register_properties (NMDeviceEthernet *device) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMDeviceEthernetPrivate *priv; - object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructed (object); priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); @@ -246,8 +243,6 @@ constructor (GType type, NM_DBUS_INTERFACE_DEVICE_WIRED); register_properties (NM_DEVICE_ETHERNET (object)); - - return object; } static void @@ -314,7 +309,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c index 384a348076..9ac38257bc 100644 --- a/libnm-glib/nm-device-infiniband.c +++ b/libnm-glib/nm-device-infiniband.c @@ -68,13 +68,17 @@ enum { GObject * nm_device_infiniband_new (DBusGConnection *connection, const char *path) { + GObject *device; + g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); - return g_object_new (NM_TYPE_DEVICE_INFINIBAND, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + device = g_object_new (NM_TYPE_DEVICE_INFINIBAND, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return device; } /** @@ -168,19 +172,12 @@ register_properties (NMDeviceInfiniband *device) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMDeviceInfinibandPrivate *priv; - object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructed (object); priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); @@ -190,8 +187,6 @@ constructor (GType type, NM_DBUS_INTERFACE_DEVICE_INFINIBAND); register_properties (NM_DEVICE_INFINIBAND (object)); - - return object; } static void @@ -247,7 +242,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *eth_class) g_type_class_add_private (eth_class, sizeof (NMDeviceInfinibandPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c index e6dc5a23a4..dd43d3d217 100644 --- a/libnm-glib/nm-device-modem.c +++ b/libnm-glib/nm-device-modem.c @@ -147,29 +147,21 @@ register_properties (NMDeviceModem *device) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMDeviceModemPrivate *priv; - object = G_OBJECT_CLASS (nm_device_modem_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (object) { - priv = NM_DEVICE_MODEM_GET_PRIVATE (object); + G_OBJECT_CLASS (nm_device_modem_parent_class)->constructed (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), - NM_DBUS_SERVICE, - nm_object_get_path (NM_OBJECT (object)), - NM_DBUS_INTERFACE_DEVICE_MODEM); + priv = NM_DEVICE_MODEM_GET_PRIVATE (object); - register_properties (NM_DEVICE_MODEM (object)); - } + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), + NM_DBUS_SERVICE, + nm_object_get_path (NM_OBJECT (object)), + NM_DBUS_INTERFACE_DEVICE_MODEM); - return object; + register_properties (NM_DEVICE_MODEM (object)); } static void @@ -224,7 +216,7 @@ nm_device_modem_class_init (NMDeviceModemClass *modem_class) g_type_class_add_private (modem_class, sizeof (NMDeviceModemPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; device_class->connection_valid = connection_valid; diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c index 4c9c6be91a..7fca0bc94a 100644 --- a/libnm-glib/nm-device-wifi.c +++ b/libnm-glib/nm-device-wifi.c @@ -97,13 +97,17 @@ static guint signals[LAST_SIGNAL] = { 0 }; GObject * nm_device_wifi_new (DBusGConnection *connection, const char *path) { + GObject *device; + g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); - return g_object_new (NM_TYPE_DEVICE_WIFI, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + device = g_object_new (NM_TYPE_DEVICE_WIFI, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return device; } /** @@ -538,19 +542,12 @@ register_properties (NMDeviceWifi *device) access_point_removed); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMDeviceWifiPrivate *priv; - object = G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object); priv = NM_DEVICE_WIFI_GET_PRIVATE (object); @@ -565,15 +562,6 @@ constructor (GType type, "notify::" NM_DEVICE_STATE, G_CALLBACK (state_changed_cb), NULL); - - /* Get initial access points to prevent possible errors on - * AccessPointRemoved signal processing. We could make D-Bus - * GetAccessPoints() call on a removed WiFi device object (when - * AccessPointRemoved was triggered by removing the device). - */ - nm_device_wifi_get_access_points (NM_DEVICE_WIFI (object)); - - return object; } static void @@ -614,7 +602,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class) g_type_class_add_private (wifi_class, sizeof (NMDeviceWifiPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c index 2eb8846aff..e5525a4f5f 100644 --- a/libnm-glib/nm-device-wimax.c +++ b/libnm-glib/nm-device-wimax.c @@ -97,13 +97,17 @@ static guint signals[LAST_SIGNAL] = { 0 }; GObject * nm_device_wimax_new (DBusGConnection *connection, const char *path) { + GObject *device; + g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); - return g_object_new (NM_TYPE_DEVICE_WIMAX, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + device = g_object_new (NM_TYPE_DEVICE_WIMAX, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return device; } /** @@ -525,19 +529,12 @@ register_properties (NMDeviceWimax *wimax) nsp_removed); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMDeviceWimaxPrivate *priv; - object = G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructed (object); priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); @@ -552,8 +549,6 @@ constructor (GType type, "notify::" NM_DEVICE_STATE, G_CALLBACK (state_changed_cb), NULL); - - return object; } static void @@ -586,7 +581,7 @@ nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class) g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; device_class->connection_valid = connection_valid; diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 616f110c10..2a1e58fb08 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -163,83 +163,21 @@ device_state_changed (DBusGProxy *proxy, } static void -get_all_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +constructed (GObject *object) { - NMObject *self = NM_OBJECT (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)) { - if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) { - g_warning ("%s: couldn't retrieve device properties: (%d) %s.", - __func__, - error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); - } - g_clear_error (&error); - g_object_unref (proxy); - return; - } - g_object_unref (proxy); - - _nm_object_process_properties_changed (NM_OBJECT (self), props); - g_hash_table_destroy (props); - -} - -static void -initialize_properties (NMObject *object) -{ - DBusGProxy *props_proxy; - - /* D-Bus properties proxy */ - props_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), - NM_DBUS_SERVICE, - nm_object_get_path (object), - "org.freedesktop.DBus.Properties"); - g_assert (props_proxy); - - /* Get properties */ - dbus_g_proxy_begin_call (props_proxy, "GetAll", - get_all_cb, - object, - NULL, - G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE, - G_TYPE_INVALID); - -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - NMObject *object; NMDevicePrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_device_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); priv = NM_DEVICE_GET_PRIVATE (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_DEVICE); register_properties (NM_DEVICE (object)); - /* Get initial properties, so that we have all properties set even if - * no PropertiesChanged signal is received. - * It has to be called after register_for_property_changed(). - */ - initialize_properties (object); - dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, @@ -254,8 +192,6 @@ constructor (GType type, G_CALLBACK (device_state_changed), NM_DEVICE (object), NULL); - - return G_OBJECT (object); } static void @@ -393,7 +329,7 @@ nm_device_class_init (NMDeviceClass *device_class) g_type_class_add_private (device_class, sizeof (NMDevicePrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->set_property = set_property; object_class->dispose = dispose; @@ -704,6 +640,7 @@ GObject * nm_device_new (DBusGConnection *connection, const char *path) { GType dtype; + NMDevice *device = NULL; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); @@ -712,10 +649,12 @@ nm_device_new (DBusGConnection *connection, const char *path) if (dtype == G_TYPE_INVALID) return NULL; - return g_object_new (dtype, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + device = (NMDevice *) g_object_new (dtype, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return G_OBJECT (device); } typedef struct { diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c index 06c292d760..2074e6d11e 100644 --- a/libnm-glib/nm-dhcp4-config.c +++ b/libnm-glib/nm-dhcp4-config.c @@ -90,34 +90,25 @@ register_properties (NMDHCP4Config *config) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; DBusGConnection *connection; NMDHCP4ConfigPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructed (object); priv = NM_DHCP4_CONFIG_GET_PRIVATE (object); priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - connection = nm_object_get_connection (object); + connection = nm_object_get_connection (NM_OBJECT (object)); priv->proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_DHCP4_CONFIG); register_properties (NM_DHCP4_CONFIG (object)); - - return G_OBJECT (object); } static void @@ -159,7 +150,7 @@ nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMDHCP4ConfigPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->finalize = finalize; diff --git a/libnm-glib/nm-dhcp6-config.c b/libnm-glib/nm-dhcp6-config.c index 84eb88fbd1..3764cbf089 100644 --- a/libnm-glib/nm-dhcp6-config.c +++ b/libnm-glib/nm-dhcp6-config.c @@ -90,34 +90,25 @@ register_properties (NMDHCP6Config *config) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; DBusGConnection *connection; NMDHCP6ConfigPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructed (object); priv = NM_DHCP6_CONFIG_GET_PRIVATE (object); priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - connection = nm_object_get_connection (object); + connection = nm_object_get_connection (NM_OBJECT (object)); priv->proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_DHCP6_CONFIG); register_properties (NM_DHCP6_CONFIG (object)); - - return G_OBJECT (object); } static void @@ -159,7 +150,7 @@ nm_dhcp6_config_class_init (NMDHCP6ConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMDHCP6ConfigPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->finalize = finalize; diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c index 3ea5db0506..56678545e8 100644 --- a/libnm-glib/nm-ip4-config.c +++ b/libnm-glib/nm-ip4-config.c @@ -132,32 +132,23 @@ register_properties (NMIP4Config *config) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; DBusGConnection *connection; NMIP4ConfigPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructed (object); priv = NM_IP4_CONFIG_GET_PRIVATE (object); - connection = nm_object_get_connection (object); + connection = nm_object_get_connection (NM_OBJECT (object)); priv->proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_IP4_CONFIG); register_properties (NM_IP4_CONFIG (object)); - - return G_OBJECT (object); } static void @@ -226,7 +217,7 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->finalize = finalize; diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c index 01842264a3..c9a2627949 100644 --- a/libnm-glib/nm-ip6-config.c +++ b/libnm-glib/nm-ip6-config.c @@ -216,20 +216,13 @@ nm_ip6_config_get_routes (NMIP6Config *config) return NM_IP6_CONFIG_GET_PRIVATE (config)->routes; } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; DBusGConnection *connection; NMIP6ConfigPrivate *priv; - object = G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructed (object); priv = NM_IP6_CONFIG_GET_PRIVATE (object); connection = nm_object_get_connection (NM_OBJECT (object)); @@ -240,8 +233,6 @@ constructor (GType type, NM_DBUS_INTERFACE_IP6_CONFIG); register_properties (NM_IP6_CONFIG (object)); - - return object; } static void @@ -309,7 +300,7 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->finalize = finalize; diff --git a/libnm-glib/nm-object-private.h b/libnm-glib/nm-object-private.h index 83cd82f1d5..9e7bbe5ee8 100644 --- a/libnm-glib/nm-object-private.h +++ b/libnm-glib/nm-object-private.h @@ -23,8 +23,7 @@ #ifndef NM_OBJECT_PRIVATE_H #define NM_OBJECT_PRIVATE_H -#include -#include +#include #include "nm-object.h" void _nm_object_ensure_inited (NMObject *object); @@ -47,7 +46,12 @@ void _nm_object_register_properties (NMObject *object, gboolean _nm_object_reload_properties (NMObject *object, GError **error); -void _nm_object_process_properties_changed (NMObject *self, GHashTable *properties); +void _nm_object_reload_properties_async (NMObject *object, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean _nm_object_reload_properties_finish (NMObject *object, + GAsyncResult *result, + GError **error); typedef void (*NMPseudoPropertyChangedFunc) (NMObject *self, NMObject *changed); void _nm_object_register_pseudo_property (NMObject *object, diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c index 58efe06734..4f87b3718f 100644 --- a/libnm-glib/nm-object.c +++ b/libnm-glib/nm-object.c @@ -34,7 +34,13 @@ #define DEBUG 0 -G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT) +static void nm_object_initable_iface_init (GInitableIface *iface); +static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init); + ) #define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate)) @@ -47,6 +53,8 @@ typedef struct { gpointer field; } PropertyInfo; +static void reload_complete (NMObject *object); + typedef struct { PropertyInfo pi; @@ -70,6 +78,10 @@ typedef struct { GSList *notify_props; guint32 notify_id; gboolean inited, disposed; + + GSList *reload_results; + guint reload_remaining; + GError *reload_error; } NMObjectPrivate; enum { @@ -96,8 +108,6 @@ constructor (GType type, object = G_OBJECT_CLASS (nm_object_parent_class)->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; priv = NM_OBJECT_GET_PRIVATE (object); @@ -107,16 +117,77 @@ constructor (GType type, return NULL; } - priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection, - NM_DBUS_SERVICE, - priv->path, - "org.freedesktop.DBus.Properties"); - _nm_object_cache_add (NM_OBJECT (object)); return object; } +static void +constructed (GObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + if (G_OBJECT_CLASS (nm_object_parent_class)->constructed) + G_OBJECT_CLASS (nm_object_parent_class)->constructed (object); + + priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection, + NM_DBUS_SERVICE, + priv->path, + "org.freedesktop.DBus.Properties"); +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (initable); + + priv->inited = TRUE; + return _nm_object_reload_properties (NM_OBJECT (initable), error); +} + +static void +init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + priv->inited = TRUE; + if (_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async); + _nm_object_reload_properties_async (NM_OBJECT (initable), init_async_got_properties, simple); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + /* This is needed for now because of bug 667375; it can go away + * when we depend on glib >= 2.38 + */ + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + static void dispose (GObject *object) { @@ -219,6 +290,7 @@ nm_object_class_init (NMObjectClass *nm_object_class) /* 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; @@ -253,6 +325,19 @@ nm_object_class_init (NMObjectClass *nm_object_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } +static void +nm_object_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} + +static void +nm_object_async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = init_async; + iface->init_finish = init_finish; +} + /** * nm_object_get_connection: * @object: a #NMObject @@ -352,15 +437,25 @@ static GObject * _nm_object_create (GType type, DBusGConnection *connection, const char *path) { NMObjectTypeFunc type_func; + GObject *object; + GError *error = NULL; type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); if (type_func) type = type_func (connection, path); - return g_object_new (type, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, path, - NULL); + object = g_object_new (type, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + if (!g_initable_init (G_INITABLE (object), NULL, &error)) { + g_object_unref (object); + object = NULL; + g_warning ("Could not create object for %s: %s", path, error->message); + g_error_free (error); + } + + return object; } typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer); @@ -371,6 +466,33 @@ typedef struct { gpointer user_data; } NMObjectTypeAsyncData; +static void +create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data) +{ + async_data->callback (object, async_data->user_data); + + g_free (async_data->path); + g_slice_free (NMObjectTypeAsyncData, async_data); +} + +static void +async_inited (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMObjectTypeAsyncData *async_data = user_data; + GObject *object = G_OBJECT (source); + GError *error = NULL; + + if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) { + g_warning ("Could not create object for %s: %s", + nm_object_get_path (NM_OBJECT (object)), error->message); + g_error_free (error); + g_object_unref (object); + object = NULL; + } + + create_async_complete (object, async_data); +} + static void async_got_type (GType type, gpointer user_data) { @@ -382,13 +504,13 @@ async_got_type (GType type, gpointer user_data) NM_OBJECT_DBUS_CONNECTION, async_data->connection, NM_OBJECT_DBUS_PATH, async_data->path, NULL); - } else - object = NULL; + } else { + create_async_complete (NULL, async_data); + return; + } - async_data->callback (object, async_data->user_data); - - g_free (async_data->path); - g_slice_free (NMObjectTypeAsyncData, async_data); + g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT, + NULL, async_inited, async_data); } static void @@ -396,6 +518,7 @@ _nm_object_create_async (GType type, DBusGConnection *connection, const char *pa NMObjectCreateCallbackFunc callback, gpointer user_data) { NMObjectTypeAsyncFunc type_async_func; + NMObjectTypeFunc type_func; NMObjectTypeAsyncData *async_data; async_data = g_slice_new (NMObjectTypeAsyncData); @@ -405,10 +528,16 @@ _nm_object_create_async (GType type, DBusGConnection *connection, const char *pa async_data->user_data = user_data; type_async_func = g_hash_table_lookup (type_async_funcs, GSIZE_TO_POINTER (type)); - if (type_async_func) + if (type_async_func) { type_async_func (connection, path, async_got_type, async_data); - else - async_got_type (type, async_data); + return; + } + + type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); + if (type_func) + type = type_func (connection, path); + + async_got_type (type, async_data); } /* Stolen from dbus-glib */ @@ -449,6 +578,7 @@ object_created (GObject *obj, gpointer user_data) { ObjectCreatedData *odata = user_data; NMObject *self = odata->self; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); PropertyInfo *pi = odata->pi; /* We assume that on error, the creator_func printed something */ @@ -478,6 +608,9 @@ object_created (GObject *obj, gpointer user_data) if (odata->property_name) _nm_object_queue_notify (self, odata->property_name); + if (priv->reload_results && --priv->reload_remaining == 0) + reload_complete (self); + g_object_unref (self); g_free (odata->objects); g_slice_free (ObjectCreatedData, odata); @@ -514,12 +647,14 @@ handle_object_property (NMObject *self, const char *property_name, GValue *value obj = _nm_object_create (pi->object_type, priv->connection, path); object_created (obj, odata); return obj != NULL; - } else { - _nm_object_create_async (pi->object_type, priv->connection, path, - object_created, odata); - /* Assume success */ - return TRUE; } + + if (priv->reload_results) + priv->reload_remaining++; + _nm_object_create_async (pi->object_type, priv->connection, path, + object_created, odata); + /* Assume success */ + return TRUE; } static gboolean @@ -532,6 +667,7 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue GPtrArray **array = pi->field; const char *path; ObjectCreatedData *odata; + gboolean add_to_reload = (priv->reload_results != NULL); int i; paths = g_value_get_boxed (value); @@ -554,13 +690,19 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue obj = G_OBJECT (_nm_object_cache_get (path)); if (obj) { object_created (obj, odata); + continue; } else if (synchronously) { obj = _nm_object_create (pi->object_type, priv->connection, path); object_created (obj, odata); - } else { - _nm_object_create_async (pi->object_type, priv->connection, path, - object_created, odata); + continue; } + + if (add_to_reload) { + priv->reload_remaining++; + add_to_reload = FALSE; + } + _nm_object_create_async (pi->object_type, priv->connection, path, + object_created, odata); } if (!synchronously) { @@ -636,8 +778,8 @@ out: g_free (prop_name); } -void -_nm_object_process_properties_changed (NMObject *self, GHashTable *properties) +static void +process_properties_changed (NMObject *self, GHashTable *properties) { GHashTableIter iter; gpointer name, value; @@ -652,7 +794,7 @@ properties_changed_proxy (DBusGProxy *proxy, GHashTable *properties, gpointer user_data) { - _nm_object_process_properties_changed (NM_OBJECT (user_data), properties); + process_properties_changed (NM_OBJECT (user_data), properties); } #define HANDLE_TYPE(ucase, lcase, getter) \ @@ -773,8 +915,6 @@ _nm_object_reload_properties (NMObject *object, GError **error) if (!priv->property_interfaces) return TRUE; - priv->inited = TRUE; - for (p = priv->property_interfaces; p; p = p->next) { if (!dbus_g_proxy_call (priv->properties_proxy, "GetAll", error, G_TYPE_STRING, p->data, @@ -783,7 +923,7 @@ _nm_object_reload_properties (NMObject *object, GError **error) G_TYPE_INVALID)) return FALSE; - _nm_object_process_properties_changed (object, props); + process_properties_changed (object, props); g_hash_table_destroy (props); } @@ -803,11 +943,14 @@ _nm_object_ensure_inited (NMObject *object) GError *error = NULL; if (!priv->inited) { - if (!_nm_object_reload_properties (object, &error)) { + if (!g_initable_init (G_INITABLE (object), NULL, &error)) { g_warning ("Could not initialize %s %s: %s", G_OBJECT_TYPE_NAME (object), priv->path, error->message); g_error_free (error); + + /* Only warn once */ + priv->inited = TRUE; } } } @@ -1026,3 +1169,148 @@ _nm_object_reload_pseudo_property (NMObject *object, handle_object_array_property (object, NULL, &value, &ppi->pi, TRUE); g_value_unset (&value); } + +static void +reload_complete (NMObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple; + GSList *results, *iter; + GError *error; + + results = priv->reload_results; + priv->reload_results = NULL; + error = priv->reload_error; + priv->reload_error = NULL; + + for (iter = results; iter; iter = iter->next) { + simple = results->data; + + if (error) + g_simple_async_result_set_from_error (simple, error); + else + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + + g_simple_async_result_complete (simple); + g_object_unref (simple); + } + g_slist_free (results); + g_clear_error (&error); +} + +static void +reload_got_properties (DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + NMObject *object = user_data; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + 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)) { + process_properties_changed (object, props); + g_hash_table_destroy (props); + } else { + if (priv->reload_error) + g_error_free (error); + else + priv->reload_error = error; + } + + if (--priv->reload_remaining == 0) + reload_complete (object); +} + +static void +reload_got_pseudo_property (DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + PseudoPropertyInfo *ppi = user_data; + NMObject *object = ppi->self; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GPtrArray *temp; + GValue value = { 0, }; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &temp, + G_TYPE_INVALID)) { + g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH); + g_value_take_boxed (&value, temp); + handle_object_array_property (object, NULL, &value, &ppi->pi, FALSE); + g_value_unset (&value); + } else { + if (priv->reload_error) + g_error_free (error); + else + priv->reload_error = error; + } + + if (--priv->reload_remaining == 0) + reload_complete (object); +} + +void +_nm_object_reload_properties_async (NMObject *object, GAsyncReadyCallback callback, gpointer user_data) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple; + GSList *p; + + simple = g_simple_async_result_new (G_OBJECT (object), callback, + user_data, _nm_object_reload_properties_async); + + if (!priv->property_interfaces && !priv->pseudo_properties) { + g_simple_async_result_complete_in_idle (simple); + return; + } + + priv->reload_results = g_slist_prepend (priv->reload_results, simple); + + /* If there was already a reload happening, we don't need to + * re-read the properties again, we just need to wait for the + * existing reload to finish. + */ + if (priv->reload_results->next) + return; + + for (p = priv->property_interfaces; p; p = p->next) { + priv->reload_remaining++; + dbus_g_proxy_begin_call (priv->properties_proxy, "GetAll", + reload_got_properties, object, NULL, + G_TYPE_STRING, p->data, + G_TYPE_INVALID); + } + + if (priv->pseudo_properties) { + GHashTableIter iter; + gpointer key, value; + PseudoPropertyInfo *ppi; + + g_hash_table_iter_init (&iter, priv->pseudo_properties); + while (g_hash_table_iter_next (&iter, &key, &value)) { + ppi = value; + priv->reload_remaining++; + dbus_g_proxy_begin_call (ppi->proxy, ppi->get_method, + reload_got_pseudo_property, ppi, NULL, + G_TYPE_INVALID); + } + } +} + +gboolean +_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_OBJECT (object), FALSE); + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object), _nm_object_reload_properties_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return g_simple_async_result_get_op_res_gboolean (simple); +} diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c index 91d3d469fb..d8bcfd97f4 100644 --- a/libnm-glib/nm-remote-connection.c +++ b/libnm-glib/nm-remote-connection.c @@ -382,18 +382,11 @@ nm_remote_connection_new (DBusGConnection *bus, NULL); } -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; NMRemoteConnectionPrivate *priv; - object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); g_assert (priv->bus); g_assert (nm_connection_get_path (NM_CONNECTION (object))); @@ -414,7 +407,6 @@ constructor (GType type, dbus_g_proxy_begin_call (priv->proxy, "GetSettings", init_get_settings_cb, object, NULL, G_TYPE_INVALID); - return object; } static void @@ -486,7 +478,7 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; - object_class->constructor = constructor; + object_class->constructed = constructed; /* Properties */ g_object_class_install_property diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c index 60c13c8afe..19e297c594 100644 --- a/libnm-glib/nm-remote-settings.c +++ b/libnm-glib/nm-remote-settings.c @@ -754,19 +754,12 @@ 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); /* D-Bus proxy for clearing connections on NameOwnerChanged */ @@ -847,7 +840,6 @@ constructor (GType type, G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS, G_TYPE_INVALID); - return object; } static void @@ -937,7 +929,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; diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c index 58c2ea4fbb..652206bb40 100644 --- a/libnm-glib/nm-vpn-connection.c +++ b/libnm-glib/nm-vpn-connection.c @@ -164,25 +164,18 @@ register_properties (NMVPNConnection *connection) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; NMVPNConnectionPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructed (object); priv = NM_VPN_CONNECTION_GET_PRIVATE (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_VPN_CONNECTION); dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT, @@ -197,8 +190,6 @@ constructor (GType type, NULL); register_properties (NM_VPN_CONNECTION (object)); - - return G_OBJECT (object); } static void @@ -241,7 +232,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->finalize = finalize; diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c index bfacc8710e..c3b222df1f 100644 --- a/libnm-glib/nm-wimax-nsp.c +++ b/libnm-glib/nm-wimax-nsp.c @@ -279,30 +279,21 @@ register_properties (NMWimaxNsp *nsp) property_info); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - NMObject *object; NMWimaxNspPrivate *priv; - object = (NMObject *) G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructed (object); priv = NM_WIMAX_NSP_GET_PRIVATE (object); - priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), NM_DBUS_SERVICE, - nm_object_get_path (object), + nm_object_get_path (NM_OBJECT (object)), NM_DBUS_INTERFACE_WIMAX_NSP); register_properties (NM_WIMAX_NSP (object)); - - return G_OBJECT (object); } @@ -314,7 +305,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate)); /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize;