Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/dbus/qdbusintegrator.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information ([email protected])
     4** All rights reserved.
     5** Contact: Nokia Corporation ([email protected])
    56**
    67** This file is part of the QtDBus module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you
     37** @nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7575    if (th && !th->objectName().isEmpty())
    7676        dbg.nospace() << ", name=" << th->objectName();
    77     dbg.nospace() << ")";
     77    dbg.nospace() << ;
    7878    return dbg.space();
    7979}
     
    9191    else
    9292        dbg.nospace() << conn->thread();
    93     dbg.nospace() << ")";
     93    dbg.nospace() << ;
    9494    return dbg.space();
    9595}
     
    391391} // extern "C"
    392392
    393 static QByteArray buildMatchRule(const QString &service, const QString & /*owner*/,
     393static QByteArray buildMatchRule(const QString &service,
    394394                                 const QString &objectPath, const QString &interface,
    395                                  const QString &member, const QString & /*signature*/)
     395                                 const QString &member, const QString & /*signature*/)
    396396{
    397397    QString result = QLatin1String("type='signal',");
     
    406406    if (!member.isEmpty())
    407407        result += keyValue.arg(QLatin1String("member"), member);
     408
     409
     410
     411
     412
     413
     414
     415
    408416
    409417    result.chop(1);             // remove ending comma
     
    492500    // object not found
    493501    return 0;
     502
     503
     504
     505
     506
    494507}
    495508
     
    566579    QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd();
    567580    for ( ; it != end; ++it)
    568         huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1String("/") + it->name);
     581        huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1) + it->name);
    569582
    570583    if (needle == haystack.obj) {
     
    921934      rootNode(QString(QLatin1Char('/')))
    922935{
    923     static const bool threads = qDBusInitThreads();
    924     static const int debugging = ::isDebugging = qgetenv("QDBUS_DEBUG").toInt();
     936    static const bool threads = q_dbus_threads_init_default();
     937    static const int debugging = qgetenv("QDBUS_DEBUG").toInt();
     938    ::isDebugging = debugging;
    925939    Q_UNUSED(threads)
     940
    926941
    927942#ifdef QDBUS_THREAD_DEBUG
     
    933948
    934949    rootNode.flags = 0;
    935 
    936     connect(this, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
    937             this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
    938950}
    939951
     
    11031115
    11041116    for (int i = 0; i < pendingWatches.size(); ++i)
    1105         if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_READABLE))
     1117        if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_ABLE))
    11061118            qDebug("OUT OF MEM");
    11071119}
     
    11261138                                         const QVariantList &args)
    11271139{
    1128     int mciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
    1129     Q_ASSERT(mciid != -1);
    1130 
    1131     QMetaClassInfo mci = mo->classInfo(mciid);
    1132     Q_ASSERT(mci.value());
    1133     const char *interface = mci.value();
     1140    QString interface = qDBusInterfaceFromMetaObject(mo);
    11341141
    11351142    QMetaMethod mm = mo->method(signalId);
     
    11471154
    11481155    QDBusReadLocker locker(RelaySignalAction, this);
    1149     QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), QLatin1String(interface),
     1156    QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), ,
    11501157                                                      QLatin1String(memberName));
     1158
    11511159    message.setArguments(args);
    1152     DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);
     1160    QDBusError error;
     1161    DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error);
    11531162    if (!msg) {
    1154         qWarning("QDBusConnection: Could not emit signal %s.%s", interface, memberName.constData());
     1163        qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(),
     1164                 qPrintable(error.message()));
     1165        lastError = error;
    11551166        return;
    11561167    }
     
    11661177                                                    const QString &oldOwner, const QString &newOwner)
    11671178{
    1168     if (oldOwner == baseService)
    1169         unregisterService(name);
    1170     if (newOwner == baseService)
    1171         registerService(name);
    1172 
     1179    Q_UNUSED(oldOwner);
    11731180    QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this);
    1174     QMutableHashIterator<QString, SignalHook> it(signalHooks);
    1175     it.toFront();
    1176     while (it.hasNext())
    1177         if (it.next().value().service == name)
    1178             it.value().owner = newOwner;
     1181    WatchedServicesHash::Iterator it = watchedServices.find(name);
     1182    if (it == watchedServices.end())
     1183        return;
     1184    if (oldOwner != it->owner)
     1185        qWarning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'",
     1186                 qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner));
     1187
     1188    qDBusDebug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner;
     1189    it->owner = newOwner;
    11791190}
    11801191
     
    11941205
    11951206bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
    1196                                          const QString &service, const QString &owner,
     1207                                         const QString &service,
    11971208                                         const QString &path, const QString &interface, const QString &name,
     1209
    11981210                                         QObject *receiver, const char *signal, int minMIdx,
    11991211                                         bool buildSignature)
     
    12121224
    12131225    hook.service = service;
    1214     hook.owner = owner; // we don't care if the service has an owner yet
    12151226    hook.path = path;
    12161227    hook.obj = receiver;
     1228
    12171229
    12181230    // build the D-Bus signal name and signature
     
    12361248    }
    12371249
    1238     hook.matchRule = buildMatchRule(service, owner, path, interface, mname, hook.signature);
     1250    hook.matchRule = buildMatchRule(service, , hook.signature);
    12391251    return true;                // connect to this signal
    12401252}
     
    13651377    if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots)) {
    13661378        bool interfaceFound = true;
    1367         if (!msg.interface().isEmpty()) {
    1368             // check if the interface name matches anything in the class hierarchy
    1369             const QMetaObject *mo = node.obj->metaObject();
    1370             for ( ; !interfaceFound && mo != &QObject::staticMetaObject; mo = mo->superClass())
    1371                 interfaceFound = msg.interface() == qDBusInterfaceFromMetaObject(mo);
    1372         }
     1379        if (!msg.interface().isEmpty())
     1380            interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
    13731381
    13741382        if (interfaceFound) {
     
    14831491    for ( ; it != end && it.key() == key; ++it) {
    14841492        const SignalHook &hook = it.value();
    1485         if (!hook.owner.isEmpty() && hook.owner != msg.service())
    1486             continue;
     1493        if (!hook.service.isEmpty()) {
     1494            const QString owner =
     1495                    shouldWatchService(hook.service) ?
     1496                    watchedServices.value(hook.service).owner :
     1497                    hook.service;
     1498            if (owner != msg.service())
     1499                continue;
     1500        }
    14871501        if (!hook.path.isEmpty() && hook.path != msg.path())
    14881502            continue;
     
    14911505        if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
    14921506            continue;
     1507
     1508
     1509
     1510
     1511
     1512
     1513
     1514
     1515
     1516
     1517
     1518
     1519
     1520
     1521
     1522
     1523
     1524
    14931525
    14941526        activateSignal(hook, msg);
     
    16251657        baseService = QString::fromUtf8(service);
    16261658    } else {
    1627         qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service");
    1628     }
     1659        qWarning("QDBusConnectionPrivate::setConnection: Unable to get base service");
     1660    }
     1661
     1662    QString busService = QLatin1String(DBUS_SERVICE_DBUS);
     1663    WatchedServicesHash::mapped_type &bus = watchedServices[busService];
     1664    bus.refcount = 1;
     1665    bus.owner = getNameOwnerNoCache(busService);
     1666    connectSignal(busService, QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(),
     1667                  this, SLOT(registerService(QString)));
     1668    connectSignal(busService, QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(),
     1669                  this, SLOT(unregisterService(QString)));
     1670
    16291671
    16301672    q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);
     
    17081750                                // through the d_ptr->localReply link
    17091751
    1710     DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);
     1752    QDBusError error;
     1753    DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error);
    17111754    if (!msg) {
    17121755        if (message.type() == QDBusMessage::MethodCallMessage)
    1713             qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
     1756            qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
    17141757                     qPrintable(message.service()), qPrintable(message.path()),
    1715                      qPrintable(message.interface()), qPrintable(message.member()));
     1758                     qPrintable(message.interface()), qPrintable(message.member()),
     1759                     qPrintable(error.message()));
    17161760        else if (message.type() == QDBusMessage::SignalMessage)
    1717             qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\"",
     1761            qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\"",
    17181762                     qPrintable(message.path()), qPrintable(message.interface()),
    1719                      qPrintable(message.member()));
     1763                     qPrintable(message.member()),
     1764                     qPrintable(error.message()));
    17201765        else
    1721             qWarning("QDBusConnection: error: could not send %s message to service \"%s\"",
     1766            qWarning("QDBusConnection: error: could not send %s message to service \"%s\"",
    17221767                     message.type() == QDBusMessage::ReplyMessage ? "reply" :
    17231768                     message.type() == QDBusMessage::ErrorMessage ? "error" :
    1724                      "invalid", qPrintable(message.service()));
     1769                     "invalid", qPrintable(message.service()),
     1770                     qPrintable(error.message()));
     1771        lastError = error;
    17251772        return 0;
    17261773    }
     
    17491796
    17501797    if (!QCoreApplication::instance() || sendMode == QDBus::Block) {
    1751         DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);
     1798        QDBusError err;
     1799        DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &err);
    17521800        if (!msg) {
    1753             qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
     1801            qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
    17541802                     qPrintable(message.service()), qPrintable(message.path()),
    1755                      qPrintable(message.interface()), qPrintable(message.member()));
    1756             return QDBusMessage();
     1803                     qPrintable(message.interface()), qPrintable(message.member()),
     1804                     qPrintable(err.message()));
     1805            lastError = err;
     1806            return QDBusMessage::createError(err);
    17571807        }
    17581808
     
    17641814
    17651815        if (!!error) {
    1766             QDBusError qe = error;
    1767             lastError = qe;
    1768             return QDBusMessage::createError(qe);
     1816            lastError = err = error;
     1817            return QDBusMessage::createError(err);
    17691818        }
    17701819
     
    17761825    } else { // use the event loop
    17771826        QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout);
    1778         if (!pcall)
    1779             return QDBusMessage();
    1780 
    1781         pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
    1782         QEventLoop loop;
    1783         loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit()));
    1784         loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit()));
    1785 
    1786         // enter the event loop and wait for a reply
    1787         loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
     1827        Q_ASSERT(pcall);
     1828
     1829        if (pcall->replyMessage.type() != QDBusMessage::InvalidMessage) {
     1830            pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
     1831            QEventLoop loop;
     1832            loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit()));
     1833            loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit()));
     1834
     1835            // enter the event loop and wait for a reply
     1836            loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
     1837        }
    17881838
    17891839        QDBusMessage reply = pcall->replyMessage;
     
    18411891    }
    18421892
    1843     DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);
    1844     if (!msg) {
    1845         qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
    1846                  qPrintable(message.service()), qPrintable(message.path()),
    1847                  qPrintable(message.interface()), qPrintable(message.member()));
    1848         return 0;
    1849     }
    1850 
    18511893    checkThread();
    1852     qDBusDebug() << QThread::currentThread() << "sending message (async):" << message;
    1853     DBusPendingCall *pending = 0;
    18541894    QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate;
    18551895    pcall->sentMessage = message;
    18561896    pcall->ref = 0;
     1897
     1898
     1899
     1900
     1901
     1902
     1903
     1904
     1905
     1906
     1907
     1908
     1909
     1910
     1911
    18571912
    18581913    QDBusDispatchLocker locker(SendWithReplyAsyncAction, this);
     
    18681923        } else {
    18691924            // we're probably disconnected at this point
    1870             lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server"));
     1925            lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server"));
    18711926        }
    18721927    } else {
    1873         lastError = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory"));
     1928        lastError = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory"));
    18741929    }
    18751930
    18761931    q_dbus_message_unref(msg);
    1877     pcall->replyMessage = QDBusMessage::createError(lastError);
     1932    pcall->replyMessage = QDBusMessage::createError(rror);
    18781933    return pcall;
    18791934}
     
    18841939{
    18851940    QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout);
    1886     if (!pcall)
    1887         return 0;
     1941    Q_ASSERT(pcall);
    18881942
    18891943    // has it already finished (dispatched locally)?
     
    19261980}
    19271981
     1982
     1983
     1984
     1985
     1986
     1987
     1988
     1989
     1990
     1991
     1992
     1993
     1994
     1995
     1996
     1997
     1998
     1999
     2000
     2001
     2002
     2003
     2004
     2005
     2006
     2007
     2008
     2009
     2010
     2011
     2012
     2013
     2014
     2015
     2016
    19282017void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook)
    19292018{
    19302019    signalHooks.insertMulti(key, hook);
    19312020    connect(hook.obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)),
    1932             Qt::DirectConnection);
     2021            Qt::);
    19332022
    19342023    MatchRefCountHash::iterator it = matchRefCounts.find(hook.matchRule);
     
    19532042                     qPrintable(qerror.name()), qPrintable(qerror.message()));
    19542043            Q_ASSERT(false);
    1955         }
    1956     }
     2044        } else {
     2045            // Successfully connected the signal
     2046            // Do we need to watch for this name?
     2047            if (shouldWatchService(hook.service)) {
     2048                WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
     2049                if (data.refcount) {
     2050                    // already watching
     2051                    ++data.refcount;
     2052                } else {
     2053                    // we need to watch for this service changing
     2054                    QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS);
     2055                    connectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS),
     2056                                  QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
     2057                                  this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
     2058                    data.owner = getNameOwnerNoCache(hook.service);
     2059                    qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
     2060                            << data.owner << ")";
     2061                }
     2062            }
     2063        }
     2064    }
     2065}
     2066
     2067bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
     2068                                              const QString &path, const QString &interface, const QString &name,
     2069                                              const QStringList &argumentMatch, const QString &signature,
     2070                                              QObject *receiver, const char *slot)
     2071{
     2072    // check the slot
     2073    QDBusConnectionPrivate::SignalHook hook;
     2074    QString key;
     2075    QString name2 = name;
     2076    if (name2.isNull())
     2077        name2.detach();
     2078
     2079    hook.signature = signature;
     2080    if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
     2081        return false;           // don't disconnect
     2082
     2083    // avoid duplicating:
     2084    QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key);
     2085    QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end();
     2086    for ( ; it != end && it.key() == key; ++it) {
     2087        const QDBusConnectionPrivate::SignalHook &entry = it.value();
     2088        if (entry.service == hook.service &&
     2089            entry.path == hook.path &&
     2090            entry.signature == hook.signature &&
     2091            entry.obj == hook.obj &&
     2092            entry.midx == hook.midx) {
     2093            // no need to compare the parameters if it's the same slot
     2094            disconnectSignal(it);
     2095            return true;        // it was there
     2096        }
     2097    }
     2098
     2099    // the slot was not found
     2100    return false;
    19572101}
    19582102
     
    19612105{
    19622106    const SignalHook &hook = it.value();
     2107
     2108
     2109
     2110
     2111
     2112
     2113
     2114
     2115
     2116
     2117
     2118
     2119
    19632120
    19642121    bool erase = false;