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/qdbusabstractinterface.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    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 have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545#include "qdbusargument.h"
    4646#include "qdbuspendingcall.h"
     47#include "qdbusmessage_p.h"
    4748#include "qdbusmetaobject_p.h"
    4849#include "qdbusmetatype_p.h"
     
    5253
    5354QT_BEGIN_NAMESPACE
     55
     56static QDBusError checkIfValid(const QString &service, const QString &path,
     57                               const QString &interface, bool isDynamic)
     58{
     59    // We should be throwing exceptions here... oh well
     60    QDBusError error;
     61
     62    // dynamic interfaces (QDBusInterface) can have empty interfaces, but not service and object paths
     63    // non-dynamic is the opposite: service and object paths can be empty, but not the interface
     64    if (!isDynamic) {
     65        // use assertion here because this should never happen, at all
     66        Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty");
     67    }
     68    if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
     69        return error;
     70    if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
     71        return error;
     72    if (!QDBusUtil::checkInterfaceName(interface, QDBusUtil::EmptyAllowed, &error))
     73        return error;
     74
     75    // no error
     76    return QDBusError();
     77}
    5478
    5579QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv,
     
    5882                                                             const QDBusConnection& con,
    5983                                                             bool isDynamic)
    60     : connection(con), service(serv), path(p), interface(iface), isValid(true)
    61 {
    62     if (isDynamic) {
    63         // QDBusInterface: service and object path can't be empty, but interface can
    64 #if 0
    65         Q_ASSERT_X(QDBusUtil::isValidBusName(service),
    66                    "QDBusInterface::QDBusInterface", "Invalid service name");
    67         Q_ASSERT_X(QDBusUtil::isValidObjectPath(path),
    68                    "QDBusInterface::QDBusInterface", "Invalid object path given");
    69         Q_ASSERT_X(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface),
    70                    "QDBusInterface::QDBusInterface", "Invalid interface name");
    71 #else
    72         if (!QDBusUtil::isValidBusName(service)) {
    73             lastError = QDBusError(QDBusError::Disconnected,
    74                                    QLatin1String("Invalid service name"));
    75             isValid = false;
    76         } else if (!QDBusUtil::isValidObjectPath(path)) {
    77             lastError = QDBusError(QDBusError::Disconnected,
    78                                    QLatin1String("Invalid object name given"));
    79             isValid = false;
    80         } else if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) {
    81             lastError = QDBusError(QDBusError::Disconnected,
    82                                    QLatin1String("Invalid interface name"));
    83             isValid = false;
    84         }
    85 #endif
    86     } else {
    87         // all others: service and path can be empty here, but interface can't
    88 #if 0
    89         Q_ASSERT_X(service.isEmpty() || QDBusUtil::isValidBusName(service),
    90                    "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid service name");
    91         Q_ASSERT_X(path.isEmpty() || QDBusUtil::isValidObjectPath(path),
    92                    "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid object path given");
    93         Q_ASSERT_X(QDBusUtil::isValidInterfaceName(interface),
    94                    "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid interface class!");
    95 #else
    96         if (!service.isEmpty() && !QDBusUtil::isValidBusName(service)) {
    97             lastError = QDBusError(QDBusError::Disconnected,
    98                                    QLatin1String("Invalid service name"));
    99             isValid = false;
    100         } else if (!path.isEmpty() && !QDBusUtil::isValidObjectPath(path)) {
    101             lastError = QDBusError(QDBusError::Disconnected,
    102                                    QLatin1String("Invalid object path given"));
    103             isValid = false;
    104         } else if (!QDBusUtil::isValidInterfaceName(interface)) {
    105             lastError = QDBusError(QDBusError::Disconnected,
    106                                    QLatin1String("Invalid interface class"));
    107             isValid = false;
    108         }
    109 #endif
    110     }
    111 
     84    : connection(con), service(serv), path(p), interface(iface),
     85      lastError(checkIfValid(serv, p, iface, isDynamic)),
     86      isValid(!lastError.isValid())
     87{
    11288    if (!isValid)
    11389        return;
     
    11692        lastError = QDBusError(QDBusError::Disconnected,
    11793                               QLatin1String("Not connected to D-Bus server"));
    118         isValid = false;
    11994    } else if (!service.isEmpty()) {
    12095        currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner
    12196        if (currentOwner.isEmpty()) {
    122             isValid = false;
    12397            lastError = connectionPrivate()->lastError;
    12498        }
     
    126100}
    127101
    128 QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const
    129 {
    130     if (!connection.isConnected())    // not connected
    131         return QVariant();
     102bool QDBusAbstractInterfacePrivate::canMakeCalls() const
     103{
     104    // recheck only if we have a wildcard (i.e. empty) service or path
     105    // if any are empty, set the error message according to QDBusUtil
     106    if (service.isEmpty())
     107        return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError);
     108    if (path.isEmpty())
     109        return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError);
     110    return true;
     111}
     112
     113void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &where) const
     114{
     115    if (!isValid || !canMakeCalls()) {   // can't make calls
     116        where.clear();
     117        return;
     118    }
    132119
    133120    // is this metatype registered?
    134     int mid;
    135     const char *expectedSignature;
    136     if (mp.type() == QVariant::LastType) {
    137         // We're asking to read a QVariant
    138         mid = qMetaTypeId<QDBusVariant>();
    139         expectedSignature = "v";
    140     } else {
    141         mid = QMetaType::type(mp.typeName());
    142         expectedSignature = QDBusMetaType::typeToSignature(mid);
     121    const char *expectedSignature = "";
     122    if (mp.type() != 0xff) {
     123        expectedSignature = QDBusMetaType::typeToSignature(where.userType());
    143124        if (expectedSignature == 0) {
    144125            qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be "
    145126                     "used to read property %s.%s",
    146127                     mp.typeName(), qPrintable(interface), mp.name());
    147             return QVariant();
     128            lastError = QDBusError(QDBusError::Failed,
     129                                   QString::fromLatin1("Unregistered type %1 cannot be handled")
     130                                   .arg(QLatin1String(mp.typeName())));
     131            where.clear();
     132            return;
    148133        }
    149134    }
     
    153138                                                      QLatin1String(DBUS_INTERFACE_PROPERTIES),
    154139                                                      QLatin1String("Get"));
     140    QDBusMessagePrivate::setParametersValidated(msg, true);
    155141    msg << interface << QString::fromUtf8(mp.name());
    156142    QDBusMessage reply = connection.call(msg, QDBus::Block);
     
    158144    if (reply.type() != QDBusMessage::ReplyMessage) {
    159145        lastError = reply;
    160         return QVariant();
     146        where.clear();
     147        return;
    161148    }
    162149    if (reply.signature() != QLatin1String("v")) {
     
    164151                                       DBUS_INTERFACE_PROPERTIES);
    165152        lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature()));
    166         return QVariant();
     153        where.clear();
     154        return;
    167155    }
    168156
     
    171159    QVariant value = qvariant_cast<QDBusVariant>(reply.arguments().at(0)).variant();
    172160
    173     if (value.userType() == mid)
    174         return value;       // simple match
     161    if (value.userType() == where.userType() || mp.type() == 0xff
     162        || (expectedSignature[0] == 'v' && expectedSignature[1] == '\0')) {
     163        // simple match
     164        where = value;
     165        return;
     166    }
    175167
    176168    if (value.userType() == qMetaTypeId<QDBusArgument>()) {
     
    180172        foundSignature = arg.currentSignature().toLatin1();
    181173        if (foundSignature == expectedSignature) {
    182             void *null = 0;
    183             QVariant result(mid, null);
    184             QDBusMetaType::demarshall(arg, mid, result.data());
    185 
    186             if (mp.type() == QVariant::LastType)
    187                 // special case: QVariant
    188                 return qvariant_cast<QDBusVariant>(result).variant();
    189             return result;
     174            // signatures match, we can demarshall
     175            QDBusMetaType::demarshall(arg, where.userType(), where.data());
     176            return;
    190177        }
    191178    } else {
     
    204191                                      QString::fromLatin1(mp.typeName()),
    205192                                      QString::fromLatin1(expectedSignature)));
    206     return QVariant();
    207 }
    208 
    209 void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value)
    210 {
    211     if (!connection.isConnected())    // not connected
    212         return;
     193    where.clear();
     194    return;
     195}
     196
     197bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value)
     198{
     199    if (!isValid || !canMakeCalls())    // can't make calls
     200        return false;
    213201
    214202    // send the value
     
    216204                                                QLatin1String(DBUS_INTERFACE_PROPERTIES),
    217205                                                QLatin1String("Set"));
     206    QDBusMessagePrivate::setParametersValidated(msg, true);
    218207    msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value));
    219208    QDBusMessage reply = connection.call(msg, QDBus::Block);
    220209
    221     if (reply.type() != QDBusMessage::ReplyMessage)
     210    if (reply.type() != QDBusMessage::ReplyMessage) {
    222211        lastError = reply;
     212        return false;
     213    }
     214    return true;
    223215}
    224216
     
    231223    if (name == service) {
    232224        currentOwner = newOwner;
    233         isValid = !newOwner.isEmpty();
    234     }
    235 }
    236 
     225    }
     226}
     227
     228QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent)
     229    : QObject(d, parent)
     230{
     231}
     232
     233int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
     234{
     235    int saved_id = _id;
     236    _id = QObject::qt_metacall(_c, _id, _a);
     237    if (_id < 0)
     238        return _id;
     239
     240    if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) {
     241        QMetaProperty mp = metaObject()->property(saved_id);
     242        int &status = *reinterpret_cast<int *>(_a[2]);
     243        QVariant &variant = *reinterpret_cast<QVariant *>(_a[1]);
     244
     245        if (_c == QMetaObject::WriteProperty) {
     246            status = d_func()->setProperty(mp, variant) ? 1 : 0;
     247        } else {
     248            d_func()->property(mp, variant);
     249            status = variant.isValid() ? 1 : 0;
     250        }
     251        _id = -1;
     252    }
     253    return _id;
     254}
    237255
    238256/*!
     
    259277*/
    260278QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent)
    261     : QObject(d, parent)
     279    : QDBusAbstractInterfaceBase(d, parent)
    262280{
    263281    // keep track of the service owner
    264     if (d_func()->isValid)
    265         QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
    266                          this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
     282    if (d.isValid &&
     283        d.connection.isConnected()
     284        && !d.service.isEmpty()
     285        && !d.service.startsWith(QLatin1Char(':')))
     286        d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service
     287                                     QString(), // path
     288                                     QLatin1String(DBUS_INTERFACE_DBUS), // interface
     289                                     QLatin1String("NameOwnerChanged"),
     290                                     QStringList() << d.service,
     291                                     QString(), // signature
     292                                     this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
    267293}
    268294
     
    275301                                               const char *interface, const QDBusConnection &con,
    276302                                               QObject *parent)
    277     : QObject(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface),
     303    : QDBusAbstractInterfaceBase(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface),
    278304                                                 con, false), parent)
    279305{
    280306    // keep track of the service owner
    281     if (d_func()->connection.isConnected())
    282         QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
    283                          this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
     307    if (d_func()->isValid &&
     308        d_func()->connection.isConnected()
     309        && !service.isEmpty()
     310        && !service.startsWith(QLatin1Char(':')))
     311        d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service
     312                                     QString(), // path
     313                                     QLatin1String(DBUS_INTERFACE_DBUS), // interface
     314                                     QLatin1String("NameOwnerChanged"),
     315                                     QStringList() << service,
     316                                     QString(), //signature
     317                                     this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
    284318}
    285319
     
    301335bool QDBusAbstractInterface::isValid() const
    302336{
    303     return d_func()->isValid;
     337    return !d_func()->currentOwner.isEmpty();
    304338}
    305339
     
    367401{
    368402    Q_D(QDBusAbstractInterface);
     403
     404    if (!d->isValid || !d->canMakeCalls())
     405        return QDBusMessage::createError(d->lastError);
    369406
    370407    QString m = method;
     
    398435//    qDebug() << "QDBusAbstractInterface" << "Service" << service() << "Path:" << path();
    399436    QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m);
     437    QDBusMessagePrivate::setParametersValidated(msg, true);
    400438    msg.setArguments(args);
    401439
     
    426464    Q_D(QDBusAbstractInterface);
    427465
     466    if (!d->isValid || !d->canMakeCalls())
     467        return QDBusPendingCall::fromError(d->lastError);
     468
    428469    QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method);
     470    QDBusMessagePrivate::setParametersValidated(msg, true);
    429471    msg.setArguments(args);
    430472    return d->connection.asyncCall(msg);
     
    441483    This function returns true if the queueing succeeds. It does
    442484    not indicate that the executed call succeeded. If it fails,
    443     the \a errorMethod is called.
     485    the \a errorMethod is called. If the queueing failed, this
     486    function returns false and no slot will be called.
    444487 
    445488    The \a returnMethod must have as its parameters the types returned
     
    454497                                              const QList<QVariant> &args,
    455498                                              QObject *receiver,
    456                                               const char *returnMethod,
     499                                              const char *returnMethod,
    457500                                              const char *errorMethod)
    458501{
    459502    Q_D(QDBusAbstractInterface);
    460503
     504    if (!d->isValid || !d->canMakeCalls())
     505        return false;
     506
    461507    QDBusMessage msg = QDBusMessage::createMethodCall(service(),
    462                                                       path(),
    463                                                       interface(),
    464                                                       method);
     508                                                      path(),
     509                                                      interface(),
     510                                                      method);
     511    QDBusMessagePrivate::setParametersValidated(msg, true);
    465512    msg.setArguments(args);
    466513
    467514    d->lastError = 0;
    468515    return d->connection.callWithCallback(msg,
    469                                           receiver,
    470                                           returnMethod,
    471                                           errorMethod);
     516                                          receiver,
     517                                          returnMethod,
     518                                          errorMethod);
    472519}
    473520
     
    493540                                              const QList<QVariant> &args,
    494541                                              QObject *receiver,
    495                                               const char *slot)
     542                                              const char *slot)
    496543{
    497544    return callWithCallback(method, args, receiver, slot, 0);
     
    504551void QDBusAbstractInterface::connectNotify(const char *signal)
    505552{
     553    // someone connecting to one of our signals
     554    Q_D(QDBusAbstractInterface);
     555    if (!d->isValid)
     556        return;
     557
    506558    // we end up recursing here, so optimise away
    507559    if (qstrcmp(signal + 1, "destroyed(QObject*)") == 0)
    508560        return;
    509561
    510     // someone connecting to one of our signals
     562    QDBusConnectionPrivate *conn = d->connectionPrivate();
     563    if (conn) {
     564        conn->connectRelay(d->service, d->path, d->interface,
     565                           this, signal);
     566    }
     567}
     568
     569/*!
     570    \internal
     571    Catch signal disconnections.
     572*/
     573void QDBusAbstractInterface::disconnectNotify(const char *signal)
     574{
     575    // someone disconnecting from one of our signals
    511576    Q_D(QDBusAbstractInterface);
     577    if (!d->isValid)
     578        return;
    512579
    513580    QDBusConnectionPrivate *conn = d->connectionPrivate();
    514581    if (conn)
    515         conn->connectRelay(d->service, d->currentOwner, d->path, d->interface,
    516                            this, signal);
    517 }
    518 
    519 /*!
    520     \internal
    521     Catch signal disconnections.
    522 */
    523 void QDBusAbstractInterface::disconnectNotify(const char *signal)
    524 {
    525     // someone disconnecting from one of our signals
    526     Q_D(QDBusAbstractInterface);
    527 
    528     QDBusConnectionPrivate *conn = d->connectionPrivate();
    529     if (conn)
    530         conn->disconnectRelay(d->service, d->currentOwner, d->path, d->interface,
     582        conn->disconnectRelay(d->service, d->path, d->interface,
    531583                              this, signal);
    532584}
     
    541593    // we're only called from generated code anyways
    542594
    543     int idx = metaObject()->indexOfProperty(propname);
    544     if (idx != -1)
    545         return d_func()->property(metaObject()->property(idx));
    546     qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname);
    547     return QVariant();          // error
     595    return property(propname);
    548596}
    549597
     
    554602void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value)
    555603{
    556     Q_D(QDBusAbstractInterface);
    557 
    558     // assume this property exists and is writeable
    559     // we're only called from generated code anyways
    560 
    561     int idx = metaObject()->indexOfProperty(propname);
    562     if (idx != -1)
    563         d->setProperty(metaObject()->property(idx), value);
    564     else
    565         qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname);
     604    setProperty(propname, value);
    566605}
    567606
Note: See TracChangeset for help on using the changeset viewer.