diff options
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 10 | ||||
-rw-r--r-- | src/dbus/qdbusconnection_p.h | 7 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 28 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp | 13 |
4 files changed, 45 insertions, 13 deletions
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 678b10d108..dd9417b87a 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -803,13 +803,8 @@ bool QDBusConnection::registerObject(const QString &path, QObject *object, Regis return false; if (options & QDBusConnectionPrivate::VirtualObject) { - // technically the check for children needs to go even deeper - if (options & SubPath) { - foreach (const QDBusConnectionPrivate::ObjectTreeNode &child, node->children) { - if (child.obj) - return false; - } - } + if (options & SubPath && node->activeChildren) + return false; } else { if ((options & ExportChildObjects && !node->children.isEmpty())) return false; @@ -846,6 +841,7 @@ bool QDBusConnection::registerObject(const QString &path, QObject *object, Regis } } else { // add entry + ++node->activeChildren; node = node->children.insert(it, pathComponents.at(i)); } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 50307e2738..3beb258bd8 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -140,14 +140,16 @@ public: { typedef QVector<ObjectTreeNode> DataList; - inline ObjectTreeNode() : obj(0), flags(0) { } + inline ObjectTreeNode() : obj(0), flags(0), activeChildren(0) { } inline ObjectTreeNode(const QString &n) // intentionally implicit - : name(n), obj(0), flags(0) { } + : name(n), obj(0), flags(0), activeChildren(0) { } inline ~ObjectTreeNode() { } inline bool operator<(const QString &other) const { return name < other; } inline bool operator<(const QStringRef &other) const { return QStringRef(&name) < other; } + inline bool isActive() const + { return obj || activeChildren; } QString name; union { @@ -155,6 +157,7 @@ public: QDBusVirtualObject *treeNode; }; int flags; + int activeChildren; DataList children; }; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 72586404a2..0caccbe044 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -591,13 +591,23 @@ static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNo { QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator end = haystack.children.end(); - for ( ; it != end; ++it) + for ( ; it != end; ++it) { + if (!it->isActive()) + continue; huntAndDestroy(needle, *it); + if (!it->isActive()) + --haystack.activeChildren; + } if (needle == haystack.obj) { haystack.obj = 0; haystack.flags = 0; } + + if (haystack.activeChildren == 0) { + // quick clean-up, if we're out of children + haystack.children.clear(); + } } static void huntAndUnregister(const QStringList &pathComponents, int i, QDBusConnection::UnregisterMode mode, @@ -610,6 +620,7 @@ static void huntAndUnregister(const QStringList &pathComponents, int i, QDBusCon if (mode == QDBusConnection::UnregisterTree) { // clear the sub-tree as well + node->activeChildren = 0; node->children.clear(); // can't disconnect the objects because we really don't know if they can // be found somewhere else in the path too } @@ -618,10 +629,17 @@ static void huntAndUnregister(const QStringList &pathComponents, int i, QDBusCon QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator end = node->children.end(); QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = std::lower_bound(node->children.begin(), end, pathComponents.at(i)); - if (it == end || it->name != pathComponents.at(i)) + if (it == end || it->name != pathComponents.at(i) || !it->isActive()) return; // node not found huntAndUnregister(pathComponents, i + 1, mode, it); + if (!it->isActive()) + --node->activeChildren; + + if (node->activeChildren == 0) { + // quick clean-up, if we're out of children + node->children.clear(); + } } } @@ -631,8 +649,10 @@ static void huntAndEmit(DBusConnection *connection, DBusMessage *msg, { QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = haystack.children.constBegin(); QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd(); - for ( ; it != end; ++it) - huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1Char('/') + it->name); + for ( ; it != end; ++it) { + if (it->isActive()) + huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1Char('/') + it->name); + } if (needle == haystack.obj) { // is this a signal we should relay? diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index ffcc2ddcdc..3c08f8999c 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1200,6 +1200,19 @@ void tst_QDBusConnection::registerVirtualObject() QVERIFY(!con.registerVirtualObject(path, &obj, QDBusConnection::SubPath)); QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); } + + { + // Register object, make sure no SubPath handling object can be registered on a parent path. + // (same as above, but deeper) + QObject objectAtSubPath; + QVERIFY(con.registerObject(childChildPath, &objectAtSubPath)); + QCOMPARE(con.objectRegisteredAt(childChildPath), static_cast<QObject *>(&objectAtSubPath)); + + VirtualObject obj; + QVERIFY(!con.registerVirtualObject(path, &obj, QDBusConnection::SubPath)); + QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); + } + QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); QCOMPARE(con.objectRegisteredAt(childPath), static_cast<QObject *>(0)); QCOMPARE(con.objectRegisteredAt(childChildPath), static_cast<QObject *>(0)); |