X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdbus%2Fobject.c;h=c333d5b702438de733ea81fb76f05569afebaaca;hb=5479dad2b3b5f342f51ca6e7ec8a5a501820bd55;hp=3101ca6b8ece54ba87fa43f7a6c2a9a250930fb1;hpb=e7692d936a532768ae816700df19b6793df6e46a;p=platform%2Fupstream%2Fconnman.git diff --git a/gdbus/object.c b/gdbus/object.c old mode 100644 new mode 100755 index 3101ca6..c333d5b --- a/gdbus/object.c +++ b/gdbus/object.c @@ -84,6 +84,10 @@ struct property_data { DBusMessage *message; }; +static int global_flags = 0; +static struct generic_data *root; +static GSList *pending = NULL; + static gboolean process_changes(gpointer user_data); static void process_properties_from_interface(struct generic_data *data, struct interface_data *iface); @@ -94,7 +98,7 @@ static void print_arguments(GString *gstr, const GDBusArgInfo *args, { for (; args && args->name; args++) { g_string_append_printf(gstr, - "\t\t\tname, args->signature); if (direction) @@ -106,15 +110,23 @@ static void print_arguments(GString *gstr, const GDBusArgInfo *args, } } -#define G_DBUS_ANNOTATE(prefix_, name_, value_) \ - prefix_ "\n" +#define G_DBUS_ANNOTATE(name_, value_) \ + "" + +#define G_DBUS_ANNOTATE_DEPRECATED \ + G_DBUS_ANNOTATE("Deprecated", "true") -#define G_DBUS_ANNOTATE_DEPRECATED(prefix_) \ - G_DBUS_ANNOTATE(prefix_, "Deprecated", "true") +#define G_DBUS_ANNOTATE_NOREPLY \ + G_DBUS_ANNOTATE("Method.NoReply", "true") + +static gboolean check_experimental(int flags, int flag) +{ + if (!(flags & flag)) + return FALSE; -#define G_DBUS_ANNOTATE_NOREPLY(prefix_) \ - G_DBUS_ANNOTATE(prefix_, "Method.NoReply", "true") + return !(global_flags & G_DBUS_FLAG_ENABLE_EXPERIMENTAL); +} static void generate_interface_xml(GString *gstr, struct interface_data *iface) { @@ -123,73 +135,58 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface) const GDBusPropertyTable *property; for (method = iface->methods; method && method->name; method++) { - gboolean deprecated = method->flags & - G_DBUS_METHOD_FLAG_DEPRECATED; - gboolean noreply = method->flags & - G_DBUS_METHOD_FLAG_NOREPLY; - - if (!deprecated && !noreply && - !(method->in_args && method->in_args->name) && - !(method->out_args && method->out_args->name)) - g_string_append_printf(gstr, - "\t\t\n", - method->name); - else { + if (check_experimental(method->flags, + G_DBUS_METHOD_FLAG_EXPERIMENTAL)) + continue; + + g_string_append_printf(gstr, "", + method->name); + print_arguments(gstr, method->in_args, "in"); + print_arguments(gstr, method->out_args, "out"); + + if (method->flags & G_DBUS_METHOD_FLAG_DEPRECATED) g_string_append_printf(gstr, - "\t\t\n", - method->name); - print_arguments(gstr, method->in_args, "in"); - print_arguments(gstr, method->out_args, "out"); - - if (deprecated) - g_string_append_printf(gstr, - G_DBUS_ANNOTATE_DEPRECATED("\t\t\t")); - if (noreply) - g_string_append_printf(gstr, - G_DBUS_ANNOTATE_NOREPLY("\t\t\t")); - - g_string_append_printf(gstr, "\t\t\n"); - } + G_DBUS_ANNOTATE_DEPRECATED); + + if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) + g_string_append_printf(gstr, G_DBUS_ANNOTATE_NOREPLY); + + g_string_append_printf(gstr, ""); } for (signal = iface->signals; signal && signal->name; signal++) { - gboolean deprecated = signal->flags & - G_DBUS_SIGNAL_FLAG_DEPRECATED; + if (check_experimental(signal->flags, + G_DBUS_SIGNAL_FLAG_EXPERIMENTAL)) + continue; - if (!deprecated && !(signal->args && signal->args->name)) - g_string_append_printf(gstr, - "\t\t\n", - signal->name); - else { - g_string_append_printf(gstr, - "\t\t\n", - signal->name); - print_arguments(gstr, signal->args, NULL); + g_string_append_printf(gstr, "", + signal->name); + print_arguments(gstr, signal->args, NULL); - if (deprecated) - g_string_append_printf(gstr, - G_DBUS_ANNOTATE_DEPRECATED("\t\t\t")); + if (signal->flags & G_DBUS_SIGNAL_FLAG_DEPRECATED) + g_string_append_printf(gstr, + G_DBUS_ANNOTATE_DEPRECATED); - g_string_append_printf(gstr, "\t\t\n"); - } + g_string_append_printf(gstr, "\n"); } for (property = iface->properties; property && property->name; property++) { - gboolean deprecated = property->flags & - G_DBUS_PROPERTY_FLAG_DEPRECATED; + if (check_experimental(property->flags, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) + continue; - g_string_append_printf(gstr, "\t\t", property->name, property->type, property->get ? "read" : "", property->set ? "write" : ""); - if (!deprecated) - g_string_append_printf(gstr, "/>\n"); - else + if (property->flags & G_DBUS_PROPERTY_FLAG_DEPRECATED) g_string_append_printf(gstr, - G_DBUS_ANNOTATE_DEPRECATED(">\n\t\t\t")); + G_DBUS_ANNOTATE_DEPRECATED); + + g_string_append_printf(gstr, ""); } } @@ -205,30 +202,30 @@ static void generate_introspection_xml(DBusConnection *conn, gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); - g_string_append_printf(gstr, "\n"); + g_string_append_printf(gstr, ""); for (list = data->interfaces; list; list = list->next) { struct interface_data *iface = list->data; - g_string_append_printf(gstr, "\t\n", + g_string_append_printf(gstr, "", iface->name); generate_interface_xml(gstr, iface); - g_string_append_printf(gstr, "\t\n"); + g_string_append_printf(gstr, ""); } if (!dbus_connection_list_registered(conn, path, &children)) goto done; for (i = 0; children[i]; i++) - g_string_append_printf(gstr, "\t\n", + g_string_append_printf(gstr, "", children[i]); dbus_free_string_array(children); done: - g_string_append_printf(gstr, "\n"); + g_string_append_printf(gstr, ""); data->introspect = g_string_free(gstr, FALSE); } @@ -261,7 +258,8 @@ static DBusHandlerResult process_message(DBusConnection *connection, reply = method->function(connection, message, iface_user_data); - if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) { + if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY || + dbus_message_get_no_reply(message)) { if (reply != NULL) dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; @@ -275,8 +273,7 @@ static DBusHandlerResult process_message(DBusConnection *connection, if (reply == NULL) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); + g_dbus_send_message(connection, reply); return DBUS_HANDLER_RESULT_HANDLED; } @@ -316,19 +313,14 @@ void g_dbus_pending_error_valist(DBusConnection *connection, for (list = pending_security; list; list = list->next) { struct security_data *secdata = list->data; - DBusMessage *reply; if (secdata->pending != pending) continue; pending_security = g_slist_remove(pending_security, secdata); - reply = g_dbus_create_error_valist(secdata->message, + g_dbus_send_error_valist(connection, secdata->message, name, format, args); - if (reply != NULL) { - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } dbus_message_unref(secdata->message); g_free(secdata); @@ -473,18 +465,13 @@ void g_dbus_pending_property_error_valist(GDBusPendingReply id, va_list args) { struct property_data *propdata; - DBusMessage *reply; propdata = remove_pending_property_data(id); if (propdata == NULL) return; - reply = g_dbus_create_error_valist(propdata->message, name, format, - args); - if (reply != NULL) { - dbus_connection_send(propdata->conn, reply, NULL); - dbus_message_unref(reply); - } + g_dbus_send_error_valist(propdata->conn, propdata->message, name, + format, args); dbus_message_unref(propdata->message); g_free(propdata); @@ -540,6 +527,10 @@ static void append_properties(struct interface_data *data, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); for (p = data->properties; p && p->name; p++) { + if (check_experimental(p->flags, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) + continue; + if (p->get == NULL) continue; @@ -569,16 +560,11 @@ static void emit_interfaces_added(struct generic_data *data) { DBusMessage *signal; DBusMessageIter iter, array; - struct generic_data *parent = data->parent; - if (parent == NULL) + if (root == NULL || data == root) return; - /* Find root data */ - while (parent->parent) - parent = parent->parent; - - signal = dbus_message_new_signal(parent->path, + signal = dbus_message_new_signal(root->path, DBUS_INTERFACE_OBJECT_MANAGER, "InterfacesAdded"); if (signal == NULL) @@ -604,7 +590,9 @@ static void emit_interfaces_added(struct generic_data *data) dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); } static struct interface_data *find_interface(GSList *interfaces, @@ -645,6 +633,16 @@ static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args, return TRUE; } +static void add_pending(struct generic_data *data) +{ + if (data->process_id > 0) + return; + + data->process_id = g_idle_add(process_changes, data); + + pending = g_slist_append(pending, data); +} + static gboolean remove_interface(struct generic_data *data, const char *name) { struct interface_data *iface; @@ -682,10 +680,7 @@ static gboolean remove_interface(struct generic_data *data, const char *name) data->removed = g_slist_prepend(data->removed, iface->name); g_free(iface); - if (data->process_id > 0) - return TRUE; - - data->process_id = g_idle_add(process_changes, data); + add_pending(data); return TRUE; } @@ -746,8 +741,14 @@ static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable * const GDBusPropertyTable *p; for (p = properties; p && p->name; p++) { - if (strcmp(name, p->name) == 0) - return p; + if (strcmp(name, p->name) != 0) + continue; + + if (check_experimental(p->flags, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) + break; + + return p; } return NULL; @@ -845,6 +846,8 @@ static DBusMessage *properties_set(DBusConnection *connection, const GDBusPropertyTable *property; const char *name, *interface; struct property_data *propdata; + gboolean valid_signature; + char *signature; if (!dbus_message_iter_init(message, &iter)) return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, @@ -895,6 +898,14 @@ static DBusMessage *properties_set(DBusConnection *connection, DBUS_ERROR_UNKNOWN_PROPERTY, "No such property '%s'", name); + signature = dbus_message_iter_get_signature(&sub); + valid_signature = strcmp(signature, property->type) ? FALSE : TRUE; + dbus_free(signature); + if (!valid_signature) + return g_dbus_create_error(message, + DBUS_ERROR_INVALID_SIGNATURE, + "Invalid signature for '%s'", name); + propdata = g_new(struct property_data, 1); propdata->id = next_pending_property++; propdata->message = dbus_message_ref(message); @@ -943,16 +954,11 @@ static void emit_interfaces_removed(struct generic_data *data) { DBusMessage *signal; DBusMessageIter iter, array; - struct generic_data *parent = data->parent; - if (parent == NULL) + if (root == NULL || data == root) return; - /* Find root data */ - while (parent->parent) - parent = parent->parent; - - signal = dbus_message_new_signal(parent->path, + signal = dbus_message_new_signal(root->path, DBUS_INTERFACE_OBJECT_MANAGER, "InterfacesRemoved"); if (signal == NULL) @@ -970,14 +976,26 @@ static void emit_interfaces_removed(struct generic_data *data) dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); +} + +static void remove_pending(struct generic_data *data) +{ + if (data->process_id > 0) { + g_source_remove(data->process_id); + data->process_id = 0; + } + + pending = g_slist_remove(pending, data); } static gboolean process_changes(gpointer user_data) { struct generic_data *data = user_data; - data->process_id = 0; + remove_pending(data); if (data->added != NULL) emit_interfaces_added(data); @@ -989,6 +1007,8 @@ static gboolean process_changes(gpointer user_data) if (data->removed != NULL) emit_interfaces_removed(data); + data->process_id = 0; + return FALSE; } @@ -1002,6 +1022,7 @@ static void generic_unregister(DBusConnection *connection, void *user_data) if (data->process_id > 0) { g_source_remove(data->process_id); + data->process_id = 0; process_changes(data); } @@ -1030,10 +1051,15 @@ static DBusHandlerResult generic_message(DBusConnection *connection, for (method = iface->methods; method && method->name && method->function; method++) { + if (dbus_message_is_method_call(message, iface->name, method->name) == FALSE) continue; + if (check_experimental(method->flags, + G_DBUS_METHOD_FLAG_EXPERIMENTAL)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (g_dbus_args_have_signature(method->in_args, message) == FALSE) continue; @@ -1146,7 +1172,7 @@ static const GDBusSignalTable manager_signals[] = { { } }; -static void add_interface(struct generic_data *data, +static gboolean add_interface(struct generic_data *data, const char *name, const GDBusMethodTable *methods, const GDBusSignalTable *signals, @@ -1155,7 +1181,32 @@ static void add_interface(struct generic_data *data, GDBusDestroyFunction destroy) { struct interface_data *iface; + const GDBusMethodTable *method; + const GDBusSignalTable *signal; + const GDBusPropertyTable *property; + + for (method = methods; method && method->name; method++) { + if (!check_experimental(method->flags, + G_DBUS_METHOD_FLAG_EXPERIMENTAL)) + goto done; + } + + for (signal = signals; signal && signal->name; signal++) { + if (!check_experimental(signal->flags, + G_DBUS_SIGNAL_FLAG_EXPERIMENTAL)) + goto done; + } + + for (property = properties; property && property->name; property++) { + if (!check_experimental(property->flags, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) + goto done; + } + + /* Nothing to register */ + return FALSE; +done: iface = g_new0(struct interface_data, 1); iface->name = g_strdup(name); iface->methods = methods; @@ -1166,13 +1217,13 @@ static void add_interface(struct generic_data *data, data->interfaces = g_slist_append(data->interfaces, iface); if (data->parent == NULL) - return; + return TRUE; data->added = g_slist_append(data->added, iface); - if (data->process_id > 0) - return; - data->process_id = g_idle_add(process_changes, data); + add_pending(data); + + return TRUE; } static struct generic_data *object_path_ref(DBusConnection *connection, @@ -1197,6 +1248,10 @@ static struct generic_data *object_path_ref(DBusConnection *connection, if (!dbus_connection_register_object_path(connection, path, &generic_table, data)) { +#if !defined TIZEN_EXT + dbus_connection_unref(data->conn); + g_free(data->path); +#endif g_free(data->introspect); g_free(data); return NULL; @@ -1207,15 +1262,6 @@ static struct generic_data *object_path_ref(DBusConnection *connection, add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, introspect_methods, NULL, NULL, data, NULL); - /* Only root path export ObjectManager interface */ - if (data->parent == NULL) - add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER, - manager_methods, manager_signals, - NULL, data, NULL); - - add_interface(data, DBUS_INTERFACE_PROPERTIES, properties_methods, - properties_signals, NULL, data, NULL); - return data; } @@ -1237,7 +1283,6 @@ static void object_path_unref(DBusConnection *connection, const char *path) remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE); remove_interface(data, DBUS_INTERFACE_PROPERTIES); - remove_interface(data, DBUS_INTERFACE_OBJECT_MANAGER); invalidate_parent_data(data->conn, data->path); @@ -1268,55 +1313,23 @@ static gboolean check_signal(DBusConnection *conn, const char *path, } for (signal = iface->signals; signal && signal->name; signal++) { - if (!strcmp(signal->name, name)) { - *args = signal->args; - return TRUE; + if (strcmp(signal->name, name) != 0) + continue; + + if (signal->flags & G_DBUS_SIGNAL_FLAG_EXPERIMENTAL) { + const char *env = g_getenv("GDBUS_EXPERIMENTAL"); + if (g_strcmp0(env, "1") != 0) + break; } + + *args = signal->args; + return TRUE; } error("No signal named %s on interface %s", name, interface); return FALSE; } -static dbus_bool_t emit_signal_valist(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int first, - va_list var_args) -{ - DBusMessage *signal; - dbus_bool_t ret; - const GDBusArgInfo *args; - - if (!check_signal(conn, path, interface, name, &args)) - return FALSE; - - signal = dbus_message_new_signal(path, interface, name); - if (signal == NULL) { - error("Unable to allocate new %s.%s signal", interface, name); - return FALSE; - } - - ret = dbus_message_append_args_valist(signal, first, var_args); - if (!ret) - goto fail; - - if (g_dbus_args_have_signature(args, signal) == FALSE) { - error("%s.%s: got unexpected signature '%s'", interface, name, - dbus_message_get_signature(signal)); - ret = FALSE; - goto fail; - } - - ret = dbus_connection_send(conn, signal, NULL); - -fail: - dbus_message_unref(signal); - - return ret; -} - gboolean g_dbus_register_interface(DBusConnection *connection, const char *path, const char *name, const GDBusMethodTable *methods, @@ -1336,8 +1349,17 @@ gboolean g_dbus_register_interface(DBusConnection *connection, return FALSE; } - add_interface(data, name, methods, signals, properties, user_data, - destroy); + if (!add_interface(data, name, methods, signals, properties, user_data, + destroy)) { + object_path_unref(connection, path); + return FALSE; + } + + if (properties != NULL && !find_interface(data->interfaces, + DBUS_INTERFACE_PROPERTIES)) + add_interface(data, DBUS_INTERFACE_PROPERTIES, + properties_methods, properties_signals, NULL, + data, NULL); g_free(data->introspect); data->introspect = NULL; @@ -1393,7 +1415,10 @@ DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name, { char str[1024]; - vsnprintf(str, sizeof(str), format, args); + if (format) + vsnprintf(str, sizeof(str), format, args); + else + str[0] = '\0'; return dbus_message_new_error(message, name, str); } @@ -1444,20 +1469,97 @@ DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...) return reply; } +static void g_dbus_flush(DBusConnection *connection) +{ + GSList *l; + + for (l = pending; l;) { + struct generic_data *data = l->data; + + l = l->next; + if (data->conn != connection) + continue; + + process_changes(data); + } +} + gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message) { - dbus_bool_t result; + dbus_bool_t result = FALSE; if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL) dbus_message_set_no_reply(message, TRUE); + else if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL) { + const char *path = dbus_message_get_path(message); + const char *interface = dbus_message_get_interface(message); + const char *name = dbus_message_get_member(message); + const GDBusArgInfo *args; + + if (!check_signal(connection, path, interface, name, &args)) + goto out; + } + + /* Flush pending signal to guarantee message order */ + g_dbus_flush(connection); result = dbus_connection_send(connection, message, NULL); +out: dbus_message_unref(message); return result; } +gboolean g_dbus_send_message_with_reply(DBusConnection *connection, + DBusMessage *message, + DBusPendingCall **call, int timeout) +{ + dbus_bool_t ret; + + /* Flush pending signal to guarantee message order */ + g_dbus_flush(connection); + + ret = dbus_connection_send_with_reply(connection, message, call, + timeout); + + if (ret == TRUE && call != NULL && *call == NULL) { + error("Unable to send message (passing fd blocked?)"); + return FALSE; + } + + return ret; +} + +gboolean g_dbus_send_error_valist(DBusConnection *connection, + DBusMessage *message, const char *name, + const char *format, va_list args) +{ + DBusMessage *error; + + error = g_dbus_create_error_valist(message, name, format, args); + if (error == NULL) + return FALSE; + + return g_dbus_send_message(connection, error); +} + +gboolean g_dbus_send_error(DBusConnection *connection, DBusMessage *message, + const char *name, const char *format, ...) +{ + va_list args; + gboolean result; + + va_start(args, format); + + result = g_dbus_send_error_valist(connection, message, name, + format, args); + + va_end(args); + + return result; +} + gboolean g_dbus_send_reply_valist(DBusConnection *connection, DBusMessage *message, int type, va_list args) { @@ -1499,7 +1601,7 @@ gboolean g_dbus_emit_signal(DBusConnection *connection, va_start(args, type); - result = emit_signal_valist(connection, path, interface, + result = g_dbus_emit_signal_valist(connection, path, interface, name, type, args); va_end(args); @@ -1511,8 +1613,36 @@ gboolean g_dbus_emit_signal_valist(DBusConnection *connection, const char *path, const char *interface, const char *name, int type, va_list args) { - return emit_signal_valist(connection, path, interface, - name, type, args); + DBusMessage *signal; + dbus_bool_t ret; + const GDBusArgInfo *args_info; + + if (!check_signal(connection, path, interface, name, &args_info)) + return FALSE; + + signal = dbus_message_new_signal(path, interface, name); + if (signal == NULL) { + error("Unable to allocate new %s.%s signal", interface, name); + return FALSE; + } + + ret = dbus_message_append_args_valist(signal, type, args); + if (!ret) + goto fail; + + if (g_dbus_args_have_signature(args_info, signal) == FALSE) { + error("%s.%s: got unexpected signature '%s'", interface, name, + dbus_message_get_signature(signal)); + ret = FALSE; + goto fail; + } + + return g_dbus_send_message(connection, signal); + +fail: + dbus_message_unref(signal); + + return ret; } static void process_properties_from_interface(struct generic_data *data, @@ -1523,6 +1653,8 @@ static void process_properties_from_interface(struct generic_data *data, DBusMessageIter iter, dict, array; GSList *invalidated; + data->pending_prop = FALSE; + if (iface->pending_prop == NULL) return; @@ -1572,10 +1704,12 @@ static void process_properties_from_interface(struct generic_data *data, g_slist_free(invalidated); dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); - g_slist_free(iface->pending_prop); iface->pending_prop = NULL; + + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); } static void process_property_changes(struct generic_data *data) @@ -1587,18 +1721,20 @@ static void process_property_changes(struct generic_data *data) process_properties_from_interface(data, iface); } - - data->pending_prop = FALSE; } -void g_dbus_emit_property_changed(DBusConnection *connection, +void g_dbus_emit_property_changed_full(DBusConnection *connection, const char *path, const char *interface, - const char *name) + const char *name, + GDbusPropertyChangedFlags flags) { const GDBusPropertyTable *property; struct generic_data *data; struct interface_data *iface; + if (path == NULL) + return; + if (!dbus_connection_get_object_path_data(connection, path, (void **) &data) || data == NULL) return; @@ -1607,6 +1743,13 @@ void g_dbus_emit_property_changed(DBusConnection *connection, if (iface == NULL) return; + /* + * If ObjectManager is attached, don't emit property changed if + * interface is not yet published + */ + if (root && g_slist_find(data->added, iface)) + return; + property = find_property(iface->properties, name); if (property == NULL) { error("Could not find property %s in %p", name, @@ -1614,14 +1757,23 @@ void g_dbus_emit_property_changed(DBusConnection *connection, return; } + if (g_slist_find(iface->pending_prop, (void *) property) != NULL) + return; + data->pending_prop = TRUE; iface->pending_prop = g_slist_prepend(iface->pending_prop, (void *) property); - if (!data->process_id) { - data->process_id = g_idle_add(process_changes, data); - return; - } + if (flags & G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH) + process_property_changes(data); + else + add_pending(data); +} + +void g_dbus_emit_property_changed(DBusConnection *connection, const char *path, + const char *interface, const char *name) +{ + g_dbus_emit_property_changed_full(connection, path, interface, name, 0); } gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, @@ -1630,6 +1782,9 @@ gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, struct generic_data *data; struct interface_data *iface; + if (path == NULL) + return FALSE; + if (!dbus_connection_get_object_path_data(connection, path, (void **) &data) || data == NULL) return FALSE; @@ -1642,3 +1797,40 @@ gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, return TRUE; } + +gboolean g_dbus_attach_object_manager(DBusConnection *connection) +{ + struct generic_data *data; + + data = object_path_ref(connection, "/"); + if (data == NULL) + return FALSE; + + add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER, + manager_methods, manager_signals, + NULL, data, NULL); + root = data; + + return TRUE; +} + +gboolean g_dbus_detach_object_manager(DBusConnection *connection) +{ + if (!g_dbus_unregister_interface(connection, "/", + DBUS_INTERFACE_OBJECT_MANAGER)) + return FALSE; + + root = NULL; + + return TRUE; +} + +void g_dbus_set_flags(int flags) +{ + global_flags = flags; +} + +int g_dbus_get_flags(void) +{ + return global_flags; +}