mirror of https://github.com/qt/qtbase.git
QDBusServiceWatcher: Move the logic to QDBusConnectionPrivate
With kdbus, we won't have a regular signal, but instead a special message. So keep the logic of what to do in QDBusConnectionPrivate. The #ifdef is to make sure the bootstrapped qdbuscpp2xml continues to build in cross-compilation environments. Change-Id: Iee8cbc07c4434ce9b560ffff13d06f0d9904cb6d Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
This commit is contained in:
parent
186d881440
commit
f744aece9d
|
@ -63,6 +63,7 @@
|
|||
#include "qdbus_symbols_p.h"
|
||||
|
||||
#include <qdbusmessage.h>
|
||||
#include <qdbusservicewatcher.h> // for the WatchMode enum
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
|
||||
|
@ -198,6 +199,12 @@ public:
|
|||
|
||||
QString getNameOwner(const QString &service);
|
||||
|
||||
bool shouldWatchService(const QString &service);
|
||||
void watchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
|
||||
QObject *obj, const char *member);
|
||||
void unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
|
||||
QObject *obj, const char *member);
|
||||
|
||||
bool send(const QDBusMessage &message);
|
||||
QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1);
|
||||
QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
|
||||
|
|
|
@ -445,11 +445,27 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool shouldWatchService(const QString &service)
|
||||
static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
|
||||
{
|
||||
return !service.isEmpty() && !service.startsWith(QLatin1Char(':'));
|
||||
QStringList matchArgs;
|
||||
matchArgs << service;
|
||||
|
||||
switch (mode) {
|
||||
case QDBusServiceWatcher::WatchForOwnerChange:
|
||||
break;
|
||||
|
||||
case QDBusServiceWatcher::WatchForRegistration:
|
||||
matchArgs << QString::fromLatin1("", 0);
|
||||
break;
|
||||
|
||||
case QDBusServiceWatcher::WatchForUnregistration:
|
||||
matchArgs << QString() << QString::fromLatin1("", 0);
|
||||
break;
|
||||
}
|
||||
return matchArgs;
|
||||
}
|
||||
|
||||
|
||||
extern Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook);
|
||||
void qDBusAddSpyHook(QDBusSpyHook hook)
|
||||
{
|
||||
|
@ -1473,10 +1489,7 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
|
|||
for ( ; it != end && it.key() == key; ++it) {
|
||||
const SignalHook &hook = it.value();
|
||||
if (!hook.service.isEmpty()) {
|
||||
const QString owner =
|
||||
shouldWatchService(hook.service) ?
|
||||
watchedServices.value(hook.service).owner :
|
||||
hook.service;
|
||||
QString owner = watchedServices.value(hook.service, WatchedServiceData(hook.service)).owner;
|
||||
if (owner != msg.service())
|
||||
continue;
|
||||
}
|
||||
|
@ -2278,6 +2291,51 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
|
|||
}
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::shouldWatchService(const QString &service)
|
||||
{
|
||||
// we don't have to watch anything in peer mode
|
||||
if (mode != ClientMode)
|
||||
return false;
|
||||
// we don't have to watch wildcard services (empty strings)
|
||||
if (service.isEmpty())
|
||||
return false;
|
||||
// we don't have to watch the bus driver
|
||||
if (service == QDBusUtil::dbusService())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets up a watch rule for service \a service for the change described by
|
||||
mode \a mode. When the change happens, slot \a member in object \a obj will
|
||||
be called.
|
||||
|
||||
The caller should call QDBusConnectionPrivate::shouldWatchService() before
|
||||
calling this function to check whether the service needs to be watched at
|
||||
all. Failing to do so may add rules that are never activated.
|
||||
*/
|
||||
void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
|
||||
{
|
||||
QStringList matchArgs = matchArgsForService(service, mode);
|
||||
connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||
matchArgs, QString(), obj, member);
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a watch rule set up by QDBusConnectionPrivate::watchService(). The
|
||||
arguments to this function must be the same as the ones for that function.
|
||||
|
||||
Sets up a watch rule for service \a service for the change described by
|
||||
mode \a mode. When the change happens, slot \a member in object \a obj will
|
||||
be called.
|
||||
*/
|
||||
void QDBusConnectionPrivate::unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
|
||||
{
|
||||
QStringList matchArgs = matchArgsForService(service, mode);
|
||||
disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||
matchArgs, QString(), obj, member);
|
||||
}
|
||||
|
||||
QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName)
|
||||
{
|
||||
if (QDBusUtil::isValidUniqueConnectionName(serviceName))
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <QStringList>
|
||||
|
||||
#include <private/qobject_p.h>
|
||||
#include <private/qdbusconnection_p.h>
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
|
||||
|
@ -59,7 +60,6 @@ public:
|
|||
void _q_serviceOwnerChanged(const QString &, const QString &, const QString &);
|
||||
void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode);
|
||||
|
||||
QStringList matchArgsForService(const QString &service);
|
||||
void addService(const QString &service);
|
||||
void removeService(const QString &service);
|
||||
};
|
||||
|
@ -93,40 +93,18 @@ void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBus
|
|||
}
|
||||
}
|
||||
|
||||
QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service)
|
||||
{
|
||||
QStringList matchArgs;
|
||||
matchArgs << service;
|
||||
|
||||
switch (watchMode) {
|
||||
case QDBusServiceWatcher::WatchForOwnerChange:
|
||||
break;
|
||||
|
||||
case QDBusServiceWatcher::WatchForRegistration:
|
||||
matchArgs << QString::fromLatin1("", 0);
|
||||
break;
|
||||
|
||||
case QDBusServiceWatcher::WatchForUnregistration:
|
||||
matchArgs << QString() << QString::fromLatin1("", 0);
|
||||
break;
|
||||
}
|
||||
return matchArgs;
|
||||
}
|
||||
|
||||
void QDBusServiceWatcherPrivate::addService(const QString &service)
|
||||
{
|
||||
QStringList matchArgs = matchArgsForService(service);
|
||||
connection.connect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||
matchArgs, QString(), q_func(),
|
||||
SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
|
||||
QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection);
|
||||
if (d && d->shouldWatchService(service))
|
||||
d->watchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
|
||||
}
|
||||
|
||||
void QDBusServiceWatcherPrivate::removeService(const QString &service)
|
||||
{
|
||||
QStringList matchArgs = matchArgsForService(service);
|
||||
connection.disconnect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||
matchArgs, QString(), q_func(),
|
||||
SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
|
||||
QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection);
|
||||
if (d && d->shouldWatchService(service))
|
||||
d->unwatchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <QtCore/qobject.h>
|
||||
#include <QtDBus/qdbusmacros.h>
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_QOBJECT)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -89,5 +89,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusServiceWatcher::WatchMode)
|
|||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_DBUS
|
||||
#endif // QT_NO_DBUS || QT_NO_QOBJECT
|
||||
#endif // QDBUSSERVICEWATCHER_H
|
||||
|
|
|
@ -49,8 +49,11 @@ private slots:
|
|||
|
||||
void watchForCreation();
|
||||
void watchForDisappearance();
|
||||
void watchForDisappearanceUniqueConnection();
|
||||
void watchForOwnerChange();
|
||||
void modeChange();
|
||||
void disconnectedConnection();
|
||||
void setConnection();
|
||||
};
|
||||
|
||||
tst_QDBusServiceWatcher::tst_QDBusServiceWatcher()
|
||||
|
@ -155,6 +158,40 @@ void tst_QDBusServiceWatcher::watchForDisappearance()
|
|||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||
}
|
||||
|
||||
void tst_QDBusServiceWatcher::watchForDisappearanceUniqueConnection()
|
||||
{
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
QVERIFY(con.isConnected());
|
||||
|
||||
// second connection
|
||||
QString watchedName = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "session2").baseService();
|
||||
QVERIFY(!watchedName.isEmpty());
|
||||
|
||||
QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration);
|
||||
watcher.setObjectName("watcher for disappearance");
|
||||
|
||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
||||
QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
|
||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
|
||||
|
||||
// unregister it:
|
||||
QDBusConnection::disconnectFromBus("session2");
|
||||
|
||||
QTestEventLoop::instance().enterLoop(1);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(spyR.count(), 0);
|
||||
|
||||
QCOMPARE(spyU.count(), 1);
|
||||
QCOMPARE(spyU.at(0).at(0).toString(), watchedName);
|
||||
|
||||
QCOMPARE(spyO.count(), 1);
|
||||
QCOMPARE(spyO.at(0).at(0).toString(), watchedName);
|
||||
QCOMPARE(spyO.at(0).at(1).toString(), watchedName);
|
||||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||
}
|
||||
|
||||
void tst_QDBusServiceWatcher::watchForOwnerChange()
|
||||
{
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
|
@ -263,5 +300,72 @@ void tst_QDBusServiceWatcher::modeChange()
|
|||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||
}
|
||||
|
||||
void tst_QDBusServiceWatcher::disconnectedConnection()
|
||||
{
|
||||
QDBusConnection con("");
|
||||
QVERIFY(!con.isConnected());
|
||||
|
||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
|
||||
watcher.addWatchedService("com.example.somethingelse");
|
||||
watcher.addWatchedService("org.freedesktop.DBus");
|
||||
|
||||
watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
||||
watcher.setWatchMode(QDBusServiceWatcher::WatchForOwnerChange);
|
||||
|
||||
watcher.setWatchedServices(QStringList());
|
||||
}
|
||||
|
||||
void tst_QDBusServiceWatcher::setConnection()
|
||||
{
|
||||
// begin with a disconnected connection
|
||||
QDBusConnection con("");
|
||||
QVERIFY(!con.isConnected());
|
||||
|
||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
|
||||
|
||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(exitLoop()));
|
||||
|
||||
// move to the session bus
|
||||
con = QDBusConnection::sessionBus();
|
||||
QVERIFY(con.isConnected());
|
||||
watcher.setConnection(con);
|
||||
|
||||
// register a name
|
||||
QVERIFY(con.registerService(serviceName));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(1);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(spyR.count(), 1);
|
||||
QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
|
||||
QCOMPARE(spyU.count(), 0);
|
||||
|
||||
// is the system bus available?
|
||||
if (!QDBusConnection::systemBus().isConnected())
|
||||
return;
|
||||
|
||||
// connect to the system bus and ask to watch that base service
|
||||
QString watchedName = QDBusConnection::connectToBus(QDBusConnection::SystemBus, "system2").baseService();
|
||||
watcher.setWatchedServices(QStringList() << watchedName);
|
||||
watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
||||
|
||||
// move to the system bus
|
||||
watcher.setConnection(QDBusConnection::systemBus());
|
||||
spyR.clear();
|
||||
spyU.clear();
|
||||
|
||||
QDBusConnection::disconnectFromBus("system2");
|
||||
|
||||
QTestEventLoop::instance().enterLoop(1);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(spyR.count(), 0);
|
||||
|
||||
QCOMPARE(spyU.count(), 1);
|
||||
QCOMPARE(spyU.at(0).at(0).toString(), watchedName);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDBusServiceWatcher)
|
||||
#include "tst_qdbusservicewatcher.moc"
|
||||
|
|
Loading…
Reference in New Issue