summaryrefslogtreecommitdiff
path: root/libnm/nm-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm/nm-object.c')
-rw-r--r--libnm/nm-object.c865
1 files changed, 150 insertions, 715 deletions
diff --git a/libnm/nm-object.c b/libnm/nm-object.c
index aa1c177b2f..abade94b8d 100644
--- a/libnm/nm-object.c
+++ b/libnm/nm-object.c
@@ -29,7 +29,6 @@
#include "nm-utils.h"
#include "nm-dbus-interface.h"
-#include "nm-object-cache.h"
#include "nm-object-private.h"
#include "nm-dbus-helpers.h"
#include "nm-client.h"
@@ -38,25 +37,18 @@
static gboolean debug = FALSE;
#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); }
+G_DEFINE_QUARK (nm-obj-nm, _nm_object_obj_nm);
+
static void nm_object_initable_iface_init (GInitableIface *iface);
static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface);
typedef struct {
- NMObjectDecideTypeFunc type_func;
- char *interface;
- char *property;
-} NMObjectTypeFuncData;
-
-static GHashTable *type_funcs;
-
-typedef struct {
GSList *interfaces;
} NMObjectClassPrivate;
#define NM_OBJECT_CLASS_GET_PRIVATE(k) (G_TYPE_CLASS_GET_PRIVATE ((k), NM_TYPE_OBJECT, NMObjectClassPrivate))
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT,
- type_funcs = g_hash_table_new (NULL, NULL);
g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate));
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init);
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init);
@@ -75,15 +67,11 @@ static void reload_complete (NMObject *object, gboolean emit_now);
static gboolean demarshal_generic (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field);
typedef struct {
- GDBusConnection *connection;
- gboolean nm_running;
+ GDBusObject *object;
+ GDBusObjectManager *object_manager;
- char *path;
- GHashTable *proxies;
- GDBusProxy *properties_proxy;
GSList *property_tables;
NMObject *parent;
- gboolean suppress_property_updates;
gboolean inited; /* async init finished? */
GSList *waiters; /* if async init did not finish, users of this object need
@@ -104,50 +92,27 @@ enum {
PROP_PATH,
PROP_DBUS_CONNECTION,
PROP_NM_RUNNING,
+ PROP_DBUS_OBJECT,
+ PROP_DBUS_OBJECT_MANAGER,
LAST_PROP
};
/**
- * _nm_object_class_add_interface:
- * @object_class: an #NMObjectClass
- * @interface: a D-Bus interface name
- *
- * Registers that @object_class implements @interface. A proxy for that
- * interface will automatically be created at construction time, and can
- * be retrieved with _nm_object_get_proxy().
- */
-void
-_nm_object_class_add_interface (NMObjectClass *object_class,
- const char *interface)
-{
- NMObjectClassPrivate *cpriv;
-
- g_return_if_fail (NM_IS_OBJECT_CLASS (object_class));
- g_return_if_fail (interface);
-
- cpriv = NM_OBJECT_CLASS_GET_PRIVATE (object_class);
-
- g_return_if_fail (g_slist_find_custom (cpriv->interfaces, interface, (GCompareFunc) g_strcmp0) == NULL);
-
- cpriv->interfaces = g_slist_prepend (cpriv->interfaces, g_strdup (interface));
-}
-
-/**
* nm_object_get_path:
* @object: a #NMObject
*
* Gets the DBus path of the #NMObject.
*
* Returns: the object's path. This is the internal string used by the
- * device, and must not be modified.
+ * object, and must not be modified.
**/
const char *
nm_object_get_path (NMObject *object)
{
g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
- return NM_OBJECT_GET_PRIVATE (object)->path;
+ return g_dbus_object_get_object_path (NM_OBJECT_GET_PRIVATE (object)->object);
}
/**
@@ -163,13 +128,14 @@ GDBusProxy *
_nm_object_get_proxy (NMObject *object,
const char *interface)
{
- GDBusProxy *proxy;
+ GDBusInterface *proxy;
g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
- proxy = g_hash_table_lookup (NM_OBJECT_GET_PRIVATE (object)->proxies, interface);
+ proxy = g_dbus_object_get_interface (NM_OBJECT_GET_PRIVATE (object)->object, interface);
g_return_val_if_fail (proxy != NULL, NULL);
- return proxy;
+
+ return G_DBUS_PROXY (proxy);
}
typedef enum {
@@ -351,97 +317,6 @@ _nm_object_queue_notify (NMObject *object, const char *property)
_nm_object_queue_notify_full (object, property, NULL, FALSE, NULL);
}
-void
-_nm_object_register_type_func (GType base_type,
- NMObjectDecideTypeFunc type_func,
- const char *interface,
- const char *property)
-{
- NMObjectTypeFuncData *type_data;
-
- g_return_if_fail (type_func != NULL);
- g_return_if_fail (interface != NULL);
- g_return_if_fail (property != NULL);
-
- type_data = g_slice_new (NMObjectTypeFuncData);
- type_data->type_func = type_func;
- type_data->interface = g_strdup (interface);
- type_data->property = g_strdup (property);
-
- g_hash_table_insert (type_funcs,
- GSIZE_TO_POINTER (base_type),
- type_data);
-}
-
-static GObject *
-_nm_object_create (GType type, GDBusConnection *connection, const char *path)
-{
- NMObjectTypeFuncData *type_data;
- GObject *object;
- GError *error = NULL;
-
- type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
- if (type_data) {
- GDBusProxy *proxy;
- GVariant *ret, *value;
-
- proxy = _nm_dbus_new_proxy_for_connection (connection, path,
- DBUS_INTERFACE_PROPERTIES,
- NULL, &error);
- if (!proxy) {
- g_warning ("Could not create proxy for %s: %s.", path, error->message);
- g_error_free (error);
- return NULL;
- }
-
- ret = g_dbus_proxy_call_sync (proxy,
- "Get",
- g_variant_new ("(ss)",
- type_data->interface,
- type_data->property),
- G_DBUS_CALL_FLAGS_NONE, -1,
- NULL, &error);
- g_object_unref (proxy);
- if (!ret) {
- dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
- type_data->property, type_data->interface, path, error->message);
- g_error_free (error);
- return NULL;
- }
-
- g_variant_get (ret, "(v)", &value);
- type = type_data->type_func (value);
- g_variant_unref (value);
- g_variant_unref (ret);
- }
-
- if (type == G_TYPE_INVALID) {
- dbgmsg ("Could not create object for %s: unknown object type", path);
- return NULL;
- }
-
- object = g_object_new (type,
- NM_OBJECT_PATH, path,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NULL);
- /* Cache the object before initializing it (and in particular, loading its
- * property values); this is necessary to make circular references work (eg,
- * when creating an NMActiveConnection, it will create an NMDevice which
- * will in turn try to create the parent NMActiveConnection). Since we don't
- * support multi-threaded use, we know that we will have inited the object
- * before any external code sees it.
- */
- _nm_object_cache_add (NM_OBJECT (object));
- NM_OBJECT_GET_PRIVATE (object)->inited = TRUE;
- if (!g_initable_init (G_INITABLE (object), NULL, &error)) {
- dbgmsg ("Could not create object for %s: %s", path, error->message);
- g_error_free (error);
- g_clear_object (&object);
- }
-
- return object;
-}
-
typedef struct {
NMObject *self;
PropertyInfo *pi;
@@ -465,176 +340,6 @@ odata_free (gpointer data)
static void object_property_maybe_complete (NMObject *self);
-
-typedef void (*NMObjectCreateCallbackFunc) (GObject *, const char *, gpointer);
-typedef struct {
- char *path;
- NMObjectCreateCallbackFunc callback;
- gpointer user_data;
- NMObjectTypeFuncData *type_data;
- GDBusConnection *connection;
-} NMObjectTypeAsyncData;
-
-static void
-create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
-{
- async_data->callback (object, async_data->path, async_data->user_data);
-
- g_free (async_data->path);
- g_object_unref (async_data->connection);
- g_slice_free (NMObjectTypeAsyncData, async_data);
-}
-
-static void
-create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- NMObjectPrivate *odata_priv;
- NMObjectTypeAsyncData *async_data = user_data;
- GError *error = NULL;
- ObjectCreatedData *odata;
-
- priv->inited = TRUE;
- if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
- dbgmsg ("Could not create object for %s: %s",
- nm_object_get_path (NM_OBJECT (object)),
- error->message);
-
- while (priv->waiters) {
- odata = priv->waiters->data;
- odata_priv = NM_OBJECT_GET_PRIVATE (odata->self);
-
- priv->waiters = g_slist_remove (priv->waiters, odata);
- if (!odata_priv->reload_error)
- odata_priv->reload_error = g_error_copy (error);
- odata_priv->reload_remaining--;
- reload_complete (odata->self, FALSE);
- }
-
- g_error_free (error);
- g_clear_object (&object);
- }
-
- create_async_complete (object, async_data);
-
- if (object) {
- /* There are some object properties whose creation couldn't proceed
- * because it depended on this object. */
- while (priv->waiters) {
- odata = priv->waiters->data;
- priv->waiters = g_slist_remove (priv->waiters, odata);
- object_property_maybe_complete (odata->self);
- }
- }
-}
-
-static void
-create_async_got_type (NMObjectTypeAsyncData *async_data, GType type)
-{
- GObject *object;
-
- /* Ensure we don't have the object already; we may get multiple type
- * requests for the same object if there are multiple properties on
- * other objects that refer to the object at this path. One of those
- * other requests may have already completed.
- */
- object = (GObject *) _nm_object_cache_get (async_data->path);
- if (object) {
- create_async_complete (object, async_data);
- return;
- }
-
- if (type == G_TYPE_INVALID) {
- /* Don't know how to create this object */
- create_async_complete (NULL, async_data);
- return;
- }
-
- object = g_object_new (type,
- NM_OBJECT_PATH, async_data->path,
- NM_OBJECT_DBUS_CONNECTION, async_data->connection,
- NULL);
- _nm_object_cache_add (NM_OBJECT (object));
- g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT,
- NULL, create_async_inited, async_data);
-}
-
-static void
-create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_data)
-{
- NMObjectTypeAsyncData *async_data = user_data;
- NMObjectTypeFuncData *type_data = async_data->type_data;
- GVariant *ret, *value;
- GError *error = NULL;
- GType type;
-
- ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
- G_VARIANT_TYPE ("(v)"), &error);
- if (ret) {
- g_variant_get (ret, "(v)", &value);
- type = type_data->type_func (value);
- g_variant_unref (value);
- g_variant_unref (ret);
- } else {
- dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
- type_data->property, type_data->interface, async_data->path,
- error->message);
- g_clear_error (&error);
- type = G_TYPE_INVALID;
- }
-
- create_async_got_type (async_data, type);
-}
-
-static void
-create_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- NMObjectTypeAsyncData *async_data = user_data;
- GDBusProxy *proxy;
- GError *error = NULL;
-
- proxy = _nm_dbus_new_proxy_for_connection_finish (result, &error);
- if (!proxy) {
- g_warning ("Could not create proxy for %s: %s.", async_data->path, error->message);
- g_error_free (error);
- create_async_complete (NULL, async_data);
- return;
- }
-
- g_dbus_proxy_call (proxy,
- "Get",
- g_variant_new ("(ss)",
- async_data->type_data->interface,
- async_data->type_data->property),
- G_DBUS_CALL_FLAGS_NONE, -1,
- NULL,
- create_async_got_property, async_data);
-}
-
-static void
-_nm_object_create_async (GType type, GDBusConnection *connection, const char *path,
- NMObjectCreateCallbackFunc callback, gpointer user_data)
-{
- NMObjectTypeAsyncData *async_data;
-
- async_data = g_slice_new (NMObjectTypeAsyncData);
- async_data->path = g_strdup (path);
- async_data->callback = callback;
- async_data->user_data = user_data;
- async_data->connection = g_object_ref (connection);
-
- async_data->type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
- if (async_data->type_data) {
- _nm_dbus_new_proxy_for_connection_async (connection, path,
- DBUS_INTERFACE_PROPERTIES,
- NULL,
- create_async_got_proxy, async_data);
- return;
- }
-
- create_async_got_type (async_data, type);
-}
-
/* Stolen from dbus-glib */
static char*
wincaps_to_dash (const char *caps)
@@ -855,15 +560,16 @@ object_created (GObject *obj, const char *path, gpointer user_data)
object_class->object_creation_failed (odata->self, path);
}
- odata->objects[--odata->remaining] = obj;
+ odata->objects[--odata->remaining] = obj ? g_object_ref (obj) : NULL;
object_property_maybe_complete (odata->self);
}
static gboolean
handle_object_property (NMObject *self, const char *property_name, GVariant *value,
- PropertyInfo *pi, gboolean synchronously)
+ PropertyInfo *pi)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+ gs_unref_object GDBusObject *object = NULL;
GObject *obj;
const char *path;
ObjectCreatedData *odata;
@@ -886,31 +592,28 @@ handle_object_property (NMObject *self, const char *property_name, GVariant *val
return TRUE;
}
- obj = G_OBJECT (_nm_object_cache_get (path));
- if (obj) {
- object_created (obj, path, odata);
- return TRUE;
- } else if (synchronously) {
- obj = _nm_object_create (pi->object_type, priv->connection, path);
- object_created (obj, path, odata);
- return obj != NULL;
- } else {
- _nm_object_create_async (pi->object_type, priv->connection, path,
- object_created, odata);
- /* Assume success */
- return TRUE;
+ object = g_dbus_object_manager_get_object (priv->object_manager, path);
+ if (!object) {
+ /* This is a server bug -- a dangling object path for an object
+ * that does not exist. */
+ g_warning ("No object known for %s", path);
+ return FALSE;
}
+
+ obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ());
+ object_created (obj, path, odata);
+
+ return TRUE;
}
static gboolean
handle_object_array_property (NMObject *self, const char *property_name, GVariant *value,
- PropertyInfo *pi, gboolean synchronously)
+ PropertyInfo *pi)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
GObject *obj;
GVariantIter iter;
gsize npaths;
- GPtrArray **array = pi->field;
const char *path;
ObjectCreatedData *odata;
@@ -934,34 +637,28 @@ handle_object_array_property (NMObject *self, const char *property_name, GVarian
g_variant_iter_init (&iter, value);
while (g_variant_iter_next (&iter, "&o", &path)) {
+ gs_unref_object GDBusObject *object = NULL;
+
if (!strcmp (path, "/")) {
/* FIXME: can't happen? */
continue;
}
- obj = G_OBJECT (_nm_object_cache_get (path));
- if (obj) {
- object_created (obj, path, odata);
- } else if (synchronously) {
- obj = _nm_object_create (pi->object_type, priv->connection, path);
- object_created (obj, path, odata);
- } else {
- _nm_object_create_async (pi->object_type, priv->connection, path,
- object_created, odata);
+ object = g_dbus_object_manager_get_object (priv->object_manager, path);
+ if (!object) {
+ g_warning ("no object known for %s\n", path);
+ return FALSE;
}
- }
- if (!synchronously) {
- /* Assume success */
- return TRUE;
+ obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ());
+ object_created (obj, path, odata);
}
- return *array && ((*array)->len == npaths);
+ return TRUE;
}
static void
-handle_property_changed (NMObject *self, const char *dbus_name,
- GVariant *value, gboolean synchronously)
+handle_property_changed (NMObject *self, const char *dbus_name, GVariant *value)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
char *prop_name;
@@ -1015,9 +712,9 @@ handle_property_changed (NMObject *self, const char *dbus_name,
if (pspec && pi->object_type) {
if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
- success = handle_object_property (self, pspec->name, value, pi, synchronously);
+ success = handle_object_property (self, pspec->name, value, pi);
else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao")))
- success = handle_object_array_property (self, pspec->name, value, pi, synchronously);
+ success = handle_object_array_property (self, pspec->name, value, pi);
else {
g_warn_if_reached ();
goto out;
@@ -1037,31 +734,23 @@ out:
}
static void
-process_properties_changed (NMObject *self, GVariant *properties, gboolean synchronously)
+properties_changed (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ gpointer user_data)
{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+ NMObject *self = NM_OBJECT (user_data);
GVariantIter iter;
const char *name;
GVariant *value;
- if (priv->suppress_property_updates)
- return;
-
- g_variant_iter_init (&iter, properties);
+ g_variant_iter_init (&iter, changed_properties);
while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) {
- handle_property_changed (self, name, value, synchronously);
+ handle_property_changed (self, name, value);
g_variant_unref (value);
}
}
-static void
-properties_changed (GDBusProxy *proxy,
- GVariant *properties,
- gpointer user_data)
-{
- process_properties_changed (NM_OBJECT (user_data), properties, FALSE);
-}
-
#define HANDLE_TYPE(vtype, ctype, getter) \
G_STMT_START { \
if (g_variant_is_of_type (value, vtype)) { \
@@ -1240,10 +929,8 @@ _nm_object_register_properties (NMObject *object,
}
proxy = _nm_object_get_proxy (object, interface);
- g_return_if_fail (proxy != NULL);
-
- _nm_dbus_signal_connect (proxy, "PropertiesChanged", G_VARIANT_TYPE ("(a{sv})"),
- G_CALLBACK (properties_changed), object);
+ g_signal_connect (proxy, "g-properties-changed",
+ G_CALLBACK (properties_changed), object);
instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->property_tables = g_slist_prepend (priv->property_tables, instance);
@@ -1265,92 +952,6 @@ _nm_object_register_properties (NMObject *object,
}
}
-static gboolean
-_nm_object_reload_properties (NMObject *object, GError **error)
-{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- GVariant *ret, *props;
- GHashTableIter iter;
- const char *interface;
- GDBusProxy *proxy;
-
- if (!g_hash_table_size (priv->proxies) || !priv->nm_running)
- return TRUE;
-
- priv->reload_remaining++;
-
- g_hash_table_iter_init (&iter, priv->proxies);
- while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) {
- ret = _nm_dbus_proxy_call_sync (priv->properties_proxy,
- "GetAll",
- g_variant_new ("(s)", interface),
- G_VARIANT_TYPE ("(a{sv})"),
- G_DBUS_CALL_FLAGS_NONE, -1,
- NULL, error);
- if (!ret) {
- if (error && *error)
- g_dbus_error_strip_remote_error (*error);
- return FALSE;
- }
-
- g_variant_get (ret, "(@a{sv})", &props);
- process_properties_changed (object, props, TRUE);
- g_variant_unref (props);
- g_variant_unref (ret);
- }
-
- if (--priv->reload_remaining == 0)
- reload_complete (object, TRUE);
-
- return TRUE;
-}
-
-void
-_nm_object_suppress_property_updates (NMObject *object, gboolean suppress)
-{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
-
- priv->suppress_property_updates = suppress;
-}
-
-
-void
-_nm_object_reload_property (NMObject *object,
- const char *interface,
- const char *prop_name)
-{
- GVariant *ret, *value;
- GError *err = NULL;
-
- g_return_if_fail (NM_IS_OBJECT (object));
- g_return_if_fail (interface != NULL);
- g_return_if_fail (prop_name != NULL);
-
- if (!NM_OBJECT_GET_PRIVATE (object)->nm_running)
- return;
-
- ret = _nm_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
- "Get",
- g_variant_new ("(ss)", interface, prop_name),
- G_VARIANT_TYPE ("(v)"),
- G_DBUS_CALL_FLAGS_NONE, 15000,
- NULL, &err);
- if (!ret) {
- dbgmsg ("%s: Error getting '%s' for %s: %s\n",
- __func__,
- prop_name,
- nm_object_get_path (object),
- err->message);
- g_clear_error (&err);
- return;
- }
-
- g_variant_get (ret, "(v)", &value);
- handle_property_changed (object, prop_name, value, TRUE);
- g_variant_unref (value);
- g_variant_unref (ret);
-}
-
void
_nm_object_set_property (NMObject *object,
const char *interface,
@@ -1366,16 +967,13 @@ _nm_object_set_property (NMObject *object,
g_return_if_fail (prop_name != NULL);
g_return_if_fail (format_string != NULL);
- if (!NM_OBJECT_GET_PRIVATE (object)->nm_running)
- return;
-
va_start (ap, format_string);
val = g_variant_new_va (format_string, NULL, &ap);
va_end (ap);
g_return_if_fail (val != NULL);
- ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
- "Set",
+ ret = g_dbus_proxy_call_sync (_nm_object_get_proxy (object, interface),
+ DBUS_INTERFACE_PROPERTIES ".Set",
g_variant_new ("(ssv)", interface, prop_name, val),
G_DBUS_CALL_FLAGS_NONE, 2000,
NULL, NULL);
@@ -1418,139 +1016,40 @@ reload_complete (NMObject *object, gboolean emit_now)
g_clear_error (&error);
}
-static void
-reload_got_properties (GObject *proxy,
- GAsyncResult *result,
- gpointer user_data)
-{
- NMObject *object = user_data;
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- GVariant *ret, *props;
- GError *error = NULL;
-
- ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
- G_VARIANT_TYPE ("(a{sv})"),
- &error);
- if (ret) {
- g_variant_get (ret, "(@a{sv})", &props);
- process_properties_changed (object, props, FALSE);
- g_variant_unref (props);
- g_variant_unref (ret);
- } else {
- g_dbus_error_strip_remote_error (error);
- if (priv->reload_error)
- g_error_free (error);
- else
- priv->reload_error = error;
- }
-
- if (--priv->reload_remaining == 0)
- reload_complete (object, FALSE);
-}
-
-void
-_nm_object_reload_properties_async (NMObject *object,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- GSimpleAsyncResult *simple;
- GHashTableIter iter;
- const char *interface;
- GDBusProxy *proxy;
-
- simple = g_simple_async_result_new (G_OBJECT (object), callback,
- user_data, _nm_object_reload_properties_async);
-
- if (!g_hash_table_size (priv->proxies) || !priv->nm_running) {
- g_simple_async_result_complete_in_idle (simple);
- g_object_unref (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;
-
- g_hash_table_iter_init (&iter, priv->proxies);
- while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) {
- priv->reload_remaining++;
- g_dbus_proxy_call (priv->properties_proxy,
- "GetAll",
- g_variant_new ("(s)", interface),
- G_DBUS_CALL_FLAGS_NONE, -1,
- cancellable,
- reload_got_properties, object);
- }
-}
-
-gboolean
-_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error)
-{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- 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);
-
- /* NM might have disappeared meanwhile. That would cause a NoReply error to be emitted,
- * but we don't care if property updates were disabled. */
- if (priv->suppress_property_updates)
- return TRUE;
-
- 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);
-}
-
-gboolean
-_nm_object_get_nm_running (NMObject *self)
+GDBusObjectManager *
+_nm_object_get_dbus_object_manager (NMObject *self)
{
- return NM_OBJECT_GET_PRIVATE (self)->nm_running;
+ return NM_OBJECT_GET_PRIVATE (self)->object_manager;
}
/*****************************************************************************/
static void
-on_name_owner_changed (GObject *proxy,
- GParamSpec *pspec,
- gpointer user_data)
+init_dbus (NMObject *object)
{
- NMObject *self = NM_OBJECT (user_data);
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
- gboolean now_running;
- char *owner;
-
- now_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL);
- g_free (owner);
- if (now_running != priv->nm_running) {
- priv->nm_running = now_running;
- g_object_notify (G_OBJECT (self), NM_OBJECT_NM_RUNNING);
- }
}
static void
-init_dbus (NMObject *object)
+init_if (GDBusInterface *interface, gpointer user_data)
{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- char *owner;
-
- if (_nm_dbus_is_connection_private (priv->connection))
- priv->nm_running = TRUE;
- else {
- priv->nm_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL);
- g_free (owner);
- g_signal_connect (priv->properties_proxy, "notify::g-name-owner",
- G_CALLBACK (on_name_owner_changed), object);
+ NMObject *self = NM_OBJECT (user_data);
+ GDBusProxy *proxy = G_DBUS_PROXY (interface);
+ gchar **props;
+ char **prop;
+ GVariant *val;
+ gchar *str;
+
+ props = g_dbus_proxy_get_cached_property_names (proxy);
+
+ for (prop = props; *prop; prop++) {
+ val = g_dbus_proxy_get_cached_property (proxy, *prop);
+ str = g_variant_print (val, TRUE);
+ handle_property_changed (self, *prop, val);
+ g_variant_unref (val);
+ g_free (str);
}
+
+ g_strfreev (props);
}
static gboolean
@@ -1558,42 +1057,33 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
{
NMObject *self = NM_OBJECT (initable);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
- NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (self));
- GSList *iter;
+ GList *interfaces;
- if (!priv->path) {
- g_set_error_literal (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
- _("Caller did not specify D-Bus path for object"));
- return FALSE;
- }
+ g_assert (priv->object && priv->object_manager);
- if (!priv->connection)
- priv->connection = _nm_dbus_new_connection (cancellable, error);
- if (!priv->connection)
- return FALSE;
+ NM_OBJECT_GET_CLASS (self)->init_dbus (self);
- /* Create proxies */
- for (iter = cpriv->interfaces; iter; iter = iter->next) {
- const char *interface = iter->data;
- GDBusProxy *proxy;
+ priv->reload_remaining++;
- proxy = _nm_dbus_new_proxy_for_connection (priv->connection, priv->path, interface,
- cancellable, error);
- if (!proxy)
- return FALSE;
- g_hash_table_insert (priv->proxies, (char *) interface, proxy);
- }
+ interfaces = g_dbus_object_get_interfaces (priv->object);
+ g_list_foreach (interfaces, (GFunc) init_if, self);
+ g_list_free_full (interfaces, g_object_unref);
- priv->properties_proxy = _nm_dbus_new_proxy_for_connection (priv->connection,
- priv->path,
- DBUS_INTERFACE_PROPERTIES,
- cancellable, error);
- if (!priv->properties_proxy)
- return FALSE;
+ priv->inited = TRUE;
- NM_OBJECT_GET_CLASS (self)->init_dbus (self);
+ if (--priv->reload_remaining == 0)
+ reload_complete (self, TRUE);
+
+ /* There are some object properties whose creation couldn't proceed
+ * because it depended on this object. */
+ while (priv->waiters) {
+ ObjectCreatedData *odata = priv->waiters->data;
- return _nm_object_reload_properties (self, error);
+ priv->waiters = g_slist_remove (priv->waiters, odata);
+ object_property_maybe_complete (odata->self);
+ }
+
+ return TRUE;
}
/*****************************************************************************/
@@ -1613,88 +1103,13 @@ init_async_complete (NMObjectInitData *init_data)
g_simple_async_result_take_error (init_data->simple, init_data->error);
else
g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE);
- g_simple_async_result_complete (init_data->simple);
+ g_simple_async_result_complete_in_idle (init_data->simple);
g_object_unref (init_data->simple);
g_clear_object (&init_data->cancellable);
g_slice_free (NMObjectInitData, init_data);
}
static void
-init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- NMObjectInitData *init_data = user_data;
-
- _nm_object_reload_properties_finish (NM_OBJECT (object), result, &init_data->error);
- init_async_complete (init_data);
-}
-
-static void
-init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- NMObjectInitData *init_data = user_data;
- NMObject *self = init_data->object;
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
- GDBusProxy *proxy;
-
- if (!init_data->error) {
- proxy = _nm_dbus_new_proxy_for_connection_finish (result, &init_data->error);
- if (proxy) {
- const char *interface = g_dbus_proxy_get_interface_name (proxy);
-
- if (!strcmp (interface, DBUS_INTERFACE_PROPERTIES))
- priv->properties_proxy = proxy;
- else
- g_hash_table_insert (priv->proxies, (char *) interface, proxy);
- }
- }
-
- init_data->proxies_pending--;
- if (init_data->proxies_pending)
- return;
-
- if (init_data->error) {
- init_async_complete (init_data);
- return;
- }
-
- NM_OBJECT_GET_CLASS (self)->init_dbus (self);
-
- _nm_object_reload_properties_async (init_data->object, init_data->cancellable, init_async_got_properties, init_data);
-}
-
-static void
-init_async_got_bus (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- NMObjectInitData *init_data = user_data;
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (init_data->object);
- NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (init_data->object));
- GSList *iter;
-
- priv->connection = _nm_dbus_new_connection_finish (result, &init_data->error);
- if (!priv->connection) {
- init_async_complete (init_data);
- return;
- }
-
- for (iter = cpriv->interfaces; iter; iter = iter->next) {
- const char *interface = iter->data;
-
- _nm_dbus_new_proxy_for_connection_async (priv->connection,
- priv->path, interface,
- init_data->cancellable,
- init_async_got_proxy, init_data);
- init_data->proxies_pending++;
- }
-
- _nm_dbus_new_proxy_for_connection_async (priv->connection,
- priv->path,
- DBUS_INTERFACE_PROPERTIES,
- init_data->cancellable,
- init_async_got_proxy, init_data);
- init_data->proxies_pending++;
-}
-
-static void
init_async (GAsyncInitable *initable, int io_priority,
GCancellable *cancellable, GAsyncReadyCallback callback,
gpointer user_data)
@@ -1702,29 +1117,40 @@ init_async (GAsyncInitable *initable, int io_priority,
NMObject *self = NM_OBJECT (initable);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
NMObjectInitData *init_data;
+ GList *interfaces;
- if (!priv->path) {
- g_simple_async_report_error_in_idle (G_OBJECT (initable),
- callback, user_data,
- NM_CLIENT_ERROR,
- NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
- "%s",
- _("Caller did not specify D-Bus path for object"));
- return;
- }
+ g_assert (priv->object && priv->object_manager);
+
+ NM_OBJECT_GET_CLASS (self)->init_dbus (self);
init_data = g_slice_new0 (NMObjectInitData);
init_data->object = self;
init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async);
init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
- _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data);
+ interfaces = g_dbus_object_get_interfaces (priv->object);
+ g_list_foreach (interfaces, (GFunc) init_if, self);
+ g_list_free_full (interfaces, g_object_unref);
+
+ init_async_complete (init_data);
}
static gboolean
init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (initable);
+
+ priv->inited = TRUE;
+
+ /* There are some object properties whose creation couldn't proceed
+ * because it depended on this object. */
+ while (priv->waiters) {
+ ObjectCreatedData *odata = priv->waiters->data;
+
+ priv->waiters = g_slist_remove (priv->waiters, odata);
+ object_property_maybe_complete (odata->self);
+ }
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
@@ -1750,9 +1176,6 @@ nm_object_async_initable_iface_init (GAsyncInitableIface *iface)
static void
nm_object_init (NMObject *object)
{
- NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
-
- priv->proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
}
static void
@@ -1762,13 +1185,13 @@ set_property (GObject *object, guint prop_id,
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_PATH:
+ case PROP_DBUS_OBJECT:
/* Construct only */
- priv->path = g_value_dup_string (value);
+ priv->object = g_value_dup_object (value);
break;
- case PROP_DBUS_CONNECTION:
+ case PROP_DBUS_OBJECT_MANAGER:
/* Construct only */
- priv->connection = g_value_dup_object (value);
+ priv->object_manager = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1784,13 +1207,16 @@ get_property (GObject *object, guint prop_id,
switch (prop_id) {
case PROP_PATH:
- g_value_set_string (value, priv->path);
+ g_value_set_string (value, nm_object_get_path (NM_OBJECT (object)));
break;
case PROP_DBUS_CONNECTION:
- g_value_set_object (value, priv->connection);
+ g_value_set_object (value, g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager)));
break;
- case PROP_NM_RUNNING:
- g_value_set_boolean (value, priv->nm_running);
+ case PROP_DBUS_OBJECT:
+ g_value_set_object (value, priv->object);
+ break;
+ case PROP_DBUS_OBJECT_MANAGER:
+ g_value_set_object (value, priv->object_manager);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1809,10 +1235,9 @@ dispose (GObject *object)
priv->notify_items = NULL;
g_slist_free_full (priv->waiters, odata_free);
- g_clear_pointer (&priv->proxies, g_hash_table_unref);
- g_clear_object (&priv->properties_proxy);
- g_clear_object (&priv->connection);
+ g_clear_object (&priv->object);
+ g_clear_object (&priv->object_manager);
G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
}
@@ -1823,7 +1248,6 @@ finalize (GObject *object)
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
g_slist_free_full (priv->property_tables, (GDestroyNotify) g_hash_table_destroy);
- g_free (priv->path);
G_OBJECT_CLASS (nm_object_parent_class)->finalize (object);
}
@@ -1846,7 +1270,7 @@ nm_object_class_init (NMObjectClass *nm_object_class)
/* Properties */
/**
- * NMObject:path:
+ * NMObject:path: (skip)
*
* The D-Bus object path.
**/
@@ -1854,8 +1278,7 @@ nm_object_class_init (NMObjectClass *nm_object_class)
(object_class, PROP_PATH,
g_param_spec_string (NM_OBJECT_PATH, "", "",
NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
@@ -1867,20 +1290,32 @@ nm_object_class_init (NMObjectClass *nm_object_class)
(object_class, PROP_DBUS_CONNECTION,
g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "",
G_TYPE_DBUS_CONNECTION,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMObject:dbus-object: (skip)
+ *
+ * The #GDBusObject of the object.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DBUS_OBJECT,
+ g_param_spec_object (NM_OBJECT_DBUS_OBJECT, "", "",
+ G_TYPE_DBUS_OBJECT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
- * NMObject:manager-running: (skip)
+ * NMObject:dbus-object-manager: (skip)
*
- * Internal use only.
- */
+ * The #GDBusObjectManager of the object.
+ **/
g_object_class_install_property
- (object_class, PROP_NM_RUNNING,
- g_param_spec_boolean (NM_OBJECT_NM_RUNNING, "", "",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
+ (object_class, PROP_DBUS_OBJECT_MANAGER,
+ g_param_spec_object (NM_OBJECT_DBUS_OBJECT_MANAGER, "", "",
+ G_TYPE_DBUS_OBJECT_MANAGER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
}
-