summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dbus/qdbusconnection.cpp10
-rw-r--r--src/dbus/qdbusconnection_p.h7
-rw-r--r--src/dbus/qdbusintegrator.cpp28
-rw-r--r--tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp13
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));