diff options
-rw-r--r-- | ChangeLog | 38 | ||||
-rw-r--r-- | qt/qdbusabstractinterface.cpp | 2 | ||||
-rw-r--r-- | qt/qdbusabstractinterface.h | 84 | ||||
-rw-r--r-- | qt/qdbusbus.h | 2 | ||||
-rw-r--r-- | qt/qdbusconnection.h | 2 | ||||
-rw-r--r-- | qt/qdbusconnection_p.h | 1 | ||||
-rw-r--r-- | qt/qdbusintegrator.cpp | 85 | ||||
-rw-r--r-- | qt/qdbusinterface.cpp | 17 | ||||
-rw-r--r-- | qt/qdbusinterface.h | 15 | ||||
-rw-r--r-- | qt/qdbusinterface_p.h | 2 | ||||
-rw-r--r-- | qt/qdbusinternalfilters.cpp | 10 |
11 files changed, 230 insertions, 28 deletions
@@ -1,5 +1,43 @@ 2006-04-29 Thiago Macieira <thiago.macieira@trolltech.com> + * qt/qdbusinterface.h: Rename QDBusRef to QDBusInterfacePtr + and disable the copy operators. (r533772, r534746) + + * qt/qdbuserror.h: Remove the automatic cast to bool. (r533929) + + * qt/qdbusabstractinterface.cpp: + * qt/qdbusabstractinterface.h: Change the default call mode to + not use the event loop. Add convenience call() methods that + take a CallMode parameter. (r534042) + + * qt/qdbusconnection.h: Change the default call mode to not + use the event loop. (r534042) + + * qt/qdbusinterface.cpp: + * qt/qdbusinterface.h: Add a method to tell us if the + interface is valid (since we don't return a null pointer + anymore) (r534099) + + * qt/qdbusinterface_p.h: Don't crash if metaObject is 0 + (r534101) + + * qt/qdbusinternalfilters.cpp: Decouple the introspection + function in two so taht we get the chance to introspect + without having a QDBusMessage (r534102) + + * qt/qdbusbus.h: + * qt/qdbusconnection.cpp: + * qt/qdbusconnection_p.h: + * qt/qdbusintegrator.cpp: Keep a list of our own names to + avoid a round-trip to the server when attempting to introspect + one of our own objects. Also make sure the filter functions + match the empty interface as well. (r534108) + Don't keep the connection names. Instead, trust the unique + connection name (r534111) + Remove event loop usage (r534112) + +2006-04-29 Thiago Macieira <thiago.macieira@trolltech.com> + * qt/qdbusintegrator.cpp: Fix assertion failure spotted by Brad Hards. diff --git a/qt/qdbusabstractinterface.cpp b/qt/qdbusabstractinterface.cpp index 291888fe..eec373a3 100644 --- a/qt/qdbusabstractinterface.cpp +++ b/qt/qdbusabstractinterface.cpp @@ -148,7 +148,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgs(const QString& method, const Q if (mode == AutoDetect) { // determine if this a sync or async call - mode = UseEventLoop; + mode = NoUseEventLoop; const QMetaObject *mo = metaObject(); QByteArray match = method.toLatin1() + '('; diff --git a/qt/qdbusabstractinterface.h b/qt/qdbusabstractinterface.h index ae80b0a3..23f928a2 100644 --- a/qt/qdbusabstractinterface.h +++ b/qt/qdbusabstractinterface.h @@ -69,6 +69,11 @@ public: { return callWithArgs(m); } + + inline QDBusMessage call(CallMode mode, const QString &m) + { + return callWithArgs(m, QList<QVariant>(), mode); + } #ifndef Q_QDOC private: @@ -152,6 +157,85 @@ public: << qvfv(t7) << qvfv(t8); return callWithArgs(m, args); } + + template<typename T1> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1) + { + QList<QVariant> args; + args << qvfv(t1); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3, typename T4> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3, const T4 &t4) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3) + << qvfv(t4); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3, const T4 &t4, const T5 &t5) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3) + << qvfv(t4) << qvfv(t5); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3) + << qvfv(t4) << qvfv(t5) << qvfv(t6); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3) + << qvfv(t4) << qvfv(t5) << qvfv(t6) + << qvfv(t7); + return callWithArgs(m, args, mode); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8> + inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2, + const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, + const T8 &t8) + { + QList<QVariant> args; + args << qvfv(t1) << qvfv(t2) << qvfv(t3) + << qvfv(t4) << qvfv(t5) << qvfv(t6) + << qvfv(t7) << qvfv(t8); + return callWithArgs(m, args, mode); + } #endif protected: diff --git a/qt/qdbusbus.h b/qt/qdbusbus.h index ae2720e2..6f0bbb1c 100644 --- a/qt/qdbusbus.h +++ b/qt/qdbusbus.h @@ -150,7 +150,7 @@ public slots: signals: void nameAcquired(const QString &service); void nameLost(const QString &service); - void nameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + void nameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusBusService::RequestNameOptions); diff --git a/qt/qdbusconnection.h b/qt/qdbusconnection.h index 60116e10..e107242b 100644 --- a/qt/qdbusconnection.h +++ b/qt/qdbusconnection.h @@ -74,7 +74,7 @@ public: QDBusError lastError() const; bool send(const QDBusMessage &message) const; - QDBusMessage sendWithReply(const QDBusMessage &message, WaitMode mode = UseEventLoop) const; + QDBusMessage sendWithReply(const QDBusMessage &message, WaitMode mode = NoUseEventLoop) const; int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, const char *slot) const; diff --git a/qt/qdbusconnection_p.h b/qt/qdbusconnection_p.h index 36f21db7..af572084 100644 --- a/qt/qdbusconnection_p.h +++ b/qt/qdbusconnection_p.h @@ -230,6 +230,7 @@ extern int qDBusNameToTypeId(const char *name); extern bool qDBusCheckAsyncTag(const char *tag); // in qdbusinternalfilters.cpp +extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node); extern void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node, const QDBusMessage &msg); extern void qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode *node, diff --git a/qt/qdbusintegrator.cpp b/qt/qdbusintegrator.cpp index bef8268d..3f907256 100644 --- a/qt/qdbusintegrator.cpp +++ b/qt/qdbusintegrator.cpp @@ -984,13 +984,14 @@ bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node, { // object may be null - if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) { + if (msg.interface().isEmpty() || msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) { if (msg.method() == QLatin1String("Introspect") && msg.signature().isEmpty()) qDBusIntrospectObject(node, msg); return true; } - if (node->obj && msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES)) { + if (node->obj && (msg.interface().isEmpty() || + msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES))) { if (msg.method() == QLatin1String("Get") && msg.signature() == QLatin1String("ss")) qDBusPropertyGet(node, msg); else if (msg.method() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv")) @@ -1053,25 +1054,26 @@ bool QDBusConnectionPrivate::activateObject(const ObjectTreeNode *node, const QD return false; } -bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) +template<typename Func> +static bool applyForObject(QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, + Func& functor) { - QReadLocker locker(&lock); - // walk the object tree - QStringList path = msg.path().split(QLatin1Char('/')); + QStringList path = fullpath.split(QLatin1Char('/')); if (path.last().isEmpty()) path.removeLast(); // happens if path is "/" int i = 1; - ObjectTreeNode *node = &rootNode; + QDBusConnectionPrivate::ObjectTreeNode *node = root; // try our own tree first while (node && !(node->flags & QDBusConnection::ExportChildObjects) ) { if (i == path.count()) { // found our object - return activateObject(node, msg); + functor(node); + return true; } - QVector<ObjectTreeNode::Data>::ConstIterator it = + QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it = qLowerBound(node->children.constBegin(), node->children.constEnd(), path.at(i)); if (it != node->children.constEnd() && it->name == path.at(i)) // match @@ -1089,9 +1091,10 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) while (obj) { if (i == path.count()) { // we're at the correct level - ObjectTreeNode fakenode(*node); + QDBusConnectionPrivate::ObjectTreeNode fakenode(*node); fakenode.obj = obj; - return activateObject(&fakenode, msg); + functor(&fakenode); + return true; } const QObjectList &children = obj->children(); @@ -1112,6 +1115,31 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) } } + // object not found + return false; +} + +struct qdbus_activateObject +{ + QDBusConnectionPrivate *self; + const QDBusMessage &msg; + bool returnVal; + inline qdbus_activateObject(QDBusConnectionPrivate *s, const QDBusMessage &m) + : self(s), msg(m) + { } + + inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node) + { returnVal = self->activateObject(node, msg); } +}; + +bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) +{ + QReadLocker locker(&lock); + + qdbus_activateObject apply(this, msg); + if (applyForObject(&rootNode, msg.path(), apply)) + return apply.returnVal; + qDebug("Call failed: no object found at %s", qPrintable(msg.path())); return false; } @@ -1479,6 +1507,7 @@ QDBusConnectionPrivate::findInterface(const QString &service, QString owner = getNameOwner(service); if (connection && !owner.isEmpty() && QDBusUtil::isValidObjectPath(path) && (interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface))) + // always call here with the unique connection name mo = findMetaObject(owner, path, interface); QDBusInterfacePrivate *p = new QDBusInterfacePrivate(QDBusConnection(name), this, owner, path, interface, mo); @@ -1509,24 +1538,52 @@ QDBusConnectionPrivate::findInterface(const QString &service, return p; } +struct qdbus_Introspect +{ + QString xml; + inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node) + { xml = qDBusIntrospectObject(node); } +}; + QDBusMetaObject * QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &path, const QString &interface) { + // service must be a unique connection name if (!interface.isEmpty()) { QReadLocker locker(&lock); QDBusMetaObject *mo = cachedMetaObjects.value(interface, 0); if (mo) return mo; } + if (service == QString::fromUtf8(dbus_bus_get_unique_name(connection))) { + // it's one of our own + QWriteLocker locker(&lock); + QDBusMetaObject *mo = 0; + if (!interface.isEmpty()) + mo = cachedMetaObjects.value(interface, 0); + if (mo) + // maybe it got created when we switched from read to write lock + return mo; + + qdbus_Introspect apply; + if (!applyForObject(&rootNode, path, apply)) { + lastError = QDBusError(QDBusError::InvalidArgs, + QString(QLatin1String("No object at %1")).arg(path)); + return 0; // no object at path + } + + // release the lock and return + return QDBusMetaObject::createMetaObject(interface, apply.xml, cachedMetaObjects, lastError); + } - // introspect the target object: + // not local: introspect the target object: QDBusMessage msg = QDBusMessage::methodCall(service, path, QLatin1String(DBUS_INTERFACE_INTROSPECTABLE), QLatin1String("Introspect")); - // we have to spin the event loop because the call could be targetting ourselves - QDBusMessage reply = sendWithReply(msg, QDBusConnection::UseEventLoop); + + QDBusMessage reply = sendWithReply(msg, QDBusConnection::NoUseEventLoop); // it doesn't exist yet, we have to create it QWriteLocker locker(&lock); diff --git a/qt/qdbusinterface.cpp b/qt/qdbusinterface.cpp index ff8fdc95..48b1011c 100644 --- a/qt/qdbusinterface.cpp +++ b/qt/qdbusinterface.cpp @@ -58,6 +58,19 @@ QDBusInterface::~QDBusInterface() } /*! + Returns true if this is a valid reference to a remote object. It returns false if + there was an error during the creation of this interface (for instance, if the remote + application does not exist). + + Note: when dealing with remote objects, it is not always possible to determine if it + exists when creating a QDBusInterface or QDBusInterfacePtr object. +*/ +bool QDBusInterface::isValid() const +{ + return d_func()->isValid; +} + +/*! \internal Overrides QObject::metaObject to return our own copy. */ @@ -238,13 +251,13 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv) return id; } -QDBusRef::QDBusRef(QDBusConnection &conn, const QString &service, const QString &path, +QDBusInterfacePtr::QDBusInterfacePtr(QDBusConnection &conn, const QString &service, const QString &path, const QString &interface) : d(conn.findInterface(service, path, interface)) { } -QDBusRef::QDBusRef(const QString &service, const QString &path, const QString &interface) +QDBusInterfacePtr::QDBusInterfacePtr(const QString &service, const QString &path, const QString &interface) : d(QDBus::sessionBus().findInterface(service, path, interface)) { } diff --git a/qt/qdbusinterface.h b/qt/qdbusinterface.h index f667698b..2e16e5ce 100644 --- a/qt/qdbusinterface.h +++ b/qt/qdbusinterface.h @@ -35,6 +35,8 @@ private: public: ~QDBusInterface(); + bool isValid() const; + virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); @@ -43,16 +45,19 @@ private: Q_DECLARE_PRIVATE(QDBusInterface); }; -struct QDBUS_EXPORT QDBusRef +struct QDBUS_EXPORT QDBusInterfacePtr { - QDBusRef(QDBusConnection &conn, const QString &service, const QString &path, + QDBusInterfacePtr(QDBusInterface *iface) : d(iface) { } + QDBusInterfacePtr(QDBusConnection &conn, const QString &service, const QString &path, const QString &interface = QString()); - QDBusRef(const QString &service, const QString &path, const QString &interface = QString()); - ~QDBusRef() { delete d; } + QDBusInterfacePtr(const QString &service, const QString &path, const QString &interface = QString()); + ~QDBusInterfacePtr() { delete d; } - QDBusInterface* operator->() const { return d; } + QDBusInterface *interface() { return d; } + QDBusInterface *operator->() { return d; } private: QDBusInterface *const d; + Q_DISABLE_COPY(QDBusInterfacePtr) }; #endif diff --git a/qt/qdbusinterface_p.h b/qt/qdbusinterface_p.h index 70b732c2..25cb9ffa 100644 --- a/qt/qdbusinterface_p.h +++ b/qt/qdbusinterface_p.h @@ -55,7 +55,7 @@ public: } ~QDBusInterfacePrivate() { - if (!metaObject->cached) + if (metaObject && !metaObject->cached) delete metaObject; } diff --git a/qt/qdbusinternalfilters.cpp b/qt/qdbusinternalfilters.cpp index fe57a875..3d454277 100644 --- a/qt/qdbusinternalfilters.cpp +++ b/qt/qdbusinternalfilters.cpp @@ -225,8 +225,7 @@ static QString generateSubObjectXml(QObject *object) return retval; } -void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node, - const QDBusMessage &msg) +QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node) { // object may be null @@ -281,10 +280,15 @@ void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node, } xml_data += QLatin1String("</node>\n"); + return xml_data; +} +void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node, + const QDBusMessage &msg) +{ // now send it QDBusMessage reply = QDBusMessage::methodReply(msg); - reply << xml_data; + reply << qDBusIntrospectObject(node); msg.connection().send(reply); } |